OnInitDialog中ShowWindow爲什麼無效?

最近看到有關對話框啓動隱藏的問題, 覺得不就是在OnInitDialog裏調用 ShowWindow( SW_HIDE )
幸虧想當然了的一段還算不太長的時間(^_^)
試了以後發現啓動時對話框並沒有隱藏,納悶了?????
然後查看了一下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
發佈了31 篇原創文章 · 獲贊 1 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章