首页 > 代码库 > MFC一些必要的名词(二)
MFC一些必要的名词(二)
- UI:Windows 程序分为「程序代码」和「UI(User Interface)资源」两大部份,两部份最后以RC
编译器整合为一个完整的EXE 文件( 图 1-1 )。所谓UI 资源是指功能菜单、对话框
外貌、程序图标、光标形状等等东西。这些UI 资源的实际内容(二进制代码)系借助各
种工具产生,并以各种扩展名存在,如.ico、.bmp、.cur 等等。程序员必须在一个所谓
的资源描述档(.rc)中描述它们。RC 编译器(RC.EXE)读取RC 档的描述后将所有UI
资源档集中制作出一个.RES 档,再与程序代码结合在一起,这才是一个完整的Windows
可执行档。
2.消息驱动:可以分为由硬件装置所产生的消息(如鼠标
移动或键盘被按下),放在系统队列(system queue)中,以及由Windows 系统或其它
Windows 程序传送过来的消息,放在程序队列(application queue)中。
3. UpdateWindow函数: 我们希望先传送个WM_PAINT 给窗口, 以驱动窗口的绘图动作, 所以调用
UpdateWindow。
4.消息处理函数:TranslateMessage 是为了将键盘消息转化, DispatchMessage 会将消息传给窗口函
数去处理;
因为消息发生之时,操作系统已根据当时状态,为它标明了所属窗口,而窗口所属之窗口类别又已经明白标示了窗口函数(也就是wc.lpfnWndProc 所指定的函数),所以DispatchMessage不需要再指定窗口函数(注意DispatchMessage是把消息送到对应的窗口函数中去)
5.将数据和带待处理该数据的函数封装在一起:对象导向观念中把「资料」和「处理资料的方法」封装起来的一种具体实现
6. 消息映射:有没有可能把窗口函数的内容设计得更模块化、更一般化:(具体见深入浅出MFC)
#define dim(x) (sizeof(x) / sizeof(x[0]))
struct MSGMAP_ENTRY {
UINT nMessage;
LONG(*pfn)(HWND, UINT, WPARAM, LPARAM);
};
struct MSGMAP_ENTRY _messageEntries[] =
{
WM_CREATE, OnCreate,
WM_PAINT, OnPaint,
WM_SIZE, OnSize,
WM_COMMAND, OnCommand,
WM_SETFOCUS, OnSetFocus,
WM_CLOSE, OnClose,
WM_DESTROY, OnDestroy,
};
struct MSGMAP_ENTRY _commandEntries =
{
IDM_ABOUT, OnAbout,
IDM_FILEOPEN, OnFileOpen,
IDM_SAVEAS, OnSaveAs,
};
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));
}
LONG OnCommand(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int i;
for (i = 0; i < dim(_commandEntries); i++) { //
if (LOWORD(wParam) == _commandEntries[i].nMessage)
return((*_commandEntries[i].pfn)(hWnd, message, wParam, lParam));
}
return(DefWindowProc(hWnd, message, wParam, lParam));
}
LONG OnCreate(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
...
}
7. 对话框函数:其类型非常类似窗口函数,但是它通常只处
理WM_INITDIALOG 和WM_COMMAND 两个消息。对话框中的各个控制组件也都是小小窗口,各有自己的窗口函数,它们以消息与其管理者(父窗口,也就是对话框)沟通。而所有的控制组件传来的消息都是WM_COMMAND,再由其参数分辨哪一种控制组件以及哪一种通告(notification)
Modal 对话框的激活与结束,靠的是DialogBox 和EndDialog 两个API 函数
8. 资源描述档 ( .RC ):RC 文件是一个以文字描述资源的地方。常用的资源有九项之多,分别是ICON、CURSOR、
BITMAP、FONT、DIALOG、MENU、ACCELERATOR、STRING、VERSIONINFO。还可能有新的资源不断加入;这
些文字描述需经过RC 编译器,才产生可使用的二进制代码
- Windows程序的生与死:
***********************************
详细解释:
1. 程序初始化过程中调用CreateWindow,为程序建立了一个窗口,做为程序的萤
幕舞台。CreateWindow 产生窗口之后会送出WM_CREATE 直接给窗口函数,
后者于是可以在此时机做些初始化动作(例如配置内存、开文件、读初始资
料...)。
2. 程序活着的过程中,不断以GetMessage 从消息贮列中抓取消息。如果这个消
息是WM_QUIT,GetMessage 会传回0 而结束while 循环,进而结束整个程序。
3. DispatchMessage 透过Windows USER 模块的协助与监督,把消息分派至窗口
函数。消息将在该处被判别并处理。
4. 程序不断进行2. 和3. 的动作。
5. 当使用者按下系统菜单中的Close 命令项,系统送出WM_CLOSE。通常程序
的窗口函数不栏截此消息,于是DefWindowProc 处理它。
6. DefWindowProc 收到WM_CLOSE 后, 调用DestroyWindow 把窗口清除。
DestroyWindow 本身又会送出WM_DESTROY。
7. 程序对WM_DESTROY 的标准反应是调用PostQuitMessage。
8. PostQuitMessage 没什么其它动作,就只送出WM_QUIT 消息,准备让消息循
环中的GetMessage 取得,如步骤2,结束消息循环。
******************************************
10 .空闲时间的处理: OnIdle;所谓空闲时间(idle time),是指「系统中没有任何消息等待处理」的时间
**************************
背景工作最适宜在空闲时间完成。传统的SDK 程序如果要处理空闲时间,可以以下列
循环取代WinMain 中传统的消息循环:
while (TRUE) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) {
if (msg.message == WM_QUIT) //注意此处二者的不同
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
OnIdle();
}
}
原因是PeekMessage 和GetMessage 的性质不同。它们都是到消息队列中抓消息,如果
抓不到,程序的主执行线程(primary thread,是一个UI 执行线程)会被操作系统虚悬住。
当操作系统再次回来照顾此一执行线程,而发现消息队列中仍然是空的,这时候两个API
函数的行为就有不同了:
GetMessage 会过门不入,于是操作系统再去照顾其它人。
PeekMessage 会取回控制权,使程序得以执行一段时间。于是上述消息循环进
入OnIdle 函数中。
***************************
11 .MFC 有两个十分十分重要的虚
拟函数:与document 有关的Serialize 函数和与view 有关的OnDraw 函数。你应该在自己的CMyDoc 和CMyView 中改写这两个虚拟函数。
12.
MFC一些必要的名词(二)