• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • Visual C++模態對話框消息處理機制的分析

    發表于:2007-05-25來源:作者:點擊數: 標簽:模態C++對話框visual消息
    摘要: 消息驅動機制是 Windows操作系統 的根本,模態對話框消息處理又是不同于一般消息處理的特殊形式。通過分析這種消息機制的原理,可用來處理類似的 程序設計 要求。 在Windows操作系統中,面向用戶的GUI基本上可分為對話框形式和文檔/視圖兩種表現形式

      摘要:消息驅動機制是Windows操作系統的根本,模態對話框消息處理又是不同于一般消息處理的特殊形式。通過分析這種消息機制的原理,可用來處理類似的程序設計要求。

      在Windows操作系統中,面向用戶的GUI基本上可分為對話框形式和文檔/視圖兩種表現形式。對話框的顯示方式又可分為模態對話框和非模態對話框,以適應不同的用戶交互需求。由于對話框和文檔/視圖框架結構各有特色,能不能將文檔/視圖框架結構當作一對話框來使用,或在對話框中實現文檔/視圖框架結構內的特色功能呢,答案是肯定的。

      下面,從Windows 操作系統消息驅動機制開始,進而探討模態對話框實現過程的消息封裝、傳遞和處理機制,最后以模態的形式顯示應用到文檔/視圖框架結構中的實例作為對所講內容的驗證和實踐。

      一、Windows消息機制

      Windows是一種面向對象的體系結構,Windows環境和應用程序都是通過消息來交互的。Windows應用程序開始執行后,Windows為該程序創建一個"消息隊列(message queue)",用以存放郵寄給該程序可能創建的各種不同窗口的消息。消息隊列中消息的結構(MSG)為:

    typedef struct tagMSG{
     HWND hwnd;
     UINT message;
     WPARAM wParam;
     LPARAM lParam;
     DWORD time;
     POINT pt;
    }MSG;

      其中第一個成員變量是用來標識接收消息的窗口句柄;第二個參數便是消息標識號,如WM_PAINT;第三個和第四個參數的具體意義同message值有關,均為消息參數。前四個參數是非常重要和經常用到的,至于后兩個參數則分別表示郵寄消息的時間和光標位置(屏幕坐標)。把消息傳送到應用程序有兩種方法:一種是由系統將消息"郵寄(post)"到應用程序的"消息隊列"這是"進隊消息"Win32 API有對應的函數: PostMessage(),此函數不等待該消息處理完就返回;而另一種則是由系統在直接調用窗口函數時將消息"發送(send)"給應用程序的窗口函數,屬于"不進隊消息"對應的函數是SendMessage()其必須等待該消息處理完后方可返回。

      對于每一個正在執行的Windows應用程序,系統為其建立一個"消息隊列",即應用程序隊列,用來存放該程序可能創建的各種窗口的消息。應用程序中含有一段稱作"消息循環"的代碼,用來從消息隊列中檢索這些消息并把它們分發到相應的窗口函數中。

      消息循環代碼是應用程序中主函數winmain ( )中類似如下的程序段:

      while(GetMessage(&&msg,NULL,NULL,NULL))
      { file://從消息隊列中取得消息
       TranslateMessage(&&msg);
       file://檢索并生成字符消息WM_CHAR
       DispatchMessage(&&msg);
       file://將消息發送給相應的窗口函數
       }

      由此可見,所謂"消息循環",實際是程序循環。

      Windows 應用程序創建的每個窗口都在系統核心注冊一個相應的窗口函數,窗口函數程序代碼形式上是一個巨大的switch 語句,用以處理由消息循環發送到該窗口的消息,窗口函數由Windows 采用消息驅動的形式直接調用,而不是由應用程序顯示調用的,窗口函數處理完消息后又將控制權返回給Windows。



      二、模態對話框的消息處理

      由上面我們看到,Windows是一個巨大的消息驅動結構,由用戶發出消息,系統響應處理。非模態對話框是響應一個消息,系統處理一個消息,處理完畢后返回控制權給Windows。文檔/視圖框架結構與其類似。模態對話框在對話框創建后,掛起外部的消息,只是響應對話框內部的消息,而外部消息則全部"過濾"掉了,直到系統接收到WM_DESTROY或WM_CLOSE后,系統返回控制權給模態對話框創建前的線程,繼續模態對話框創建前的線程將執行下面的代碼。

      讓我們看看下面的對話框DoModal實現代碼:

    {
     … …
     // Disable 父窗口 (在創建對話框前)
     HWND hWndParent = PreModal();
     AfxUnhookWindowCreate();
     BOOL bEnableParent = FALSE;
     if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
     {
      ::EnableWindow(hWndParent, FALSE);
      bEnableParent = TRUE;
     }
     TRY
     {
      // 創建模態對話框
      AfxHookWindowCreate(this);
      if (CreateDlgIndirect(lpDialogTemplate,CWnd::FromHandle(hWndParent), hInst))
      {
       if (m_nFlags & WF_CONTINUEMODAL)
       {
        // 進入模式循環
        DWORD dwFlags = MLF_SHOWONIDLE;
        if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG;
          VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
       }
      }
     }
     CATCH_ALL(e)
     {
      DELETE_EXCEPTION(e);
      m_nModalResult = -1;
     }
     END_CATCH_ALL
     file://Enable 父窗口
     if (bEnableParent)
      ::EnableWindow(hWndParent, TRUE);
      if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
       ::SetActiveWindow(hWndParent);
       // 刪除對話框
       DestroyWindow();
       PostModal();
       … …
     }

      可以看到,在此實現代碼中,并沒有開辟新的線程。系統是在RunModalLoop()中進行消息循環。當 m_nFlags 為 WF_CONTINUEMODAL時,系統繼續模式狀態。RunModalLoop()函數實際上也是一for(;;)循環,控制重新分派Windows消息。直到ContinueModal()返回FALSE,而當調用EndModalLoop()時,ContinueModal()返回FALSE。此時,標志著模態顯示的結束。因此,實現模態對話框消息處理的核心部分為RunModalLoop()和EndModalLoop()函數。

      三、以模態的形式顯示應用到文檔/視圖框架結構實例

     ?。?)新建一工程文件:ModeFrame,選取MFC AppWizard(exe)。

     ?。?)第二步選取Single document(單文檔)。

     ?。?)其余幾步均為缺省值。

     ?。?)用ClassWizard添加一新類CSubModeFrame,以CFrameWnd為基類。

     ?。?)添加CsubModeFrame的實現函數DoMode();

    int CsubModeFrame::DoModal()
    {
     HWND hWndParent = m_hWndPrt;
     CRect rc(0,0,400,400);
     CWnd *pParent = CWnd::FromHandle(hWndParent);
     DWORD dwStyle=WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_THICKFRAME |  WS_VISIBLE | WS_SYSMENU | WS_CAPTION;
     if(!Create(NULL,"模態文檔/試圖框架 ",dwStyle,rc,pParent,NULL)) return FALSE;
      BOOL bEnableParent = FALSE;
      if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
      {
       ::EnableWindow(hWndParent,FALSE);
       ::EnableWindow(m_hWnd,TRUE);
       bEnableParent = TRUE;
      }
      CenterWindow();
      TRY
      {
       // enter modal loop
       DWORD dwFlags = MLF_SHOWONIDLE;
       if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG;
        VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
      }
      CATCH_ALL(e)
      {
       DELETE_EXCEPTION(e);
       m_nModalResult = -1;
      }
      END_CATCH_ALL
     
     if (bEnableParent)
      ::EnableWindow(hWndParent, TRUE);
      if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
       ::SetActiveWindow(hWndParent);
       // destroy modal window
       DestroyWindow();
       return m_nModalResult;
     }

     ?。?)添加CsubModeFrame的實現函數EndMode()

    void CSubFrame::EndModal(){
     ASSERT(::IsWindow(m_hWnd));
     if (m_nFlags & (WF_MODALLOOP|WF_CONTINUEMODAL)) {
      EndModalLoop(1);
     }
    }

     ?。?)添加CModeFrameView的實現函數OnLButtonDblClk()

      在此函數的消息處理中:可以象顯示對話框一樣處理CsubModeFrame類。

    CSubModeFrame SubModeFrame;
    If(SubModeFrame.DoMode()){ MessageBox("Mode Ok");}

     ?。?)編譯運行工程,雙擊視圖,就會彈出模態的子文檔/視圖框架結構

      結論: 通過上面的分析和實例可以看出,深入研究了解Windows的消息處理機制,可利用消息對Windows的事件進行任意的定制和處理,不用拘泥于系統原有的模式。對進行深入Windows編程是很有必要的。

    原文轉自:http://www.kjueaiud.com

    評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>