11.2.2 消息处理函数(1)
除应用程序窗口的通用外观以外,WinMain()函数不包含任何应用程序特有的代码。使应用程序以我们希望的方式运转的所有代码都位于程序的消息处理部分-- 即在传递给Windows的WindowClass结构中标识的WindowProc()函数。每次分派主应用程序窗口的消息时,都要调用该函数。因为Windows通过函数指针标识WindowProc()函数,所以可以给该函数使用任意名称,这里继续称之为WindowProc()。
本示例相当简单,因此我们将把所有处理消息的代码都放在WindowProc()这一个函数内。但更通常的做法是让WindowProc()函数负责分析给定的消息是什么,以及该消息是供哪个窗口使用的,然后调用一大堆函数中的一个。在被调用的这些函数中,每个函数只负责处理相关特定窗口的上下文中某条特定的消息。但在大多数应用程序上下文中,总体的操作顺序以及WindowProc()函数分析传入消息的方式都是非常相似的。
1. WindowProc()函数
WindowProc()函数的原型如下:
- LRESULT CALLBACK WindowProc(HWND hWnd, UINT message,
- WPARAM wParam, LPARAM lParam);
返回类型是LRESULT,是一个Windows类型,通常等价于long类型。因为该函数是Windows通过指针(该指针是在WinMain()函数的WNDCLASSEX结构中设置的)调用的,所以需要将该函数限定为CALLBACK。前面曾提到过此说明符,其作用与Windows定义的WINAPI相同,WINAPI决定着函数实参的处理方式。这里可以使用WINAPI替代CALLBACK,但后者更好地表达出这个函数的作用。传递给WindowProc()函数的4个实参提供与致使调用该函数的特定消息有关的信息,它们的意义如表11-4所述。
表 11-4
|
实 参
|
意 义
|
|
HWND hWnd
|
一个句柄,指向致使该消息发生的事件所在的窗口
|
|
UINT message
|
消息ID,指出消息类型的32位整数值
|
|
WPARAM wParam
|
包含与消息种类有关的其他信息,
是32位(64位模式中是64位)的值
|
|
LPARAM lParam
|
包含与消息种类有关的其他信息,
是32位(64位模式中是64位)的值
|
与传入消息有关的窗口由传递给该函数的第一个实参hWnd标识。在本例中,只有一个窗口,因此可以忽略该参数。
消息是由传递给WindowProc()的message值标识的。可以对照预定义的符号常量来测试这个值,其中各个常量表示某种特定的消息。一般的窗口消息都以WM_开始,典型的示例有WM_PAINT-- 对应于重画窗口部分工作区的请求,还有WM_LBUTTONDOWN-- 表明按下鼠标左键。通过在MSDN库中搜索WM_,可以找到所有这些常量。
2. 解码Windows消息
要解码Windows发送的消息,通常要基于message的值,在WindowProc()函数中使用switch语句来完成。然后,选择希望处理的消息类型就只是为switch中的每种情形放上一条case语句。这种switch语句的典型结构如下所示:
- switch(message)
- {
- case WM_PAINT:
- // Code to deal with drawing the client area
- break;
- case WM_LBUTTONDOWN:
- // Code to deal with the left mouse button being pressed
- break;
- case WM_LBUTTONUP:
- // Code to deal with the left mouse button being released
- break;
- case WM_DESTROY:
- // Code to deal with a window being destroyed
- break;
- default:
- // Code to handle any other messages
- }
每个Windows程序都有一些与该结构类似的地方,但在后面使用MFC编写的Windows程序中,该结构可能隐藏起来了。每种情形对应一个特定的消息ID值,并对该消息进行适当的处理。程序不想单独处理的任何消息都由default语句处理,默认情形应该调用DefWindowProc()函数,将消息回传给Windows。DefWindowProc()是提供默认消息处理机制的Windows API函数。
在复杂的、逐一处理许多可能的Windows消息的程序中,该switch语句可能变得很大、相当麻烦。当使用Application Wizard来生成Windows应用程序时,将不必再担心这一点,因为向导将负责处理这一切,我们将永远也看不到WindowProc()函数,只需要提供代码来处理感兴趣的特定消息即可。
绘制窗口工作区
Windows给程序发送WM_PAINT消息,告诉程序应该重画应用程序的工作区。因此,在示例中需要绘制窗口的工作区来响应WM_PAINT消息。