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

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

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






                                                                                                                         559 


…………………………………………………………Page 622……………………………………………………………

             第篇    深入  MFC  程式設計 



              要知道,虚拟函数必须经由一个虚拟函数表(virtual function table ,vtable )实作出来,每 



              一个子类别必须有它自己的虚拟函数表,其内至少有父类别之虚拟函数表的内容复本(请 



              参考第2章「类别与对象大解剖」一节)。好哇,虚拟函数表中的每一个项目都是一个 



              函数指针,价值4 字节,如果基础类别的虚拟函数表有100 个项目,经过10 层继承, 



              开枝散叶,总共需耗费多少内存在其中?最终,系统会被巨大的额外负担(overhead ) 



              拖垮! 



              这就是为什么MFC 采用独特的消息映射机制而不采用虚拟函数的原因。 



        米诺托斯 (Minotauros)与西修斯 (Theseus) 



             截至目前我还有一些细节没有交待清楚,像是消息的比对动作、消息处理例程的调用动 



             作、以及参数的传递等等,但至少现在可以先继续进行下去,我的目标瞄准消息唧筒(叫 



             邦浦也可以啦)。 



             窗口接收消息后,是谁把消息唧进消息映射网中?是谁决定消息该直直往父映射表走 



             去?还是拐向另一条路(请回头看看图9…2 )?消息的绕行路线,以及MFC  的消息唧 



             筒的设计,活像是米诺托斯的迷宫。不过别担心,我将扮演西修斯,让你免遭毒手。 



             米诺托斯(Minotauros ),希腊神话里牛头人身的怪兽,为克里特岛国王迈诺斯之妻所生。 



             迈诺斯造迷宫将米诺托斯藏于其中,每有人误入迷宫即遭吞噬。怪兽后为雅典王子西修 



             斯(Theseus )所杀。 



             MFC 2。5 (注意,是2。5 而非4。x)曾经在WinMain 的第一个重要动作AfxWinInit 



             之中, 自动为程序注册四个Windows 窗口类别, 并且把窗口函数一致设为 



             AfxWndProc : 



560 


…………………………………………………………Page 623……………………………………………………………

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



//in APPINIT。CPP (          ) 

                    MFC 2。5 

BOOL AFXAPI AfxWinInit (HINSTANCE hInstance; HINSTANCE hPrevInstance; 

                       LPSTR lpCmdLine; int nCmdShow) 

{ 

     。。。 

     // register basic WndClasses  (以下开始注册窗口类别) 

     WNDCLASS wndcls; 

     wndcls。lpfnWndProc = AfxWndProc; 



     // Child windows no brush; no icon; safest default class styles 

     。。。 

     wndcls。lpszClassName = _afxWnd; 

   if (! ::RegisterClass(&wndcls)) 

             return FALSE; 



     // Control bar windows 

     。。。 

     wndcls。lpszClassName = _afxWndControlBar; 

   if (! ::RegisterClass(&wndcls)) 

             return FALSE; 



     // MDI Frame window (also used for splitter window) 

     。。。 

  if (!RegisterWithIcon (&wndcls; _afxWndMDIFrame; AFX_IDI_STD_MDIFRAME)) 

             return FALSE; 



     // SDI Frame or MDI Child windows or views normal colors 

     。。。 

  if (!RegisterWithIcon (&wndcls; _afxWndFrameOrView; AFX_IDI_STD_FRAME)) 

             return FALSE; 

     。。。 

} 



下面是AfxWndProc  的内容: 



// in WINCORE。CPP (          ) 

                     MFC 2。5 

LRESULT CALLBACK AFX_EXPORT 

AfxWndProc (HWND hWnd; UINT message; WPARAM wParam; LPARAM lParam) 

{ 

  CWnd* pWnd; 



  pWnd = CWnd::FromHandlePermanent(hWnd); 

  ASSERT(pWnd != NULL); 

  ASSERT(pWnd…》m_hWnd == hWnd); 



                                                                                      561 


…………………………………………………………Page 624……………………………………………………………

                   第篇    深入  MFC  程式設計 



                     LRESULT lResult = _AfxCallWndProc (pWnd; hWnd; message; wParam; lParam); 

                     return lResult; 

                   } 



                   // Official way to send message to a CWnd 

                   LRESULT PASCAL _AfxCallWndProc (CWnd* pWnd; HWND hWnd; UINT message; 

                                                  WPARAM wParam; LPARAM lParam) 

                   { 

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