按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
#0070 lpEntry = pMessageMap…》lpEntries;
#0071 while ((lpEntry = AfxFindMessageEntry (lpEntry; 0xC000; 0; 0))
#0072 != NULL)
#0073 {
#0074 UINT* pnID = (UINT*)(lpEntry…》nSig);
#0075 ASSERT(*pnID 》= 0xC000);
#0076 // must be successfully registered
#0077 if (*pnID == message)
#0078 {
#0079 msgCache。lpEntry = lpEntry;
#0080 goto LDispatchRegistered;
#0081 }
#0082 lpEntry++; // keep looking past this one
#0083 }
#0084 }
#0085 }
#0086 msgCache。lpEntry = NULL;
#0087 return FALSE;
#0088 }
#0089 ASSERT(FALSE); // not reached
#0090
#0091 LDispatch:
#0092 union MessageMapFunctions mmf;
#0093 mmf。pfn = lpEntry…》pfn;
#0094
#0095 switch (lpEntry…》nSig)
#0096 {
#0097 case AfxSig_bD:
#0098 lResult = (this…》*mmf。pfn_bD)(CDC::FromHandle((HDC)wParam));
#0099 break;
#0100
#0101 case AfxSig_bb: // AfxSig_bb; AfxSig_bw; AfxSig_bh
#0102 lResult = (this…》*mmf。pfn_bb)((BOOL)wParam);
#0103 break;
#0104
569
…………………………………………………………Page 632……………………………………………………………
第篇 深入 MFC 程式設計
#0105 case AfxSig_bWww: // really AfxSig_bWiw
#0106 lResult = (this…》*mmf。pfn_bWww)(CWnd::FromHandle((HWND)wParam);
#0107 (short)LOWORD(lParam); HIWORD(lParam));
#0108 break;
#0109
#0110 case AfxSig_bHELPINFO:
#0111 lResult = (this…》*mmf。pfn_bHELPINFO)((HELPINFO*)lParam);
#0112 break;
#0113
#0114 case AfxSig_is:
#0115 lResult = (this…》*mmf。pfn_is)((LPTSTR)lParam);
#0116 break;
#0117
#0118 case AfxSig_lwl:
#0119 lResult = (this…》*mmf。pfn_lwl)(wParam; lParam);
#0120 break;
#0121
#0122 case AfxSig_vv:
#0123 (this…》*mmf。pfn_vv)();
#0124 break;
#0125 。。。
#0126 }
#0127 goto LReturnTrue;
#0128
#0129 LDispatchRegistered: // for registered windows messages
#0130 ASSERT(message 》= 0xC000);
#0131 mmf。pfn = lpEntry…》pfn;
#0132 lResult = (this…》*mmf。pfn_lwl)(wParam; lParam);
#0133
#0134 LReturnTrue:
#0135 if (pResult != NULL)
#0136 *pResult = lResult;
#0137 return TRUE;
#0138 }
#0001 AfxFindMessageEntry (const AFX_MSGMAP_ENTRY* lpEntry;
#0002 UINT nMsg; UINT nCode; UINT nID)
#0003 {
#0004 #if defined(_M_IX86) && !defined(_AFX_PORTABLE)
#0005 // 32…bit Intel 386/486 version。
#0006 。。。 //以汇编语言码处理,加快速度。
#0007 #else // _AFX_PORTABLE
#0008 // C version of search routine
#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