友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
深入浅出MFC第2版(PDF格式)-第10部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
息以及消息处理例程的关联性建立起来:
// 消息与处理例程之对照表格
struct MSGMAP_ENTRY _messageEntries'' =
{
WM_CREATE; OnCreate;
WM_PAINT; OnPaint;
WM_SIZE; OnSize;
WM_MAND; Onmand;
WM_SETFOCUS; OnSetFocus;
WM_CLOSE; OnClose;
WM_DESTROY; OnDestroy;
} ; ↑ ↑
这是消息 这是消息处理例程
20
…………………………………………………………Page 83……………………………………………………………
// mand…ID
与处理例程之对照表格
struct MSGMAP_ENTRY _mandEntries =
{
IDM_ABOUT; OnAbout;
IDM_FILEOPEN; OnFileOpen;
IDM_SAVEAS; OnSaveAs;
} ; ↑ ↑
这是WM_MAND 命令项这是命令处理例程
于是窗口函数可以这么设计:
//………………………………………………………………………………………………………………………………………………………………………………………
// 窗口函数
//………………………………………………………………………………………………………………………………………………………………………………………
LRESULT CALLBACK WndProc(HWND hWnd; UINT message;
WPARAM wParam; LPARAM lParam)
{
int i;
for(i=0; i 《 dim(_messageEntries); i++) { //
消息对照表
if (message == _messageEntries'i'。nMessage)
return((*_messageEntries'i'。pfn)(hWnd; message; wParam; lParam));
}
return(DefWindowProc(hWnd; message; wParam; lParam));
}
//………………………………………………………………………………………………………………………………………………………………………………………
// Onmand …
专门处理 WM_MAND
//………………………………………………………………………………………………………………………………………………………………………………………
LONG Onmand(HWND hWnd; UINT message;
WPARAM wParam; LPARAM lParam)
{
int i;
for(i=0; i 《 dim(_mandEntries); i++) { //
命令项目对照表
if (LOWORD(wParam) == _mandEntries'i'。nMessage)
return((*_mandEntries'i'。pfn)(hWnd; message; wParam; lParam));
}
return(DefWindowProc(hWnd; message; wParam; lParam));
}
//………………………………………………………………………………………………………………………………………………………………………………………
LONG OnCreate(HWND hWnd; UINT wMsg; UINT wParam; LONG lParam)
{
。。。
}
21
…………………………………………………………Page 84……………………………………………………………
//………………………………………………………………………………………………………………………………………………………………………………………
LONG OnAbout (HWND hWnd; UINT wMsg; UINT wParam; LONG lParam)
{
。。。
}
//………………………………………………………………………………………………………………………………………………………………………………………
这么一来,WndProc 和Onmand 永远不必改变,每有新要处理的消息,只要在
_messageEntries ' ' 和_mandEntries ' ' 两个数组中加上新元素,并针对新消息撰写新
的处理例程即可。
这种观念以及作法就是MFC 的Message Map 的雏形。MFC 把其中的动作包装得更好
更精致(当然因此也就更复杂得多),成为一张庞大的消息地图;程序一旦获得消息,
就可以按图上溯,直到被处理为止。我将在第3章简单仿真MFC 的Message Map ,并在
第9章「消息映射与绕行」中详细探索其完整内容。
对话框的运作
Windows 的对话框依其与父窗口的关系,分为两类:
modal
1。 「令其父窗口除能,直到对话框结束」,这种称为 对话框。
modeless
2。 「父窗口与对话框共同运行」,这种称为 对话框。
modal Generic ! §About ! ¨
比较常用的是 对话框。我就以 的 对话框做为说明范例。
为了做出一个对话框,程序员必须准备两样东西:
dialog template RC
1。 对话框模板( )。这是在 文件中定义的一个对话框外貌,以各
。。。
种方式决定对话框的大小、字形、内部有哪些控制组件、各在什么位置 等等。
2。 对话框函数(dialog procedure )。其类型非常类似窗口函数,但是它通常只处
WM_INITDIAL OG WM MAND
_
理 和 两个消息。对话框中的各个控制组件也
都是小小窗口,各有自己的窗口函数,它们以消息与其管理者(父窗口,也就
WM MAND
_
是对话框)沟通。而所有的控制组件传来的消息都是 ,再由其
参数分辨哪一种控制组件以及哪一种通告(notification )。
22
…………………………………………………………Page 85……………………………………………………………
Modal 对话框的激活与结束,靠的是DialogBox 和EndDialog 两个API 函数。请看
图1…4。
TR UE FALSE
对话框处理过消息之后,应该传回 ;如果未处理消息,则应该传回 。这是
FALSE
因为你的对话框函数之上层还有一个系统提供的预设对话框函数。如果你传回 ,
该预设对话框函数就会接手处理。
Dialog Templatet in RC file。
对话框模板 ( ),
AboutBox DIALOG DISCARDABLE 22; 17; 144; 75
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION 〃About Generic〃
BEGIN
CTEXT 〃Windows 95〃; …1;0; 5;144;8
CTEXT 〃Generic Application〃;…1;0;14;144;8
1 DialogBox 打开一个对话框: CTEXT 〃Version 1。0〃; …1;0;34;144;8
DEFPUSHBUTTON 〃OK〃; IDOK;53;59;32;14;WS_GROUP
END
DialogBox(_hInst;
〃AboutBox〃; // 对话框模板名称
hWnd; // 父窗口
(DLGPROC)About // 对话框函数名称
);
2 控制权转到对话框函数
LRESULT CALLBACK About(HWND hDlg; UINT message;
4 WPARAM wParam; LPARAM lParam)
{
对 UNREFERENCED_ PARAMETER(lParam); // 避免編译时的警告
话
框 switch (message) {
结 case WM_INITDIALOG:
束 return (TRUE); // TRUE 表示我已处理过这个消息
,
case WM_MAND:
回 if (LOWORD(wParam) == IDOK 对话框內部自有一个消息
返 || LOWORD(wParam) == IDCANCEL) { 3 回路(由系統维护)
EndDialog(hDlg; TRUE);
return (TRUE); // TRUE 表示我已处理过这个消息
} 当使用者按下 'OK' 钮,产生
break; WM_MAND 命令消息,
} 识别码为IDOK,于是流往
return (FALSE); // FALSE 表示我没有处理这个消息
}
图 1…4 对话框的诞生、运作、结束
23
…………………………………………………………Page 86……………………………………………………………
模块定义文件 ( )
。DEF
Windows 程序需要一个模块定义文件,将模块名称、程序节区和资料节区的内存特性、
heap stack callback 。。。
模块堆积( )大小、堆栈( )大小、所有 函数名称 等等登记下来。下
面是个实例:
NAME Generic
DESCRIPTION 'Generic Sample'
EXETYPE WINDOWS
STUB 'WINSTUB。EXE'
CODE PRELOAD DISCARDABLE
DATA PRELOAD MOVEABLE MULTIPLE
HEAPSIZE 4096
STACKSIZE 10240
EXPORTS
MainWndProc @1
AboutBox @2
在Visual C++ 整合环境中开发程序,不再需要特别准备。DEF 文件,因为模块定义文件中的
设定都有默认值。模块定义文件中的STUB 指令用来指定所谓的stub 程序(埋在Windows
程序中的一个DOS 程序,你所看到的This Program Requires Microsoft Windows 或This
Program Can Not Run in DOS mode 就是此程序发出来的),Win16 允许程序员自设一个
stub 程序,但Win32 不允许,换句话说在Win32 之中Stub 指令已经失效。
资源描述档 ( )
。RC
RC 文件是一个以文字描述资源的地方。常用的资源有九项之多,分别是ICON 、CURSOR 、
BITMAP 、FONT、DIALOG、MENU 、ACCELERATOR 、STRING、VERSIONINFO 。还
可能有新的资源不断加入,例如Visual C++ 4。0 就多了一种名为TOOLBAR 的资源。这
些文字描述需经过RC 编译器,才产生可使用的二进制代码。本例Generic 示范ICON 、
MENU 和DIALOG 三种资源。
24
…………………………………………………………Page 87……………………………………………………………
Windows 程序的生与死
我想你已经了解Windows 程序的架构以及它与Windows 系统之间的关系。对
Windows 消息种类以及发生时机的透彻了解,正是程序设计的关键。现在我以窗口的诞
生和死亡,说明消息的发生与传递,以及应用程序的兴起与结束,请看图1…5 及图1…6。
WinMain(hInst; hPrev; 。。。)
{
MSG msg;
RegisterClass(。。。);
WM_CREATE
CreateWindow(。。。);
ShowWindow(。。。);
Message queue
UpdateWindow(。。。);
2 while(GetMessage(&msg。。。)) { 1
TranslateMessage(。。。);
DispatchMessage(。。。);
}
USER
return msg。wParam;
Module
WndProc(hwnd; msg; wParam; lParam) 3
{
switch (msg) {
case : 。。。
WM_CREATE
8 case WM_MAND: 。。。
WM_CLOSE
case WM_LBUTTONDOWN: 。。。
WM_QUIT
5 case WM_PAINT: 。。。
case WM_MOUSEMOVE: 。。。
case WM_DESTROY : 。。。
PostQuitMessage(0); 7
break;
default: return DefWindowProc (。。。);
WM_DESTROY }
return(0);
case WM_CLOSE :
} 6 case WM_CLOSE :
DestroyWindow(。。。);
DestroyWindow(。。。);
(in DefWindowProc)
图 1…5 窗口的生命周期(详细说明请看图 1…6 )
25
…………………………………………………………Page 88……………………………………………………………
1。 程序初始化过程中调用Create Window ,为程序建立了一个窗口,做为程序的萤
Create Window WM CREA TE
_
幕舞台。 产生窗口之后会送出 直接给窗口函数,
后者于是可以在此时机做些初始化动作(例如配置内存、开文件、读初始资
。。。
料 )。
2。 程序活着的过程中,不断以GetMessage 从消息贮列中抓取消息。如果这个消
WM QUIT GetMessage while
_ 0
息是 , 会传回 而结束 循环,进而结束整个程序。
3。 Dispat chMessage 透过Windows USER 模块的协助与监督,把消息分派至窗口
函数。消息将在该处被判别并处理。
4。 程序不断进行2。 和3。 的动作。
WM CLOSE
5。 当使用者按下系统菜单中的Close 命令项,系统送出 _ 。通常程序
Def WindowProc
的窗口函数不栏截此消息,于是 处理它。
Def WindowProc WM CLOSE Destroy Window
_
收到 后, 调用 把窗口清除。
6。
Destroy Window WM DESTROY
_
本身又会送出 。
WM DESTROY PostQuitMessage
_
7。 程序对 的标准反应是调用 。
PostQuitMessage WM QUIT
_
8。 没什么其它动作,就只送出 消息,准备让消息循
环
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!