VC语言

本类阅读TOP10

·VC++ 学习笔记(二)
·用Visual C++打造IE浏览器(1)
·每个开发人员现在应该下载的十种必备工具
·教你用VC6做QQ对对碰外挂程序
·Netmsg 局域网聊天程序
·Windows消息大全
·VC++下使用ADO编写数据库程序
·VC++学习笔记(四)
·非法探取密码的原理及其防范
·怎样在VC++中访问、修改注册表

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
重载CDialog::PreCreateWindow是无效的

作者:未知 来源:月光软件站 加入时间:2005-6-5 月光软件站

一般的窗口的创建是使用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, 200
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "aaaa"
FONT 9, "宋体"
BEGIN
    DEFPUSHBUTTON   "确定",IDOK,260,10,50,14
    PUSHBUTTON      "取消",IDCANCEL,260,23,50,14
    LTEXT           "TODO: 在这里设置对话控制。",IDC_STATIC,50,90,200,8
END
第一行是对话框的位置信息,第二行是对话框的样式,第三行是扩展样式,它们的内容就是在对话框编辑器修改属性时得到的内容。
重载PreCreateWindow的目的不外乎是想在其中修改默认的窗口类的样式信息,然后达到修改窗口样式的目的。而对话框能在资源编辑器里修改它的所有应有的样式,而这些样式在DoModal函数里能被读出来,并传递给CreateDialoagIndirect函数,创建对话框。
由于不能在PreCreateWindow函数里注册新的窗口类,所有的MFC程序的对话框的类名都是相同的:#32770。



相关文章

相关软件