• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理
            ?

            基于 CDialog 的應用程序一開始便被隱藏的方法

            作者: Solomon (lsong@kali.com.cn)

            日期: 2001/12/29

            相關文章: http://www.csdn.net/develop/article/11/11634.shtm

              要使一個基于 CDialog 的應用程序一開始便被隱藏的方法有好多種。大多數方法在相關文章(http://www.csdn.net/develop/article/11/11634.shtm)中已經提及。本人之所以要寫這篇文章,主要是通過分析MFC 調用模式對話框的方法向大家展示一種簡單,合理,完滿的解決方案。

              首先,用MFC 生成的一個基于對話框的應用程序框架,然后修改對話框資源的Visible屬性使之成為不可見(在屬性頁的MoreStyle中),接著按下F5 來運行這個程序,我們會發現,它并不象我們期望的那樣一開始就被隱藏。而是被顯示了出來。那么為什么會這樣呢?特別是精通SDK的朋友們,會對此百思不得其解。

              其實,MFC框架為了顯示對話框很多工作,它并不簡簡單單地調用 DialogBox 顯示對話框,而是使用了相對復雜的方法。現在,我就來引導大家對此探個究竟。

              在生成的應用程序框架中(名稱為Test),你會看到CTestApp和CTestDlg 兩個類,在 CTestApp 的 InitInstance 方法中有如下語句:

            ???? CTestDlg dlg;
            ??? ?m_pMainWnd = &dlg;
            ??? ?int nResponse = dlg.DoModal();??????? // 此處將創建并顯示對話框

            DoModal 是一個虛函數,MFC允許用戶編寫自己的調用對話框方式來替代原來的方式。但是,MS 實在令人失望。如果,你打開 DlgCore.Cpp (MFC Source 目錄下)并復制 DoModal  的代碼到你自己的類中,你會發現無法編譯成功。原因在于MS在 DoModal 中使用了兩個非輸出函數 AfxHookWindowCreate 和 AfxUnhookWindowCreate。(這兩個函數的作用超出了本文所討論的范圍,因此不作詳細論述。)由于無法編譯,所以 MS  要求用戶的 DoModal 必須調用 CDialog 的 DoModal 來顯示對話框。這樣,控制隱藏就無法通過重載 DoModal 實現了。那么 MS 在 DoModal 中干了什么呢?下面就是一部分代碼。

            int CDialog::DoModal()
            {
            ? ...... 讀入資源,并作一些設置
            ? if (CreateDlgIndirect(lpDialogTemplate,
            ??????????? CWnd::FromHandle(hWndParent), hInst))  //創建無模式對話框
            ??? {
            ????? if (m_nFlags & WF_CONTINUEMODAL)
            ????? {
            ??????? // enter modal loop
            ??????? DWORD dwFlags = MLF_SHOWONIDLE;  //罪魁禍首就是他
            ??????? if (GetStyle() & DS_NOIDLEMSG)
            ????????? dwFlags |= MLF_NOIDLEMSG;
            ??????? VERIFY(RunModalLoop(dwFlags) == m_nModalResult); //進入消息循環
            ????? }

              .......
            ??? }
            ? }
            ? ...... 釋放資源等
            }

            原來,DoModal 并不使用 DialogBox 直接調出對話框,而是通過創建無模式對話框并維護消息循環的方式(RunModalLoop)來模擬模式對話框的效果。(看起來好像有點像DialogBox 的內部作業方式)MLF_SHOWONIDLE 是什么?看英文的意思是在Idle 的時候ShowWindow。那么是不是這樣呢?好吧,為了探個究竟,讓我們進入RunModalLoop。RunModalLoop在WinCore.CPP中定義。打開WinCore.CPP 并找到 RunModalLoop, 會看到以下的語句

            BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);

            條件 dwFlags & MLF_SHOWONIDLE 始終為TRUE。 而 !(GetStyle() & WS_VISIBLE)只有在WS_VISIBLE屬性沒有設置的時候才會為 TRUE。這樣,當我們去掉Visible 屬性后 bShowIdle 就為 TRUE 了。再往下,就會看到以下的調用

            ??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;  // 指示下一次Idle 時不用顯示對話框了
            ???}
            While 里的條件是消息隊列里再也沒有任何消息了。此時,由于 bShowIdle 為 TRUE ,就會調用 ShowWindow 來顯示對話框。由于 ShowWindow 只執行一次,所以如果能截獲第一次WM_SHOWWINDOW消息, 就能控制了隱藏了。

            是的。在 CTestDlg 處理 WM_SHOWWINDOW 并添上以下代碼

            void CTestDlg::OnShowWindow(BOOL bShow, UINT nStatus)
            {

            ?if( GetStyle() & WS_VISIBLE ) {
            ??CDialog::OnShowWindow(bShow, nStatus);
            ?} else {
            ??long Style = ::GetWindowLong(*this, GWL_STYLE);
            ??::SetWindowLong(*this, GWL_STYLE, Style | WS_VISIBLE);
            ??CDialog::OnShowWindow(SW_HIDE, nStatus);
            ?}
            }
            再運行一下,哈哈,對話框不見了,連閃都不閃一下。細心的讀者也許會問為什么使用SetWindowLong,而不是 ModifyStyle, 其實是為了加快速度,因為 ModifyStyle 內部還要調用 GetWindowLong 和 SetWindowPos。到此為止,一個簡單,完滿的解決方法已經展現在大家面前了。

            其實,本來 MS 可以做的更好,比如把 GetStyle() 聲明為虛函數,使得我們能返回WS_VISIBLE 來控制 bShowIdle 成為 FALSE, 或者把

            ??????? DWORD dwFlags = MLF_SHOWONIDLE;

            改成

              DWORD dwFlags =? ShowOnIdle();? // 聲明為虛函數


            希望MS能在以后的版本中考慮這個問題。

            這是本人在CSDN上的第一個作品,希望大家能多提寶貴意見。

            无码精品久久一区二区三区| 国产精品一区二区久久国产| 国产精品久久久久天天影视| 久久亚洲AV无码精品色午夜| 久久嫩草影院免费看夜色| 国产99精品久久| 久久综合国产乱子伦精品免费| 中文字幕精品久久久久人妻| 欧美精品一区二区久久| 超级碰久久免费公开视频| 91精品国产高清久久久久久国产嫩草| 久久国产乱子伦免费精品| 色欲久久久天天天综合网| 青草国产精品久久久久久| 九九久久自然熟的香蕉图片| 久久人妻少妇嫩草AV无码专区| 久久精品无码一区二区无码| 久久久久亚洲av无码专区喷水| 久久精品无码午夜福利理论片| 国产精品久久毛片完整版| 日韩欧美亚洲综合久久影院d3| 久久免费香蕉视频| 亚洲伊人久久精品影院| 99精品久久精品一区二区| 91精品观看91久久久久久| 无码人妻久久一区二区三区蜜桃| 伊人色综合九久久天天蜜桃| 色婷婷综合久久久久中文一区二区 | 韩国三级中文字幕hd久久精品| 久久久久国产精品麻豆AR影院 | 色天使久久综合网天天| AV无码久久久久不卡蜜桃| 久久久久久久久无码精品亚洲日韩 | 久久综合鬼色88久久精品综合自在自线噜噜| 久久强奷乱码老熟女| 亚洲AV乱码久久精品蜜桃| 国产精品免费看久久久香蕉| 久久99九九国产免费看小说| 国产成人精品免费久久久久| 久久精品亚洲欧美日韩久久| 久久久精品人妻一区二区三区蜜桃 |