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

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

  • <strong id="5koa6"></strong>
  • MFC 重大缺陷及其改進方法

    發表于:2007-07-01來源:作者:點擊數: 標簽:
    MFC 重大 缺陷 及其改進方法 作者: Solomon () 日期: 2001/12/29 在侯老前輩的《深入淺出MFC2e》中,第九章是講述MFC是如何進行消息映射的。其中,侯老自扮西修斯(P418),引領讀者走入MFC消息唧筒的設計迷宮。但是,當我從迷宮走出時,卻經入了沉思。MFC真的

    MFC 重大缺陷及其改進方法

    作者: Solomon ()

    日期: 2001/12/29

      在侯老前輩的《深入淺出MFC2e》中,第九章是講述MFC是如何進行消息映射的。其中,侯老自扮西修斯(P418),引領讀者走入MFC消息唧筒的設計迷宮。但是,當我從迷宮走出時,卻經入了沉思。MFC真的做的如此之好嗎?有沒有什么缺陷?

      在講述MFC重大缺陷之前,我給大家講述一下關于子類化(SubClass)的兩種方法。子類化可是萬里長征的第一步(不是第一站 P421),第一步都走不穩,何來第一站?其一就是MFC使用的CBT Hook,在侯老的書中已經詳細說明,此處不再重復。另一種方法就是在 WM_NCCREATE 中進行子類化操作。WM_NCCREATE 是一個窗口接受到的第一個消息,能截獲他,就可以截獲其他消息,也就能沒有任何遺漏地處理任何消息了。如何進行呢?

      首先,我們必須知道一個指向窗口實例的指針。比如在 CWnd::Create()  中要調用API CreateWindow, 那么 this  就是指向窗口實例的指針.CWnd::Create()大致如下:

    CWnd::Create(char szWindowTitle, ......){
      char szXTitle[256];
      wsprintf("%ld:%s", (long)this, szWindowTitle);
      CreateWindowEx(.., szXTitle...);
    }
    注意 Title 改成了 Point to this(指向窗口實例的指針) 和原來Title 的組合。

    接著 WndProc 在 WM_NCCREATE中取得指針和并恢復原來的Title, 同時使用SetProp,把指向窗口實例的指針保存。最后,在WndProc 進行消息分發處理。WndProc大致如下:

    LRESULT WndProc(....) // 全局函數
    {
      static szTitle[256];
      if (message == WM_NCCREATE)
      {
        if( GetProp(hWnd, "ClassInstance") == NULL ) {
            //提取 指針 到 hClsInst(使用atol())
            //恢復 Title 到 szTitle
            // lParam->lpszWindowName 指向 szTitle
            SetProp(hWnd, (HANDLE)hClsInst);
        }
      }
      CWnd* p = (CWnd*)GetProp(hWnd, "ClassInstance");
      p->DisPatchMessage(...);

    這樣,窗口處理過程就被替換了。以上兩種方法都有一個問題。表現在那里呢?讓我們做個實驗。

      首先,建立一個基于對話框的MFC App,接著創建 CMyButton 繼承自CButton,然后,用ClassWizard添加OK按鈕的一個變量,類型為CMyButton。在 CMyButton 分別處理 WM_LBUTTONDOWM 和 WM_NCCREATE。在 WM_LBUTTONDOWM 中調用 MessageBox() 顯示信息,在 WM_NCCREATE 中什么也不做,直接調用基類的處理。運行該程序。按下OK按鈕,應該出現MessageBox()顯示的信息。這說明OK按鈕已經被子類化(SubClass)了?,F在,分別在 CMyButton 的 OnNcCreate 和 OnLButtonDown 中設置斷點,然后運行程序。你會驚訝的發現,程序沒有執行CMyButton 的OnNcCreate。為什么???

      到底為什么呢?其實,窗口的創建分為顯式和隱式兩種,通過調用CreateWindow, CreateWindowEx函數創建的窗口是顯式創建,可以使用前面提到的任何一種方法進行子類化,而不會損失對任何消息的截獲。而通過CreateDailog,DialogBox創建的窗口除了對話框本身是顯式創建,其含有的控件都是系統創建的,這樣,只有在該控件創建后才能被子類化,因此會損失對某些消息的截獲。

      問題既然發生了,就要改進。方法有兩種。

      其一,必須通過分析DialogTemplate手動創建子控件(FoxPro, VB 好像是這種形式)。需要改寫DoMadal, Create. 太復雜了。

      另一種方法比較方便。由于子控件的創建必須在主窗口的WM_CREATE之后,這樣,就給了我們一個子類化控件的機會。方法如下:

    1. 在對話框的WM_CREATE 中建立CBT, 傳入參數是 對話框的 CMyDlg 指針

    2. 在CBT中,判斷 創建的窗口是否為 CMyDlg 的子控件,如果是, 并且需要時就進行子類化操作。

    3. 在 WM_INITDIALOG 中銷毀CBT.

    4. CMyDlg中DDX_Control()必須注釋掉

      鑒于篇幅原因,源程序不在此處列出。如果大家有其他好的方法,請一起討論。

     


    原文轉自: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>