特殊说明:版权归个人所有,请勿转载,谢谢合作。
打开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 对话框各类调用关系