友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
深入浅出MFC第2版(PDF格式)-第106部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
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))
#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
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!