DispatchMessage函数调用作为消息目标的窗口的窗口过程。窗口过程有以下签名。
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
有四个参数:
- hwnd是窗口的句柄。
- uMsg是消息代码;例如,WM_SIZE消息指示窗口被调整大小。
- wParam和lParam包含与消息有关的附加数据。确切的含义取决于消息代码。
LRESULT是您的程序返回到Windows的整数值。它包含您的程序对特定消息的响应。这个值的含义取决于消息代码。CALLBACK是函数的调用约定。
一个典型的窗口过程只是一个大的switch语句,用来处理消息代码。为每个要处理的消息添加”case”。
switch(uMsg){
case WM_SIZE: // Handle window resizing
// etc
}
消息的其他数据包含在lParam和wParam参数中。这两个参数都是指针宽度(32位或64位)大小的整数值。每个的含义取决于消息代码(uMsg)。对于每条消息,您将需要在MSDN上查找消息代码,并将参数转换为正确的数据类型。通常数据是一个数值或者一个指向结构体的指针。有些消息没有任何数据。
例如WM_SIZE消息的文档指出:
- wParam是一个标志,指示窗口是最小化,最大化还是调整大小。
- lParam将窗口的新宽度和高度作为16位值打包到一个32位或64位数中。您将需要执行一些位移来获取这些值。幸运的是,头文件WinDef.h包含了帮助程序宏。
一个典型的窗口过程处理数十条消息,所以它可以长得很长。让代码更加模块化的一种方法是将处理每条消息的逻辑放在一个单独的函数中。在窗口过程中,将wParam和lParam参数转换为正确的数据类型,并将这些值传递给函数。例如,要处理WM_SIZE消息,窗口过程将如下所示:
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
switch(uMsg){
case WM_SIZE:
{
int width=LOWORD(lParam);// Macro to get the low-order word.
int height=HIWORD(lParam);// Macro to get the high-order word.
// Respond to the message:
OnSize(hwnd,(UINT)wParam,width,height);
}
break;
}
}
void OnSize(HWND hwnd,UINT flag,int width,int height){
// Handle resizing
}
LOWORD和HIWORD宏从lParam获得16位宽度和高度值。(您可以在MSDN文档中为每个消息代码查找这些类型的细节。)窗口过程提取宽度和高度,然后将这些值传递给OnSize函数。
默认消息处理
如果在窗口过程中不处理特定的消息,则将消息参数直接传递给DefWindowProc函数。此函数执行消息的默认操作,该操作因消息类型而异。
return DefWindowProc(hwnd,uMsg,wParam,lParam);
避免窗口过程中的瓶颈
当您的窗口过程执行时,它会阻止在同一线程上创建的任何其他窗口消息。因此,避免在窗口过程中进行冗长的处理。例如,假设你的程序打开一个TCP连接并且无限等待服务器响应。如果在窗口过程中执行该操作,则在请求完成之前,您的UI将不会响应。在此期间,窗口无法处理鼠标或键盘输入,重新绘制,甚至关闭。
相反,您应该使用内置于Windows中的多任务处理工具之一将工作移至另一个线程:
- 创建一个新的线程。
- 使用线程池。
- 使用异步I/O调用。
- 使用异步过程调用。
下一个
绘画窗口