按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
…………………………………………………………Page 642……………………………………………………………
第篇 深入 MFC 程式設計
罗塞达碑石:AfxSig_xx 的奥秘
大架构建立起来了,但我还没有很仔细地解释在消息映射「网」中的_messageEntries ''
数组内容。为什么消息经由推动引擎(上一节谈的那整套家伙)推过这些数组,就可以
找到它的处理例程?
Paul DiLascia 在他的文章(! ¨ Meandering Through the Maze of MFC Message and mand
Routing! ¨,Microsoft Systems Journal ,1995/07)中形容这些数组之内一笔一笔的记录像
是罗塞达碑石,呵呵,就靠它们揭开消息映射的最后谜底了。
罗塞达碑石(Rosetta Stone ),1799 年拿破仑远征埃及时,由一名官员在尼罗河口罗塞
达发现,揭开了古埃及象形文字之谜。石碑是黑色玄武岩,高114 公分,厚28 公分,宽
72 公分。经法国学者Jean…Francois Champollion 研究后,世人因得顺利研读古埃及文献。
消息映射表的每一笔记录是这样的形式:
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
内中包括一个Windows 消息、其控制组件ID 以及通告码(notification code ,对消息的
更多描述,例如EN_CHANGED 或CBN_DROPDIOWN 等)、一个签名记号、以及一个
CCmdTarget 衍生类别的成员函数。任何一个ON_ 宏会把这六个项目初始化起来。例
如:
#define ON_WM_CREATE ()
{ WM_CREATE; 0; 0; 0; AfxSig_is;
(AFX_PMSG)(AFX_PMSGW)(int (AFX_MSG_CALL CWnd::*)(LPCREATESTRUCT))OnCreate };
你看到了可怕的类型转换动作,这完全是为了保持类型安全(type…safe )。
580
…………………………………………………………Page 643……………………………………………………………
第9章 訊息映射與命令繞行
有一个很莫名其妙的东西:AfxSig_ 。要了解它作什么用,你得先停下来几分钟,想想另
一个问题:当上一节的推动引擎比对消息并发现吻合之后,就调用对应的处理例程,但
它怎么知道要交给消息处理例程哪些参数呢?要知道,不同的消息处理例程需要不同的
参数(包括个数和类型),而其函数指针(AFX_PMSG )却都被定义为这付德行:
typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);
这么简陋的信息无法表现应该传递什么样的参数,而这正是AfxSig_ 要贡献的地方。当
推动引擎比对完成,欲调用某个消息处理例程lpEntry…》pfn 时,动作是这样子地(出现
在CWnd::OnWndMsg 和DispatchCmdMsg 中):
union MessageMapFunctions mmf;
mmf。pfn = lpEntry…》pfn;
switch (lpEntry…》nSig)
{
case AfxSig_is:
lResult = (this…》*mmf。pfn_is)((LPTSTR)lParam);
break;
case AfxSig_lwl:
lResult = (this…》*mmf。pfn_lwl)(wParam; lParam);
break;
case AfxSig_vv:
(this…》*mmf。pfn_vv)();
break;
。。。
}
注意两样东西:MessageMapFunctions 和AfxSig_ 。AfxSig_ 定义于AFXMSG_。H 档:
enum AfxSig
{
AfxSig_end = 0; // 'marks end of message map'
AfxSig_bD; // BOOL (CDC*)
AfxSig_bb; // BOOL (BOOL)
AfxSig_bWww; // BOOL (CWnd*; UINT; UINT)
AfxSig_hDWw; // HBRUSH (CDC*; CWnd*; UINT)
AfxSig_hDw; // HBRUSH (CDC*; UINT)
581
…………………………………………………………Page 644……………………………………………………………
第篇 深入 MFC 程式設計
AfxSig_iwWw; // int (UINT; CWnd*; UINT)
AfxSig_iww; // int (UINT; UINT)
AfxSig_iWww; // int (CWnd*; UINT; UINT)
AfxSig_is; // int (LPTSTR)
AfxSig_lwl; // LRESULT (WPARAM; LPARAM)
AfxSig_lwwM; // LRESULT (UINT; UINT; CMenu*)
AfxSig_vv; // void (void)
AfxSig_vw; // void (UINT)
AfxSig_vww; // void (UINT; UINT)
AfxSig_vvii; // void (int; int) // wParam is ignored
AfxSig_vwww; // void (UINT; UINT; UINT)
AfxSig_vwii; // void (UINT; int; int)
AfxSig_vwl; // void (UINT; LPARAM)
AfxSig_vbWW; // void (BOOL; CWnd*; CWnd*)
AfxSig_vD; // void (CDC*)
AfxSig_vM; // void (CMenu*)
AfxSig_vMwb; // void (CMenu*; UINT; BOOL)
AfxSig_vW; // void (CWnd*)
AfxSig_vWww; // void (CWnd*; UINT; UINT)
AfxSig_vWp; // void (CWnd*; CPoint)
AfxSig_vWh; // void (CWnd*; HANDLE)
AfxSig_vwW; // void (UINT; CWnd*)
AfxSig_vwWb; // void (UINT; CWnd*; BOOL)
AfxSig_vwwW; // void (UINT; UINT; CWnd*)
AfxSig_vwwx; // void (UINT; UINT)
AfxSig_vs; // void (LPTSTR)
AfxSig_vOWNER; // void (int; LPTSTR); force return TRUE
AfxSig_iis; // int (int; LPTSTR)
AfxSig_wp; // UINT (CPoint)
AfxSig_wv; // UINT (void)
AfxSig_vPOS; // void (WINDOWPOS*)
AfxSig_vCALC; // void (BOOL; NCCALCSIZE_PARAMS*)
AfxSig_vNMHDRpl; // void (NMHDR*; LRESULT*)
AfxSig_bNMHDRpl; // BOOL (NMHDR*; LRESULT*)
AfxSig_vwNMHDRpl; // void (UINT; NMHDR*; LRESULT*)
AfxSig_bwNMHDRpl; // BOOL (UINT; NMHDR*; LRESULT*)
AfxSig_bHELPINFO; // BOOL (HELPINFO*)
AfxSig_vwSIZING; // void (UINT; LPRECT) …return TRUE
// signatures specific to CCmdTarget
AfxSig_cmdui; // void (CCmdUI*)
AfxSig_cmduiw; // void (CCmdUI*; UINT)
AfxSig_vpv; // void (void*)
AfxSig_bpv; // BOOL (void*)
582
…………………………………………………………Page 645……………………………………………………………
第9章 訊息映射與命令繞行
// Other aliases (based on implementation)
AfxSig_vwwh; // void (UINT; UINT; HANDLE)
AfxSig_vwp; // void (UINT; CPoint)
AfxSig_bw = AfxSig_bb; // BOOL (UINT)
AfxSig_bh = AfxSig_bb; // BOOL (HANDLE)
AfxSig_iw = AfxSig_bb; // int (UINT)
AfxSig_ww = AfxSig_bb; // UINT (UINT)
AfxSig_bv = AfxSig_wv; // BOOL (void)
AfxSig_hv = AfxSig_wv; // HANDLE (void)
AfxSig_vb = AfxSig_vw; // void (BOOL)
AfxSig_vbh = AfxSig_vww; // void (BOOL; HANDLE)
AfxSig_vbw = AfxSig_vww; // void (BOOL; UINT)
AfxSig_vhh = AfxSig_vww; // void (HANDLE; HANDLE)
AfxSig_vh = AfxSig_vw; // void (HANDLE)
AfxSig_viSS = AfxSig_vwl; // void (int; STYLESTRUCT*)