特殊说明:版权归个人所有,请勿转载,谢谢合作。
打开VC6.0后,点击【File】菜单,选择【New…】项,在弹出的新建窗口中,选择【MFC AppWizard(exe)】使用MFC向导方式创建,在【Project name】处输入项目名称,此处以“Demo_11”为例,点击【OK】按钮确认创建,如图11.2所示。
- 图11.2 新建窗口
在弹出的MFC向导的第一步里,选择【Dialog based】项,即基于对话框模式,点击【Finish】按钮确认,如图11.3所示。
- 图11.3 模式选择
工程创建完成后,如图11.4所示。
- 图11.4 对话框模式
典型的对话框程序创建完成后,可以在类视图(ClassView)中,看到如下几个类:
CAboutDlg:关于版本对话框控制类;
CDemo_11App:应用程序管理类;
CDemo_11Dlg:对话框管理类。
其中,后两个类是根据项目名称而定的,规则是:C+项目名称+App(或Dlg))组成。
11.2.1 关于对话框控制类
关于对话框,主要用来显示程序的版本、版权、作者及创建等相关信息。在应用程序中没有任何功能作用,只是用于显示版本、版本权等信息。对话框执行结果如图11.5所示。
- 图11.5 关于对话框
在VC6.0中,可以在资源视图(ResourceView)中找到这个对话框,在那里可以对相应用信息进行修改。当然也可以在类视图(ClassView)中,选择CAboutDlg类后点击鼠标右键,在弹出的菜单中选择【Go To Dialog Editor】项,如图11.6所示。
- 图11.6 对话框编辑视图跳转
跳转成功后如图11.7所示。
- 图11.7 关于对话框编辑界面
MFC编程模式下,通常情况下,一个对话框会对应一个类来对它进行管理,所有的操作方法与响应的消息也会在这个类中撰写与捕获。所有对话框管理类跳转到对话框,都可以使用如图11.6所示的操作方法。
如果想在资源视图(ResourceView)中找到这个对话框,就先需要知道这个类管理的是哪个对话框,以CAboutDlg类为例,在类视图(ClassView)中,双击【CAboutDlg】类,即可跳转到类的定义部分,代码如下所示(如下代码为系统生成):
class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() };
在类的定义部分,可以找到“IDD=”后面的“IDD_ABOUTBOX”则为这个类管理的对话框的ID,此时就可以在资源视图(ResourceView)中的“Dialog”中找到这个ID,并使用双击鼠标右键,打开它,如图11.8所示。
- 图11.8 关于对话框编辑模式
在MFC编程中,大部分对话框都需要一个类来对它进行控制。并使用DoModal()的方法显示,操作代码如下所示(如下代码为系统生成):
void CDemo_11Dlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } }
11.2.2 应用程序管理类
在MFC编程模式下,不会再出现入口函数,Windows已经将入口函数封装到底层操作,而应用程序管理类,它是项目第一个被执行的类,整个窗口由它来进行管理。它有一个很特殊的函数InitInstance,该函数可用于程序初始化,在程序开始执行时被自动调用。如果创建完工程后,不做任何操作,该函数将被第一个被执行。该函数有一个更重要的功能,就是调用下一章节讲解的对话框管理类(本例为CDemo_11Dlg)。代码如下所示(如下代码为系统生成):
BOOL CDemo_11App::InitInstance() { AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif CDemo_11Dlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; }
代码中灰色的部分说明了对话框管理类的调用,以及返回值的应用。
11.2.3 对话框管理类
对话框管理类,管理应用程序对话窗口。在通常情况下,一个对话框应该有一个管理它的类于之对应。类里的所有成员方法如图11.9所示。
- 图11.9 对话框管理类
如图11.9所示,CDemo_11Dlg类中OnSysCommand函数,主要用来处理对话框标题栏菜单的一些操作,本例中实现了关于对话框显示,具体代码如下所示(如下代码为系统生成):
void CDemo_11Dlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } }
OnPaint函数主要用于图形的绘制,该函数相当于Win32 SDK编程下的WM_PAINT消息,相当于将WM_PAINT消息内部的结构封装成一个函数,用于图形的绘制。代码如下所示(如下代码为系统生成):
void CDemo_11Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } }
OnInitDialog函数也是最常用的函数,它常用于数据的初始化操作(如:初始化控件风格、控件的内容等),代码如下所示,初始化的内容写在代码加灰处的后面(如下代码为系统生成):
BOOL CDemo_11Dlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control }
对话框工程创建完成后,系统自动生成的三个类:CAboutDlg(关于版本对话框控制类)、CDemo_11App(应用程序管理类)、CDemo_11Dlg(对话框管理类)之间的关系在上面的章节中已经进行了说明,下面从全局角度进行介绍。CDemo_11App类是最早执行的一个类,而这个类中有一个Initstance函数,此函数调用了CDemo_11Dlg类。在CDemo_11Dlg类中,有一个OnSysCommand函数,又调用了CAboutDlg类。具体的调用过程,如图11.10描述了这一调用的过程。
- 图11.10 对话框各类调用关系