CDialog中的执行路径

基于对话框的应用程序与基于SDI和MDI的程序,在程序执行路径上有所不同。对话框的执行路径是:

1.刚开始都是差不多的:_tWinMain——>AfxWinMain——>theApp.InitInstance()

2.接下来有所不同:theApp.InitInstance()——>int nResponse = dlg.DoModal()(注意不是SDI和MDI中的ProcessShellCommand(),——>CreateDlgIndirect()

——>CreateDialogIndirect——>...——>CreateWindowEx().

 

一般的窗口的创建是使用Create函数,这个函数在创建窗口之前调用了PreCreateWindow函数,并且允许在创建创建之前在PreCreateWindow注册一个拥有自定义窗口样式的新的窗口类,来创建一个拥有自定义类名新的窗口。而模式对话框是通过CreateDialogIndirect来创建的,在这当中并没有调用PreCreateWindow函数,重载的PreCreateWindow函数根本就不被执行,因此在这个函数里修改对话框的窗口类是没有用的。
  CDialog是通过CDialog::DoModal()函数创建窗口的,下面是MFC中DoModal函数的代码:  

代码
 1    int  CDialog::DoModal()
 2 ExpandedBlockStart.gifContractedBlock.gif   {
 3   // 载入资源
 4   LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;
 5   HGLOBAL hDialogTemplate = m_hDialogTemplate;
 6   HINSTANCE hInst = AfxGetResourceHandle();
 7   if (m_lpszTemplateName != NULL)
 8ExpandedSubBlockStart.gifContractedSubBlock.gif   {
 9   hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
10   HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
11   hDialogTemplate = LoadResource(hInst, hResource);
12   }

13   if (hDialogTemplate != NULL)
14   lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);
15   if (lpDialogTemplate == NULL)
16   return -1;
17   HWND hWndParent = PreModal();
18   AfxUnhookWindowCreate();
19   BOOL bEnableParent = FALSE;
20   if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
21ExpandedSubBlockStart.gifContractedSubBlock.gif   {
22   ::EnableWindow(hWndParent, FALSE);
23   bEnableParent = TRUE;
24   }

25   TRY
26ExpandedSubBlockStart.gifContractedSubBlock.gif   {
27   // 创建无模式对话框
28   AfxHookWindowCreate(this);
29   if (CreateDlgIndirect(lpDialogTemplate,
30   CWnd::FromHandle(hWndParent), hInst))
31ExpandedSubBlockStart.gifContractedSubBlock.gif   {
32   if (m_nFlags & WF_CONTINUEMODAL)
33ExpandedSubBlockStart.gifContractedSubBlock.gif   {
34   // 进入模式循环
35   DWORD dwFlags = MLF_SHOWONIDLE;
36   if (GetStyle() & DS_NOIDLEMSG)
37   dwFlags |= MLF_NOIDLEMSG;
38   VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
39   }

40   // hide the window before enabling the parent, etc.
41   if (m_hWnd != NULL)
42   SetWindowPos(NULL, 0000, SWP_HIDEWINDOW|
43   SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
44   }

45   }

46   CATCH_ALL(e)
47ExpandedSubBlockStart.gifContractedSubBlock.gif   {
48   
49   }

50   END_CATCH_ALL 
51   if (bEnableParent)
52   ::EnableWindow(hWndParent, TRUE);
53   if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
54   ::SetActiveWindow(hWndParent);
55   // destroy modal window
56   DestroyWindow();
57   PostModal();
58   // 解锁、释放资源
59   if (m_lpszTemplateName != NULL || m_hDialogTemplate != NULL)
60   UnlockResource(hDialogTemplate);
61   if (m_lpszTemplateName != NULL)
62   FreeResource(hDialogTemplate);
63   return m_nModalResult;
64  }

 在这个函数里先是载入了对话框资源,然后通过LockResource函数,使DLGTEMPLATE类型指针指向相关的内存,然后把这个指针作为参数传递给了CreateDlgIndirect函数(调用了::CreateDialogIndirect)。DLGTEMPLATE的定义如下:

代码
1 ExpandedBlockStart.gif ContractedBlock.gif   typedef  struct  
2   DWORD style; 
3   DWORD dwExtendedStyle; 
4   WORD cdit; 
5   short x; 
6   short y; 
7   short cx; 
8   short cy; 
9  }
 DLGTEMPLATE,  * LPDLGTEMPLATE; 

我们看看CreateDlgIndirect函数的源码:

代码
 1 BOOL CWnd::CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate,
 2     CWnd *  pParentWnd, HINSTANCE hInst)
 3 ExpandedBlockStart.gifContractedBlock.gif {    ASSERT(lpDialogTemplate != NULL);
 4    if (pParentWnd != NULL)
 5        ASSERT_VALID(pParentWnd);
 6
 7    if (hInst == NULL)
 8        hInst = AfxGetInstanceHandle();
 9
10#ifndef _AFX_NO_OCC_SUPPORT
11    _AFX_OCC_DIALOG_INFO occDialogInfo;
12    COccManager* pOccManager = afxOccManager;
13#endif
14
15    HGLOBAL hTemplate = NULL;
16
17    HWND hWnd = NULL;
18#ifdef _DEBUG
19    DWORD dwError = 0;
20#endif
21
22    TRY
23ExpandedSubBlockStart.gifContractedSubBlock.gif    {
24        VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
25        AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);
26
27#ifndef _AFX_NO_OCC_SUPPORT
28        // separately create OLE controls in the dialog template
29        if (pOccManager != NULL)
30ExpandedSubBlockStart.gifContractedSubBlock.gif        {
31            if (!SetOccDialogInfo(&occDialogInfo))
32                return FALSE;
33
34            lpDialogTemplate = pOccManager->PreCreateDialog(&occDialogInfo,
35                lpDialogTemplate);
36        }

37
38        if (lpDialogTemplate == NULL)
39            return FALSE;
40#endif //!_AFX_NO_OCC_SUPPORT
41
42        // If no font specified, set the system font.
43        CString strFace;
44        WORD wSize = 0;
45        BOOL bSetSysFont = !CDialogTemplate::GetFont(lpDialogTemplate, strFace,
46            wSize);
47
48        // On DBCS systems, also change "MS Sans Serif" or "Helv" to system font.
49        if ((!bSetSysFont) && GetSystemMetrics(SM_DBCSENABLED))
50ExpandedSubBlockStart.gifContractedSubBlock.gif        {
51            bSetSysFont = (strFace == _T("MS Shell Dlg"||
52                strFace == _T("MS Sans Serif"|| strFace == _T("Helv"));
53            if (bSetSysFont && (wSize == 8))
54                wSize = 0;
55        }

56
57        if (bSetSysFont)
58ExpandedSubBlockStart.gifContractedSubBlock.gif        {
59            CDialogTemplate dlgTemp(lpDialogTemplate);
60            dlgTemp.SetSystemFont(wSize);
61            hTemplate = dlgTemp.Detach();
62        }

63
64        if (hTemplate != NULL)
65            lpDialogTemplate = (DLGTEMPLATE*)GlobalLock(hTemplate);
66
67        // setup for modal loop and creation
68        m_nModalResult = -1;
69        m_nFlags |= WF_CONTINUEMODAL;
70
71        // create modeless dialog
72        AfxHookWindowCreate(this);
73        hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,
74            pParentWnd->GetSafeHwnd(), AfxDlgProc);
75#ifdef _DEBUG
76        dwError = ::GetLastError();
77#endif
78    }

79    CATCH_ALL(e)
80ExpandedSubBlockStart.gifContractedSubBlock.gif    {
81        DELETE_EXCEPTION(e);
82        m_nModalResult = -1;
83    }

84    END_CATCH_ALL
85.
86    ASSERT(hWnd == m_hWnd);
87    return TRUE;
88}

函数CreateDialogIndirect在MSDN中的解释为:The CreateDialogIndirect macro creates a modeless dialog box from a dialog box template in memory,意思是他根据对话框模板在内存中创建一个无模的对话框。他是一个API函数,最终也是调用CreateWindowEx实现窗口(对话框)的创建。
  这个结构体保存着创建对话框需要的样式、位置等信息,在DoModal函数里它是通过对话框资源得到的,那对话框资源里一定有它需要的东西。

下面是从rc文件中摘录的对话框的信息:

 

代码
 1   IDD_AAAA_DIALOG DIALOGEX  0 0 320 200
 2   STYLE DS_MODALFRAME  |  WS_POPUP  |  WS_VISIBLE  |  WS_CAPTION  |  WS_SYSMENU
 3   EXSTYLE WS_EX_APPWINDOW
 4   CAPTION  " aaaa "
 5   FONT  9 " 宋体 "
 6   BEGIN
 7    DEFPUSHBUTTON  " 确定 " ,IDOK, 260 , 10 , 50 , 14
 8    PUSHBUTTON  " 取消 " ,IDCANCEL, 260 , 23 , 50 , 14
 9    LTEXT  " TODO: 在这里设置对话控制。 " ,IDC_STATIC, 50 , 90 , 200 , 8
10   END
11

  第一行是对话框的位置信息,第二行是对话框的样式,第三行是扩展样式,它们的内容就是在对话框编辑器修改属性时得到的内容。
  重载PreCreateWindow的目的不外乎是想在其中修改默认的窗口类的样式信息,然后达到修改窗口样式的目的。而对话框能在资源编辑器里修改它的所有应有的样式,而这些样式在DoModal函数里能被读出来,并传递给CreateDialoagIndirect函数,创建对话框。

转载于:https://www.cnblogs.com/sqzxcv/archive/2009/11/30/1614074.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值