八宝书库 > 文学其他电子书 > 深入浅出MFC第2版(PDF格式) >

第116部分

深入浅出MFC第2版(PDF格式)-第116部分

小说: 深入浅出MFC第2版(PDF格式) 字数: 每页4000字

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!






推往AfxWndProc  去了。 



这种看起来很迂回又怪异的作法,是为了包容新的3D Controls                         (细节就容我省略了吧), 



并与MFC 2。5 兼容。下图把前述的hook 和subclassing 动作以流程图显示出来: 



  CFrameWnd::LoadFrame 

   CFrameWnd::LoadFrame 



    CFrameWnd::Create 

     CFrameWnd::Create 



      CWnd::CreateEx 

       CWnd::CreateEx                              安装WH_CBT hook ,设定滤网函数 



                                                   为_AfxCbtFilterHook 

                      AfxHookWindowCreate(this) 

                       AfxHookWindowCreate(this) 



                        ::SetWindowsHookEx(WH_CBT; _AfxCbtFilterHook ;。。。) 

                         ::SetWindowsHookEx(WH_CBT; _AfxCbtFilterHook ;。。。) 



     ::CreateWindowEx 

      ::CreateWindowEx 



                        _AfxCbtFilterHook     窗口产生之前一刻,由于曾安装过 

                         _AfxCbtFilterHook     WH_CBT hook,所以滤网函数 



                                              _AfxCbtFilterHook 会先被唤起。 

                       _AfxStandardSubclass 

                       _AfxStandardSubclass 



                     SetWindowLong(hWnd; GWL_WNDPROC;&AfxWndProc) 

                      SetWindowLong(hWnd; GWL_WNDPROC;&AfxWndProc) 



                                                             WND structure 

                                         subclassing 动作;改                   各种消息,来自 

                                           变窗口函数。              extra bytes ::DispatchMessage 



                message mapping and                                        的唧送,或由操作 

                   mand routing                                         系统直接送达。 



                (through message map)                                      CWL_WNDPROC 

                       。 

                                                             &AfxWndProc 



    message handler 

     message handler 



                                                                                         565 


…………………………………………………………Page 628……………………………………………………………

                  第篇    深入  MFC  程式設計 



                  不能稍息,我们还没有走出迷宫!AfxWndProc  只是消息两万五千里长征的第一站! 



           两万五千里长征消息的流动 



                  一个消息从发生到被攫取,直至走向它的归宿,是一条漫漫长路。上一节我们来到了漫 



                  漫长路的起头AfxWndProc ,这一节我要带你看看消息实际上如何推动。 



                  消息的流动路线已隐隐有脉络可寻, 此脉络是指由BEGIN_MESSAGE_MAP 和 



                  END_MESSAGE_MAP  以及许许多多ON_ WM_xxx 宏所构成的消息映射网。但是唧筒与 



                  方向盘是如何设计的?一切的线索还是要靠源代码透露: 



                                     (       ) 

                  // in WINCORE。CPP  MFC 4。x 

                  LRESULT CALLBACK AfxWndProc (HWND hWnd; UINT nMsg; WPARAM wParam; LPARAM lParam) 

                   { 

                          。。。 

                          // messages route through message map 

                          CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); 

                          return AfxCallWndProc (pWnd; hWnd; nMsg; wParam; lParam); 

                   } 



                  LRESULT AFXAPI AfxCallWndProc (CWnd* pWnd; HWND hWnd; UINT nMsg; 

                          WPARAM wParam = 0; LPARAM lParam = 0) 

                   { 

                      。。。 

                      // delegate to object's WindowProc 

                      lResult = pWnd…》WindowProc (nMsg; wParam; lParam); 

                      。。。 

                      return lResult; 

                   } 



                  整个MFC  中,拥有虚拟函数WindowProc 者包括CWnd、CControlBar、COleControl、 



                  COlePropertyPage、CDialog、CReflectorWnd、CParkingWnd。一般窗口(例如Frame 视 



                  窗、View 窗口)都衍生自CWnd,所以让我们看看CWnd::WindowProc。这个函数相当 



                  于C++  中的窗口函数: 



                                     (       ) 

                  // in WINCORE。CPP  MFC 4。x 

                  LRESULT CWnd::WindowProc (UINT message; WPARAM wParam; LPARAM lParam) 



566 


…………………………………………………………Page 629……………………………………………………………

                                                           第9章   訊息映射與命令繞行   



     { 

             // OnWndMsg does most of the work; except for DefWindowProc call 

             LRESULT lResult = 0; 

             if (!OnWndMsg (message; wParam; lParam; &lResult)) 

                     lResult = DefWindowProc (message; wParam; lParam); 

             return lResult; 

     } 



     LRESULT CWnd::DefWindowProc (UINT nMsg; WPARAM wParam; LPARAM lParam) 

     { 

         if (m_pfnSuper != NULL) 

                 return ::CallWindowProc(m_pfnSuper; m_hWnd; nMsg; wParam; lParam); 



         WNDPROC pfnWndProc; 

         if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL) 

                 return  ::DefWindowProc(m_hWnd; nMsg; wParam; lParam); 

         else 

                 return ::CallWindowProc(pfnWndProc; m_hWnd; nMsg; wParam; lParam); 

     } 



直线上溯(一般Windows 消息) 



     CWnd::WindowProc 调用的OnWndMsg 是用来分辨并处理消息的专职机构;如果是命令 



     消息,就交给Onmand 处理,如果是通告消息(Notification ),就交给OnNotify 处 



     理。WM_ACTIVATE  和WM_SETCURSOR 也都有特定的处理函数。而一般的Windows 讯 



     息,就直接在消息映射表中上溯,寻找其归宿(消息处理例程)。为什么要特别区隔出 



     命令消息WM_MAND 和通告消息WM_NOTIFY 两类呢?因为它们的上溯路径不 



     是那么单纯地只往父类别去,它们可能需要拐个弯。 



                               (        ) 

     #0001  // in WINCORE。CPP  MFC 4。0 

     #0002  BOOL CWnd::OnWndMsg (UINT message; WPARAM wParam; LPARAM lParam; LRESULT* pResult) 

     #0003  { 

     #0004      LRESULT lResult = 0; 

     #0005 

     #0006      // special case for mands 

     #0007      if (message == WM_MAND) 

     #0008      { 

     #0009          Onmand (wParam; lParam); 

     #0010          。。。 

     #0011      } 

     #0012 



                                                                                          567 


…………………………………………………………Page 630……………………………………………………………

                    第篇    深入  MFC  程式設計 



                    #0013      // special case for notifies 

                    #0014      if (message == WM_NOTIFY) 

                    #0015      { 

                    #0016          OnNotify (wParam; lParam; &lResult); 

                    #0017          。。。 

                    #0018      } 

                    #0019      。。。 

                    #0020      const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap(); 

                    #0021      UINT iHash; iHash = (LOWORD((DWORD)pMessageMap) ^ message) & (iHashMax…1); 

                    #0022      AfxLockGlobals(CRIT_WINMSGCACHE); 

                    #0023      AFX_MSG_CACHE msgCache; msgCache = _afxMsgCache'iHash'; 

                    #0024      AfxUnlockGlobals(CRIT_WINMSGCACHE); 

                    #0025 

                    #0026      const AFX_MSGMAP_ENTRY* lpEntry; 

                    #0027      if  (。。。)  //检查是否在chche 之中 

                    #0028      { 

                    #0029          // cache hit 

                    #0030          lpEntry = msgCache。lpEntry; 

                    #0031          if (lpEntry == NULL) 

                    #0032                  return FALSE; 

                    #0033 

                    #0034          // cache hit; and it needs to be handled 

                    #0035          if (message 《 0xC000) 

                    #0036                  goto LDispatch; 

                    #0037          else 

                    #0038                  goto LDispatchRegistered; 

                    #0039      } 

                    #0040      else 

                    #0041      { 

                    #0042          // not in cache; look for it 

                    #0043          msgCache。nMsg = message; 

                    #0044          msgCache。pMessageMap = pMessageMap; 

                    #0045 

                    #0046          for (/* pMessageMap already init'ed */; pMessageMap != NULL; 

                    #0047                  pMessageMap = pMessageMap…》pBaseMap) 

                    #0048          { 

                    #0049              //利用AfxFindMessageEntry 寻找消息映射表中 

                    #0050              //对应的消息处理例程。如果找到,再依nMsg 为一般消息 

                    #0051              // (《 0xC000)或自行注册之消息(》 0xC000)分别跳到 

                    #0052              // LDispatch: 或LDispatchRegistered: 去执行。 

                    #0053 

                    #0054              // Note: catch not so mon but fatal mistake!! 

                    #0055              //      BEGIN_MESSAGE_MAP(CMyWnd; CMyWnd) 

                    #0056 

                    #0057              if (message 《 0xC000) 

                    #0058              { 



568 


…………………………………………………………Page 631……………………………………………………………

                                                        第9章   訊息映射與命令繞行   



#0059                  // constant window message 

#0060                  if ((lpEntry = AfxFindMessageEntry (pMessageMap…》lpEntries; 

#0061                      message; 0; 0)) != NULL) 

#0062                  { 

#0063                      msgCache。lpEntry = lpEntry; 

#0064                      goto LDispatch; 

#0065                  } 

#0066              } 

#0067              else 

#0068              { 

#0069                  // registered windows message 

#0070                  lpEntry = pMessageMap…》lpEntries; 

#0071                  while ((lpEntry = AfxFindMessageEntry (lpEntry; 0xC000; 0; 

返回目录 上一页 下一页 回到顶部 0 0

你可能喜欢的