幸虧想當然了的一段還算不太長的時間(^_^)
試了以後發現啓動時對話框並沒有隱藏,納悶了?????
然後查看了一下MFC的底層代碼以後發現,發現對話框的顯示路由如下:
首先當然就是從InitInstance裏的dlg.DoModal()開始啦,DoModal又調用了
CWnd:CreateDlgIndirect,在CreateDlgIndirect裏又調用了全局的::CreateDlgdirect完成了對話框的
創建(當然它是通過全局的::CreateWindowEx完成窗口創建的啦),不過這裏要說一下的是目前僅僅
是對話框窗口被創建了,對話框上的控件窗口還沒有被創建呢,不要想當然哦!!
對話框窗口創建完成以後,::CreateDlgdirect會發出WM_INITDIALOG消息,可能你已經發現該消息
並沒有消息映射路由。它是由對話框消息處理函數AfxDlgProc處理的,請看下面:
BOOL CALLBACK AfxDlgProc(HWND hWnd, UINT message, WPARAM, LPARAM)
{
if (message == WM_INITDIALOG)
{
// special case for WM_INITDIALOG
CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, CWnd::FromHandlePermanent(hWnd));
if (pDlg != NULL)
return pDlg->OnInitDialog();
else
return 1;
}
return 0;
}
在這裏要說一下的是,不要想當然的認爲我們的對話框OnInitDialog初始化完後,對話框的的一切
工作就完成了,其實不是的。你有沒有想過我們鼠標單擊一個按鈕時,按鈕爲什麼會相應??
想必學過Win32編程或對MFC底層代碼有了解的肯定知道一定存在着一個類似
While(&msg,NULL,0,0)的東東,對它就是 RunModalLoop,對話框的消息循環。請看如下:
這要你的對話框有WS_VISIBLE屬性在此消息循環中就能顯示對話框。
int CWnd::RunModalLoop(DWORD dwFlags)
{
ASSERT(::IsWindow(m_hWnd)); // window must be created
ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state
// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;
BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
HWND hWndParent = ::GetParent(m_hWnd);
m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
MSG* pMsg = &AfxGetThread()->m_msgCur;
// acquire and dispatch messages until the modal state is done
for (;;)
{
ASSERT(ContinueModal());
// phase1: check to see if we can do idle work
while (bIdle &&
!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
{
ASSERT(ContinueModal());
// show the dialog when the message queue goes idle
if (bShowIdle)
{
ShowWindow(SW_SHOWNORMAL);
UpdateWindow();
bShowIdle = FALSE;
}
// call OnIdle while in bIdle state
if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
{
// send WM_ENTERIDLE to the parent
::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
}
if ((dwFlags & MLF_NOKICKIDLE) ||
!SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
{
// stop idle processing next time
bIdle = FALSE;
}
}
// phase2: pump messages while available
do
{
ASSERT(ContinueModal());
// pump message, but quit on WM_QUIT
if (!AfxGetThread()->PumpMessage())
{
AfxPostQuitMessage(0);
return -1;
}
// show the window when certain special messages rec'd
if (bShowIdle &&
(pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
{
ShowWindow(SW_SHOWNORMAL);
UpdateWindow();
bShowIdle = FALSE;
}
if (!ContinueModal())
goto ExitModal;
// reset "no idle" state after pumping "normal" message
if (AfxGetThread()->IsIdleMessage(pMsg))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
}
ExitModal:
m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
return m_nModalResult;
}
BOOL CWnd::ContinueModal()
{
return m_nFlags & WF_CONTINUEMODAL;
}
相信看了上面的首先不要認爲OnInitDialog就是對話框的初始化終點,他後面還有一個RunModalLoop
還迷惑的可以看看MFC底層代碼,看看在OnInitDialog裏要想獲得控件的值時爲什麼不用UpdateData(FALSE)
將控件關聯變量的值傳給控件,通常這是必須的,還有調用了OnOK後爲什麼不用UpdateData(TRUE)將控件
值傳給控件變量,這些就可以自動完成
還有像我上面所說的消息WM_INITDIALOG真的沒有消息路由嗎???
還有好多。。。。。
看看底層代碼就知道了 DLGCORE.cpp