前些天,根据vs2010之MFC入门到精通文档,跟着写了下一到十六节的一个程序。
下面是我在写的过程中觉得需要自己注意的:
一、MFC消息映射机制
一个消息与消息处理函数一一对应的消息映射表,以及消息处理函数的声明和实现等。
消息映射表:
如下所示:
BEGIN_MESSAGE_MAP(CAdditionDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_ADD_BUTTON, &CAdditionDlg::OnBnClickedAddButton) ON_BN_CLICKED(IDC_INSTRUCT_BUTTON, &CAdditionDlg::OnBnClickedInstructButton) END_MESSAGE_MAP()
添加消息处理函数包括三个步骤:
1、在类定义中加入消息处理函数的函数声明,注意要以afx_msg打头。
// 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnBnClickedAddButton();
BEGIN_MESSAGE_MAP(CAdditionDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_ADD_BUTTON, &CAdditionDlg::OnBnClickedAddButton) ON_BN_CLICKED(IDC_INSTRUCT_BUTTON, &CAdditionDlg::OnBnClickedInstructButton) END_MESSAGE_MAP()
void CAdditionDlg::OnBnClickedAddButton()
二、添加控件变量(这里控件为Edit control)
1.在编辑框上点右键,在右键菜单中选择“Add Variable”。弹出添加成员变量的向导对话框。
2.我们想为其添加值变量而不是控件变量,所以对话框中“Category”下的组合框中选择Value。
3.“Variable type”下的组合框此时默认选中的是“CString”,CString是字符串类,显然不能进行加法运算。我们可以选择double、float、int等。这里我们选择double,即编辑框关联一个double类型的变量。
4.在“Variablename”中写入自定义的变量名。鸡啄米为其取名m_editSummand。
在程序运行界面中,用户往往会改变控件的属性,例如,在编辑框中输入字符串,或者改变组合框的选中项,又或者改变复选框的选中状态等。控件的属性改变后MFC会相应修改控件关联变量的值。这种同步的改变是通过MFC为对话框类自动生成的成员函数DoDataExchange()来实现的,这也叫做对话框的数据交换和检验机制。
添加了控件变量后DoDataExchange中变化为:
void CAdditionDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); //处理控件IDC_SUMMAND_EDIT与m_editSummand之间的数据交换 DDX_Text(pDX, IDC_SUMMAND_EDIT, m_editSummand); DDX_Text(pDX, IDC_ADDEND_EDIT, m_editAddend); DDX_Text(pDX, IDC_SUM_EDIT, m_editSum); }
nge()。
CDialogEx::UpdateData()函数的原型为:
BOOL UpdateData(BOOL bSaveAndValidate = TRUE);
参数:bSaveAndValidate用于指示数据传输的方向,TRUE表示从控件传给变量,FALSE表示从变量传给数据。默认值是TRUE,即从控件传给变量。
返回值:CDialogEx::UpdateData()函数的返回值表示操作是否成功,成功则返回TRUE,否则返回FALSE。
三、改变控件TAB顺序
在菜单栏中格式下选择。
四、模态对话框与非模态对话框
1、模态对话框
先建立一个Dialog,并生成一个dialog类。
/*INT_PTR nRes; CTipDlg tipDlg; nRes = tipDlg.DoModal(); if (IDCANCEL == nRes) { return; }*/
同样建立一个Dialog,并生成一个dialog类。
//private: // CTipDlg *m_pTipDlg;
CAdditionDlg::CAdditionDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CAdditionDlg::IDD, pParent) , m_editSummand(0) , m_editAddend(0) , m_editSum(0) /*, m_pTipDlg(NULL)*/在消息处理函数中实现:
/*if(NULL == m_pTipDlg) { m_pTipDlg = new CTipDlg(); m_pTipDlg->Create(IDD_TIP_DIALOG, this); } m_pTipDlg->ShowWindow(SW_SHOW);*/
五、属性页对话框
属性页对话框,用到的类主要有两个:CPropertyPage类和CPropertySheet类。
CPropertyPage类提供了一些消息处理函数,来响应属性页对话框的各种消息。我们重载这些消息处理函数,就可以自定义对属性页对话框操作的处理。
可重载的消息处理函数包括:
OnApply:处理属性页的“Apply”按钮被单击的消息
OnCancel:处理属性页的“Cancel”按钮被单击的消息
OnKillActive:处理属性页当前活动状态被切换的消息,常用于数据验证
OnOK:处理属性页的“OK”按钮、“Apply”按钮或者“Close”按钮被单击的消息
OnQueryCancel:处理属性页的“Cancel”按钮被单击前发出的消息
OnReset:处理属性页的“Reset”按钮被单击的消息
OnSetActive:处理属性页被切换为当前活动页的消息
OnWizardBack:处理属性页的“Next”按钮被单击的消息,仅在向导对话框中有效
OnWizardFinish:处理属性页的“Finish”按钮被单击的消息,仅在向导对话框中有效
OnWizardNext:处理属性页的“下一步”按钮被单击的消息,仅在向导对话框中有效
2、CPropertySheet类继承自CWnd类,它是属性表类,负责加载、打开或删除属性页,并可以在属性页对话框中切换属性页,它跟对话框类似,也有模态和非模态两种。
参数dwFlags:
设置向导按钮的外观和功能属性。可以是以下值的组合:
PSWIZB_BACK 启用“Back”按钮,如果不包含此值则禁用“Back”按钮。
PSWIZB_NEXT 启用“Next”按钮,如果不包含此值则禁用“Next”按钮。
PSWIZB_FINISH 启用“Finish”按钮。
PSWIZB_DISABLEDFINISH 显示禁用的“Finish”按钮。
参数nButton:
要模拟按下的按钮,它可以是下列值之一:
PSBTN_BACK 选择“Back”按钮。
PSBTN_NEXT 选择“Next”按钮。
PSBTN_FINISH 选择“Finish”按钮。
PSBTN_OK 选择“OK”按钮。
PSBTN_APPLYNOW 选择“Apply”按钮。
PSBTN_CANCEL 选择“Cancel”按钮。
PSBTN_HELP 选择“帮助”按钮。
3、创建属性页对话框资源
在“Resource View”的Dialog”节点上点右键,然后在右键菜单中选择“Insert Dialog”创建第一个对话框模板,对话框的ID属性设置为IDD_SUMMAND_PAGE,Caption属性改为“被加数页”,Style属性在下拉列表中选择“Child”,Border属性在下拉列表中选择“Thin”。
这里要注意Style属性选择“Child”。
4、创建属性页类
在“Class name”编辑框中输入类名“CSummandPage”,与之前不同的是,因为属性页类都应继承于CPropertyPage类,所以要修改下面“Base class”的选项,在下拉列表中选择“CPropertyPage”。
因为是第一个属性页,所以它应该有一个“下一步”按钮,CPropertyPage类的可重载函数中,OnSetActive函数用于处理属性页被切换为当前活动页的消息,所以我们可以在OnSetActive函数中进行相关设置。
在类视图下,选属性下的重载。
//BOOL CSummandPage::OnSetActive() //{ // // TODO: 在此添加专用代码和/或调用基类 // // CPropertySheet* psheet = (CPropertySheet*) GetParent(); // // psheet->SetWizardButtons(PSWIZB_NEXT); // // return CPropertyPage::OnSetActive(); //}
//BOOL CAddPage::OnSetActive() //{ // // TODO: 在此添加专用代码和/或调用基类 // // CPropertySheet* psheet = (CPropertySheet*) GetParent(); // // psheet->SetFinishText(_T("完成")); // // return CPropertyPage::OnSetActive(); //} // // //BOOL CAddPage::OnWizardFinish() //{ // // TODO: 在此添加专用代码和/或调用基类 // // MessageBox(_T("使用说明向导已阅读完!")); // // return CPropertyPage::OnWizardFinish(); //}
在SolutionExplorer视图中的根节点“Addition”上点右键,在右键菜单中选择Add->Class,弹出“Add Class”对话框,然后在中间区域中选择“MFC Class”,点“Add”按钮,弹出另一个类向导对话框,设置Class name为CAddSheet,Baseclass选择“CPropertySheet”,点“Finish”按钮,这样就属性表类就建好了。
接下来,在新生成的AddSheet.h中包含三个属性页类的头文件:
#include"SummandPage.h"
#include "AddendPage.h"
#include "AddPage.h"
之后在AddSheet.h中添加private变量:
CSummandPage m_summandPage;
CAddendPage m_addendPage;
CAddPage m_addPage;
然后在AddSheet.cpp文件中修改CAddSheet的两个构造函数为:
CAddSheet::CAddSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(nIDCaption, pParentWnd, iSelectPage) { AddPage(&m_summandPage); AddPage(&m_addendPage); AddPage(&m_addPage); } CAddSheet::CAddSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(pszCaption, pParentWnd, iSelectPage) { AddPage(&m_summandPage); AddPage(&m_addendPage); AddPage(&m_addPage); }
最后在消息处理函数中添加:
void CAdditionDlg::OnBnClickedInstructButton() { // TODO: 在此添加控件通知处理程序代码 CAddSheet sheet(_T("")); /*sheet.SetWizardMode();*/ sheet.DoModal(); }
将之前的重载函数都注释,
在消息处理函数中添加:
void CAdditionDlg::OnBnClickedInstructButton() { // TODO: 在此添加控件通知处理程序代码 CAddSheet sheet(_T("")); sheet.DoModal(); }