深入浅出MFC第2版(PDF格式)-第120部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
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*)
AfxSig_bwl = AfxSig_lwl;
AfxSig_vwMOVING = AfxSig_vwSIZING; // void (UINT; LPRECT) …return TRUE
};
MessageMapFunctions 定义于 WINCORE。CPP 档:
union MessageMapFunctions
{
AFX_PMSG pfn; // generic member function pointer
// specific type safe variants
BOOL (AFX_MSG_CALL CWnd::*pfn_bD)(CDC*);
BOOL (AFX_MSG_CALL CWnd::*pfn_bb)(BOOL);
BOOL (AFX_MSG_CALL CWnd::*pfn_bWww)(CWnd*; UINT; UINT);
BOOL (AFX_MSG_CALL CWnd::*pfn_bHELPINFO)(HELPINFO*);
HBRUSH (AFX_MSG_CALL CWnd::*pfn_hDWw)(CDC*; CWnd*; UINT);
HBRUSH (AFX_MSG_CALL CWnd::*pfn_hDw)(CDC*; UINT);
int (AFX_MSG_CALL CWnd::*pfn_iwWw)(UINT; CWnd*; UINT);
int (AFX_MSG_CALL CWnd::*pfn_iww)(UINT; UINT);
int (AFX_MSG_CALL CWnd::*pfn_iWww)(CWnd*; UINT; UINT);
int (AFX_MSG_CALL CWnd::*pfn_is)(LPTSTR);
LRESULT (AFX_MSG_CALL CWnd::*pfn_lwl)(WPARAM; LPARAM);
LRESULT (AFX_MSG_CALL CWnd::*pfn_lwwM)(UINT; UINT; CMenu*);
void (AFX_MSG_CALL CWnd::*pfn_vv)(void);
void (AFX_MSG_CALL CWnd::*pfn_vw)(UINT);
void (AFX_MSG_CALL CWnd::*pfn_vww)(UINT; UINT);
void (AFX_MSG_CALL CWnd::*pfn_vvii)(int; int);
void (AFX_MSG_CALL CWnd::*pfn_vwww)(UINT; UINT; UINT);
void (AFX_MSG_CALL CWnd::*pfn_vwii)(UINT; int; int);
583
…………………………………………………………Page 646……………………………………………………………
第篇 深入 MFC 程式設計
void (AFX_MSG_CALL CWnd::*pfn_vwl)(WPARAM; LPARAM);
void (AFX_MSG_CALL CWnd::*pfn_vbWW)(BOOL; CWnd*; CWnd*);
void (AFX_MSG_CALL CWnd::*pfn_vD)(CDC*);
void (AFX_MSG_CALL CWnd::*pfn_vM)(CMenu*);
void (AFX_MSG_CALL CWnd::*pfn_vMwb)(CMenu*; UINT; BOOL);
void (AFX_MSG_CALL CWnd::*pfn_vW)(CWnd*);
void (AFX_MSG_CALL CWnd::*pfn_vWww)(CWnd*; UINT; UINT);
void (AFX_MSG_CALL CWnd::*pfn_vWp)(CWnd*; CPoint);
void (AFX_MSG_CALL CWnd::*pfn_vWh)(CWnd*; HANDLE);
void (AFX_MSG_CALL CWnd::*pfn_vwW)(UINT; CWnd*);
void (AFX_MSG_CALL CWnd::*pfn_vwWb)(UINT; CWnd*; BOOL);
void (AFX_MSG_CALL CWnd::*pfn_vwwW)(UINT; UINT; CWnd*);
void (AFX_MSG_CALL CWnd::*pfn_vwwx)(UINT; UINT);
void (AFX_MSG_CALL CWnd::*pfn_vs)(LPTSTR);
void (AFX_MSG_CALL CWnd::*pfn_vOWNER)(int; LPTSTR); // force return TRUE
int (AFX_MSG_CALL CWnd::*pfn_iis)(int; LPTSTR);
UINT (AFX_MSG_CALL CWnd::*pfn_wp)(CPoint);
UINT (AFX_MSG_CALL CWnd::*pfn_wv)(void);
void (AFX_MSG_CALL CWnd::*pfn_vPOS)(WINDOWPOS*);
void (AFX_MSG_CALL CWnd::*pfn_vCALC)(BOOL; NCCALCSIZE_PARAMS*);
void (AFX_MSG_CALL CWnd::*pfn_vwp)(UINT; CPoint);
void (AFX_MSG_CALL CWnd::*pfn_vwwh)(UINT; UINT; HANDLE);
};
其实呢,真正的函数只有一个pfn ,但通过union,它有许多类型不同的形象。pfn _vv 代
表「参数为void ,传回值为void 」;pfn _lwl 代表「参数为wParam 和lParam,传回
值为LRESULT 」;pfn _is 代表「参数为LPTSTR 字符串,传回值为int」。
相当精致,但是也有点儿可怖,是不是?使用MFC 或许应该像吃蜜饯一样; 蜜饯很好
吃,但你最好不要看到蜜饯的生产过程!唔,我真的不知道!
无论如何,我把所有的神秘都揭开在你面前了。
山高月小 水落石出
584
…………………………………………………………Page 647……………………………………………………………
第9章 訊息映射與命令繞行
Scribble Step2 :UI 对象的变化
理论基础建立完毕,该是实作的时候。Step2 将新增三个菜单命令项,一个工具栏按钮,
并维护这些UI 对象的使用状态。
改变菜单
Step2 将增加一个【Pen 】菜单,其中有两个命令项目;并在【Edit 】菜单中增加一个【Clear
All 】命令项目:
【Pen/Thick Line 】:这是一个切换开关,允许设定使用粗笔或细笔。如果使用
者设定粗笔,我们将在这项目的旁边打个勾(所谓的checked );如果使用者
选择细笔(也就是在打勾的本项目上再按一下),我们就把勾号去除(所谓的
unchecked )。
【Pen/Pen Widths 】:这会唤起一个对话框,允许设定笔的宽度。对话框的设计
并不在本章范围,那是下一章的事。
【Edit/Clear All 】:清除目前作用之Document 资料。当然对应之View 窗口
内容也应该清干净。
Visual C++ 整合环境中的菜单编辑器拥有非常方便的鼠标拖放(drag and drop )功能,所
以做出上述的菜单命令项不是难事。不过这些命令项目还得经过某些动作,才能与程序
码关联起来发生作用,这方面ClassWizard 可以帮助我们。稍后我会说明这一切。
以下利用Visual C++ 整合环境中的菜单编辑器修改菜单:
585
…………………………………………………………Page 648……………………………………………………………
第篇 深入 MFC 程式設計
激活菜单编辑器(请参考第4章)。Scribble 有两份菜单,IDR_MAINFRAME
适用于没有任何子窗口的情况,IDR_SCRIBTYPE 适用于有子窗口的情况。我
们选择后者。
IDR_SCRIBTYPE 菜单内容出现于画面右半侧。加入新增的三个命令项。每个
命令项会获得一个独一无二的识别码,定义于RESOURCE。H 或任何你指定的
文件中。图下方的【Menu Item Properties 】对话框在你双击某个命令项后出现,
允许你更改命令项的识别码与提示字符串(将出现在状态列中)。如果你对操作
过程不熟练,请参考Visual C++ User's Guide (Visual C++ Online 上附有此书之
电子版)。
三个新命令项的ID 值以及提示字符串整理于下:
【 】
Pen/Thick Line
ID : ID_PEN_THICK_OR_THIN
prompt : 〃Toggles the line thickness between thin and thicknToggle pen〃
586
…………………………………………………………Page 649……………………………………………………………
第9章 訊息映射與命令繞行
【 】
Pen/Pen Widths
ID : ID_PEN_WIDTHS
prompt : 〃Sets the size of the thin and thick pennPen thickness〃
【 】
Edit/Clear All
ID : ID_EDIT_CLEAR_ALL (这是一个预先定义的ID,有预设的提示字符串,请更改如下)
prompt : 〃Clears the drawingnErase All〃
注意:每一个提示字符串都有一个n 子字符串,那是作为工具栏按钮的「小黄卷标」
的卷标内容。「小黄卷标」(学名叫作tool tips)是Windows 95 新增的功能。
对Framework 而言,命令项的ID 是用以识别命令消息的唯一依据。你只需在【Properties 】
对话框中键入你喜欢的ID 名称(如果你不满意菜单编辑器自动给你的那个),至于它真
正的数值不必在意,菜单编辑器会在你的RESOURCE。H 档中加上定义值。
经过上述动作,菜单编辑器影响我们的程序代码如下:
// in RESOURCE。H
#define ID_PEN_THICK_OR_THIN 32772
#define ID_PEN_WIDTHS 32773
(注:另一个ID ID_EDIT_CLEAR_ALL 已预先定义于AFXRES。H 中)
// in SCRIBBLE。RC
IDR_SCRIBBTYPE MENU PRELOAD DISCARDABLE
BEGIN
。。。
POPUP 〃&Edit〃
BEGIN
。。。
MENUITEM 〃Clear &All〃; ID_EDIT