按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
#0009 while (lpEntry…》nSig != AfxSig_end)
#0010 {
#0011 if (lpEntry…》nMessage == nMsg && lpEntry…》nCode == nCode &&
570
…………………………………………………………Page 633……………………………………………………………
第9章 訊息映射與命令繞行
#0012 nID 》= lpEntry…》nID && nID nLastID)
#0013 {
#0014 return lpEntry;
#0015 }
#0016 lpEntry++;
#0017 }
#0018 return NULL; // not found
#0019 #endif // _AFX_PORTABLE
#0020 }
直线上溯的逻辑实在是相当单纯的了,唯一做的动作就是比对消息映射表,如果吻合就
调用表中项目所记录的函数。比对的对象有二,一个是原原本本的消息映射表(那个巨
大的结构),另一个是MFC 为求快速所设计的一个cache (cache 的实作太过复杂,我并
没有把它的源代码表现出来)。比对成功后,调用对应之函数时,有一个巨大的switch/case
动作,那是为了确保类型安全(type…safe )。稍后我有一个小节详细讨论之。
CWinThread CWinApp CMyWinApp
这就是在CMyView 窗口
所发生的WM_PAINT消
; ; ; ; ; ; ; ; ; ; 息的流动路线
0;0;0;0;0;0 0;0;0;0;0;0
CView CMyView
m
e
CCmdTarget CWnd CFrameWnd CMyFrameWnd
s
; ; ; ; ; ; ; ; ; ;
s
0;0;0;0;0;0 0;0;0;0;0;0 a
; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; g
0;0;0;0;0;0 0;0;0;0;0;0 0;0;0;0;0;0 e
0;0;0;0;0;0
CDocument CMyDocument
; ; ; ; ; ; ; ; ; ;
0;0;0;0;0;0 0;0;0;0;0;0
图9…3 当WM_PAINT 发生于View 窗口, 消息的流动路线。
571
…………………………………………………………Page 634……………………………………………………………
第篇 深入 MFC 程式設計
拐弯上溯(WM_MAND 命令消息)
如果消息是WM_MAND,你看到了,CWnd::OnWndMsg (上节所述)另辟蹊跷,交
由Onmand 来处理。这并不一定就指的是CWnd::Onmand,得视this 指针指向
哪一种对象而定。在MFC 之中,以下数个类别都改写了Onmand 虚拟函数:
class CWnd : public CCmdTarget
class CFrameWnd : public CWnd
class CMDIFrameWnd : public CFrameWnd
class CSplitterWnd : public CWnd
class CPropertySheet : public CWnd
class COlePropertyPage : public CDialog
我们挑一个例子来看。假设消息是从CFrameWnd 进来的好了,于是:
( )
// in FRMWND。CPP MFC 4。0
BOOL CFrameWnd::Onmand (WPARAM wParam; LPARAM lParam)
{
。。。
// route as normal mand
return CWnd::Onmand (wParam; lParam);
}
( )
// in WINCORE。CPP MFC 4。0
BOOL CWnd::Onmand (WPARAM wParam; LPARAM lParam)
{
。。。
return OnCmdMsg (nID; nCode; NULL; NULL);
}
这里调用的OnCmdMsg 并不一定就是指CWnd::OnCmdMsg,得看this 指针指向哪一种
对象而定。目前情况是指向一个CFrameWnd 对象,而MFC 之中「拥有」OnCmdMsg 的
类别(注意,此话有语病,我应该说MFC 之中「曾经改写」过OnCmdMsg 的类别)是:
class CCmdTarget : public CObject
class CFrameWnd : public CWnd
class CMDIFrameWnd : public CFrameWnd
class CView : public CWnd
class CPropertySheet : public CWnd
class CDialog : public CWnd
class CDocument : public CCmdTarget
class COleDocument : public CDocument
572
…………………………………………………………Page 635……………………………………………………………
第9章 訊息映射與命令繞行
显然我们应该往CFrameWnd 追踪:
( )
// in FRMWND。CPP MFC 4。0
BOOL CFrameWnd::OnCmdMsg (UINT nID; int nCode; void* pExtra;
AFX_CMDHANDLERINFO* pHandlerInfo)
{
// pump through current view FIRST
CView* pView = GetActi