UINT message, PARAM, LPARAM) {
if (message == WM_INITDIALOG) {
//处理WM_INITDIALOG消息
CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, CWnd::FromHandlePermanent(hWnd)); if (pDlg != NULL)
return pDlg->OnInitDialog(); else return 1; }
return 0; }
由上可以看出,MFC的对话框函数AfxDlgProc仅处理消息WM_INITDIALOG,其他都留给对话框窗口过程处理。因此,它不同于SDK编程的对话框过程。程序员在SDK的对话框过程处理消息和事件,实现自己的对话框功能。
AfxDlgProc处理WM_INITDIALOG消息时调用虚拟函数OnInitDialog,给程序员一个机会处理对话框的初始化。
2. 模式对话框窗口过程
本小节讨论对话框的窗口过程。
AfxWndProc是所有的MFC窗口类使用的窗口过程,它取代了模式对话框原来的窗口过程(Windows提供),那么,MFC如何完成Win32下对话框窗口的功能呢?
考查模式对话框的创建过程。CDialog::DoModal用来创建模式对话框窗口并执行有关任务,和DoModal相关的是MFC内部使用的成员函数
CDialog::PreModal和CDialog::PostModal。下面分别讨论它们的实现。 HWND CDialog::PreModal() {
// cannot call DoModal on a dialog already constructed as modeless ASSERT(m_hWnd == NULL);
// allow OLE servers to disable themselves AfxGetApp()->EnableModeless(FALSE); // 得到父窗口
CWnd* pWnd = CWnd::GetSafeOwner(m_pParentWnd, &m_hWndTop);
// 如同CWnd处理其他窗口的创建,设置一个窗口创建HOOK
AfxHookWindowCreate(this); //返回父窗口的句柄
return pWnd->GetSafeHwnd(); }
void CDialog::PostModal() {
//取消窗口创建前链接的HOOK
AfxUnhookWindowCreate(); // just in case //MFC对话框对象和对应的Windows对话框窗口分离 Detach(); // just in case
// m_hWndTop是当前对话框的父窗口或所属窗口,则恢复它
if (::IsWindow(m_hWndTop)) ::EnableWindow(m_hWndTop, TRUE); m_hWndTop = NULL;
AfxGetApp()->EnableModeless(TRUE); }
int CDialog::DoModal() {
// can be constructed with a resource template or InitModalIndirect
ASSERT(m_lpszTemplateName != NULL || m_hDialogTemplate != NULL || m_lpDialogTemplate != NULL); //加载对话框资源
LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;
HGLOBAL hDialogTemplate = m_hDialogTemplate; HINSTANCE hInst = AfxGetResourceHandle(); //查找资源(见9.5.2节),找到了就加载它 if (m_lpszTemplateName != NULL) {
hInst =
AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG); HRSRC hResource =
::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
hDialogTemplate = LoadResource(hInst, hResource); }
//锁定加载的资源
if (hDialogTemplate != NULL)
lpDialogTemplate =
(LPCDLGTEMPLATE)LockResource(hDialogTemplate);
// return -1 in case of failure to load the dialog template resource
if (lpDialogTemplate == NULL) return -1;
//创建对话框前禁止父窗口,为此要调用PreModal得到父窗口句柄
HWND hWndParent = PreModal(); AfxUnhookWindowCreate(); CWnd* pParentWnd =
CWnd::FromHandle(hWndParent); BOOL bEnableParent = FALSE; if (hWndParent != NULL
&& ::IsWindowEnabled(hWndParent)) {
::EnableWindow(hWndParent, FALSE); bEnableParent = TRUE; }
//创建对话框,注意是无模式对话框 TRY {
//链接一个HOOK到HOOK链以处理窗口创建, //如同4.4.1节描述的CWnd类窗口创建一样 AfxHookWindowCreate(this); //CreateDlgIndirect间接调用::CreateDlgIndirect,
//最终调用了::CreateWindowEX来创建对话框窗口。
//HOOK过程_AfxCbtFilterHook用子类化的方法 //取代原来的窗口过程为AfxWndProc。 if (CreateDlgIndirect(lpDialogTemplate, CWnd::FromHandle(hWndParent), hInst)) {
if (m_nFlags & WF_CONTINUEMODAL) {
// enter modal loop
DWORD dwFlags = MLF_SHOWONIDLE;
//RunModalLoop接管整个应用程序的消息处理 if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG; VERIFY(RunModalLoop(dwFlags) == m_nModalResult); }