windows是怎样实现模式对话框的,我一直感到比较迷惑。
非模式对话框非常好理解,因为在windows的消息循环并不对窗口进行特殊的对待,只是简单的将消息发给每个窗口的处理函数。而模式对话框却很奇怪,他可以阻止其他窗口对部分消息的响应,却可以处理像WM_PRINT的消息,怎么实现?????????????
还是他只是独占了用户输入,不允许其他用户取得输入,其他窗口对消息的处理依然是进行中,如果是这样,那又该怎么实现?
非模式对话框非常好理解,因为在windows的消息循环并不对窗口进行特殊的对待,只是简单的将消息发给每个窗口的处理函数。而模式对话框却很奇怪,他可以阻止其他窗口对部分消息的响应,却可以处理像WM_PRINT的消息,怎么实现?????????????
还是他只是独占了用户输入,不允许其他用户取得输入,其他窗口对消息的处理依然是进行中,如果是这样,那又该怎么实现?
http://desktop.chinaitlab.com/VC/35730.html
这个确实讲的不错.
CDialog::CDialog(UINT nIDTemplate, CWnd* pParentWnd /*=NULL*/)
{
AFX_ZERO_INIT_OBJECT(CWnd);m_pParentWnd = pParentWnd;
m_lpszTemplateName = MAKEINTRESOURCE(nIDTemplate);
m_nIDHelp = nIDTemplate;
}注意 pParentWnd 参数默认是 NULL,不是 this
2.
int CDialog::DoModal()
{
// can be constructed with a resource template or InitModalIndirect
ASSERT(m_lpszTemplateName != NULL || m_hDialogTemplate != NULL ||
m_lpDialogTemplate != NULL);// load resource as necessary
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);// return -1 in case of failure to load the dialog template resource
if (lpDialogTemplate == NULL)
return -1;// disable parent (before creating dialog)
HWND hWndParent = PreModal();
**因此父窗口应该来自 PreModalHWND CDialog::PreModal()
{
// cannot call DoModal on a dialog already constructed as modeless
ASSERT(m_hWnd == NULL);// allow OLE servers to disable themselves
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
pApp->EnableModeless(FALSE);// find parent HWND
HWND hWnd = CWnd::GetSafeOwner_(m_pParentWnd->GetSafeHwnd(), &m_hWndTop);// hook for creation of dialog
AfxHookWindowCreate(this);// return window to use as parent for dialog
return hWnd;
}
**父窗口来自 GetSafeOwner_3.
HWND PASCAL CWnd::GetSafeOwner_(HWND hParent, HWND* pWndTop)
{
// get window to start with
HWND hWnd = hParent;
if (hWnd == NULL)
{
CFrameWnd* pFrame = CCmdTarget::GetRoutingFrame_();
if (pFrame != NULL)
hWnd = pFrame->GetSafeHwnd();
else
hWnd = AfxGetMainWnd()->GetSafeHwnd();
}***OK,到这里应该明白了,因为 hWnd = NULL(父窗口)
因此最终的 hParent = AfxGetMainWnd()->GetSafeHwnd(),即 CMainFrame::m_hWnd楼主需要注意一个问题,模态对话框是一个比较有意思的东西,它的消息循环是伪造出来的,是对一个非模态对话框AfxHookWindowCreate并且RunModalLoop来完成的,恐怕在MFC你再找不出来其它窗口是这样创建的
而且取父窗口不是保存一个值就可以了事的,你可以发现CWnd::GetParent 的方法是通过调用 ::GetParent 完成的,你所保存的值对它来说毫无意义
我的目的是指出模态对话框的创建过程受到 AfxHookWindowCreate 的影响,使得创建过程受到控制,这就是 hParentWnd 的作用
其实我本来以为MFC的模式对话框也是通过api的DialogBox实现的,所以我想问的是api中DialogBox是怎么样实现,如goodboyws(深夜不眠者(VCMVP))所说内嵌消息消息循环,应该是可以实现的。