首页 > 代码库 > MFC一些必要的名词(二)

MFC一些必要的名词(二)

  1. 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 编译器,才产生可使用的二进制代码

  1. 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一些必要的名词(二)