友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

深入浅出MFC第2版(PDF格式)-第144章

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




                   { 

                     LRESULT lResult; 

                     。。。 

                     TRY 

                     { 

                        。。。 

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

                     } 

                     。。。 

                     return lResult; 

                   } 



                  MFC 2。5  的CWinApp::Run 调用PumpMessage ,后者又调用::DispatchMessage ,把消息源 



                  源推往AfxWndProc    (如上),最后流向pWnd…》WindowProc  去。拿SDK 程序的本质来 



                  做比对,这样的逻辑十分容易明白。 



                  MFC 4。x 仍旧使用AfxWndProc  作为消息唧筒的起点,但其间却隐藏了许多关节。 



                  但愿你记忆犹新,第6章曾经说过,MFC 4。x 适时地为我们注册Windows 窗口类别(在 



                  第一次产生该种型式之窗口之前)。这些个Windows 窗口类别的窗口函数各是「窗口所 



                  对应之C++ 类别中的DefWindowProc 成员函数」,请参考第 6章 「CFrameWnd::Create 



                  产生主窗口」一节。这就和MFC 2。5  的作法(所有窗口类别共享同一个窗口函数)有了 



                  明显的差异。那么,推动消息的心脏,也就是CWinThread::PumpMessage  中调用 



                  的::DispatchMessage (请参考第 6章 「CWinApp::Run 程序生命的活水源头」一节), 



                  照说应该把消息唧到对应之C++ 类别的DefWindowProc 成员函数去。但是,我们发现 



                  MFC 4。x  中仍然保有和MFC 2。5 相同的AfxWndProc ,仍然保有AfxCallWndProc ,而且 



                  它们扮演的角色也没有变。 



562 


…………………………………………………………Page 625……………………………………………………………

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



事实上,MFC 4。x  利用hook ,把看似无关的动作全牵联起来了。所谓hook ,是Windows 



程序设计中的一种高阶技术。通常消息都是停留在消息队列中等待被所隶属之窗口抓 



取,如果你设立hook ,就可以更早一步抓取消息,并且可以抓取不属于你的消息,送往 



你设定的一个所谓「滤网函数(filter )」。 



请查阅Win32 API 手册中有关于SetWindowsHook 和SetWindowsHookEx 两函数,以获 



得更多的hook 信息。(可参考Windows 95           A Developer s Guide 一书第6章Hooks ) 



MFC 4。x  的hook 动作是在每一个CWnd 衍生类别之对象产生之际发生,步骤如下: 



// in WINCORE。CPP (MFC 4。x) 



// 请回顾第6章「CFrameWnd::Create产生主窗口」一节 



BOOL CWnd::CreateEx(。。。) 

 { 

     。。。 

     PreCreateWindow(cs);   // 第6章曾经详细讨论过此一函数。 

     AfxHookWindowCreate(this); 

     HWND hWnd = ::CreateWindowEx(。。。); 

     。。。 

 } 



                  (        ) 

 // in WINCORE。CPP  MFC 4。x 

void AFXAPI AfxHookWindowCreate(CWnd* pWnd) 

 { 

    。。。 

    pThreadState…》m_hHookOldCbtFilter =  ::SetWindowsHookEx(WH_CBT; 

            _AfxCbtFilterHook; NULL; ::GetCurrentThreadId()); 

    。。。 

 } 



 WH_CBT 是众多hook 类型中的一种,意味着安装一个puter…Based Training  (CBT ) 



 滤网函数。安装之后,Windows 系统在进行以下任何一个动作之前,会先调用你的滤网 



 函数: 



令一个窗口成为作用中的窗口(HCBT_ACTIVATE ) 



产生或摧毁一个窗口(HCBT_CREATEWND 、HCBT_DESTROYWND ) 



最大化或最小化一个窗口(HCBT_MINMAX ) 



                                                                                563 


…………………………………………………………Page 626……………………………………………………………

                    第篇    深入  MFC  程式設計 



                      搬移或缩放一个窗口(HCBT_MOVESIZE ) 



                      完成一个来自系统菜单的系统命令(HCBT_SYSTEMMAND ) 



                      从系统队列中移去一个鼠标或键盘消息 (HCBT_KEYSKIPPED  、 



                       HCBT_CLICKSKIPPED ) 



                    因此,经过上述hook 安装之后,任何窗口即将产生之前,滤网函数_AfxCbtFilterHook  一 



                    定会先被调用: 



                    _AfxCbtFilterHook(int code; WPARAM wParam; LPARAM lParam) 

                     { 

                        _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); 

                        if (code != HCBT_CREATEWND) 

                        { 

                                // wait for HCBT_CREATEWND just pass others on。。。 

                                return CallNextHookEx(pThreadState…》m_hHookOldCbtFilter; code; 

                                        wParam; lParam); 

                        } 

                        。。。 

                                if (!afxData。bWin31) 

                                { 

                                        // perform subclassing right away on Win32 

                                        _AfxStandardSubclass((HWND)wParam); 

                                } 

                                else 

                                { 

                                   。。。 

                                } 

                        。。。 

                        LRESULT lResult = CallNextHookEx(pThreadState…》m_hHookOldCbtFilter; code; 

                                wParam; lParam); 

                        return lResult; 

                     } 



                    void AFXAPI _AfxStandardSubclass(HWND hWnd) 

                     { 

                        。。。 

                        // subclass the window with standard AfxWndProc 

                        oldWndProc = (WNDPROC)SetWindowLong (hWnd; GWL_WNDPROC; 

                                (DWORD)AfxGetAfxWndProc ()); 

                     } 



                    WNDPROC AFXAPI AfxGetAfxWndProc() 

                     { 



564 


…………………………………………………………Page 627……………………………………………………………

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



    。。。 

    return &AfxWndProc; 

} 



啊,非常明显,上面的函数合力做了偷天换日的勾当:把「窗口所属之Windows 窗口类 



别」中所记录的窗口函数,改换为AfxWndProc 。于是,::DispatchMessage 就把消息源源 



推往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 



                                                                                   
返回目录 上一页 下一页 回到顶部 0 1
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!