一般的窗口的创建是使用Create函数,这个函数在创建窗口之前调用了PreCreateWindow函数,并且允许在创建创建之前在PreCreateWindow注册一个拥有自定义窗口样式的新的窗口类,来创建一个拥有自定义类名新的窗口。而模式对话框是通过CreateDialogIndirect来创建的,在这当中并没有调用PreCreateWindow函数,重载的PreCreateWindow函数根本就不被执行,因此在这个函数里修改对话框的窗口类是没有用的。CDialog是通过CDialog::DoModal()函数创建窗口的,下面是MFC中DoModal函数的代码: int CDialog::DoModal(){ // 载入资源 LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate; HGLOBAL hDialogTemplate = m_hDialogTemplate; HINSTANCE hInst = AfxGetResourceHandle(); 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); if (lpDialogTemplate == NULL) return -1; HWND hWndParent = PreModal(); AfxUnhookWindowCreate(); BOOL bEnableParent = FALSE; if (hWndParent != NULL && ::IsWindowEnabled(hWndParent)) { ::EnableWindow(hWndParent, FALSE); bEnableParent = TRUE; } TRY { // 创建无模式对话框 AfxHookWindowCreate(this); if (CreateDlgIndirect(lpDialogTemplate, CWnd::FromHandle(hWndParent), hInst)) { if (m_nFlags & WF_CONTINUEMODAL) { // 进入模式循环 DWORD dwFlags = MLF_SHOWONIDLE; if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG; VERIFY(RunModalLoop(dwFlags) == m_nModalResult); } // hide the window before enabling the parent, etc. if (m_hWnd != NULL) SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW| SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); } } CATCH_ALL(e) { ...... } END_CATCH_ALL if (bEnableParent) ::EnableWindow(hWndParent, TRUE); if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd) ::SetActiveWindow(hWndParent); // destroy modal window DestroyWindow(); PostModal(); // 解锁、释放资源 if (m_lpszTemplateName != NULL || m_hDialogTemplate != NULL) UnlockResource(hDialogTemplate); if (m_lpszTemplateName != NULL) FreeResource(hDialogTemplate); return m_nModalResult;}在这个函里先是载入了对话框资源,然后通过LockResource函数,使DLGTEMPLATE类型指针指向相关的内存,然后把这个指针作为参数传递给了CreateDlgIndirect函数(调用了::CreateDialogIndirect)。DLGTEMPLATE的定义如下:typedef struct { DWORD style; DWORD dwExtendedStyle; WORD cdit; short x; short y; short cx; short cy; } DLGTEMPLATE, *LPDLGTEMPLATE; 这个结构体保存着创建对话框需要的样式、位置等信息,在DoModal函数里它是通过对话框资源得到的,那对话框资源里一定有它需要的东西。下面是从rc文件中摘录的对话框的信息:IDD_AAAA_DIALOG DIALOGEX 0, 0, 320, 200STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENUEXSTYLE WS_EX_APPWINDOWCAPTION "aaaa"FONT 9, "宋体"BEGIN DEFPUSHBUTTON "确定",IDOK,260,10,50,14 PUSHBUTTON "取消",IDCANCEL,260,23,50,14 LTEXT "TODO: 在这里设置对话控制。",IDC_STATIC,50,90,200,8END第一行是对话框的位置信息,第二行是对话框的样式,第三行是扩展样式,它们的内容就是在对话框编辑器修改属性时得到的内容。重载PreCreateWindow的目的不外乎是想在其中修改默认的窗口类的样式信息,然后达到修改窗口样式的目的。而对话框能在资源编辑器里修改它的所有应有的样式,而这些样式在DoModal函数里能被读出来,并传递给CreateDialoagIndirect函数,创建对话框。由于不能在PreCreateWindow函数里注册新的窗口类,所有的MFC程序的对话框的类名都是相同的:#32770。
本文地址:http://com.8s8s.com/it/it26.htm