windows消息机制
目录
- 1. 消息队列(Message Queue)
- 2. 消息循环(Message Loop)
- 3. 窗口过程(Window Procedure)
- 4. 消息(Message)
- 5. 消息发送的两种方式
Windows消息机制是Windows操作系统下应用程序与操作系统之间的一种重要通信方式。通过这一机制,应用程序能够接收来自操作系统的各种事件和请求,并作出相应的响应和处理。以下是Windows消息机制的详细解析:
1. 消息队列(Message Queue)
消息队列是一个用于存储消息的缓冲区。当操作系统有消息需要传递给应用程序时,这些消息会被放入消息队列中。
- 系统消息队列:这是一个系统唯一的队列,输入设备驱动程序(如键盘、鼠标等)会将用户的操作输入转化为消息并放置于系统队列中,然后系统会将此消息转到目标窗口所在线程的消息队列中等待处理。
- 线程消息队列(也称为应用程序消息队列):每个GUI线程都会维护这样一个线程消息队列。线程消息队列中的消息会被本线程的消息循环(也称为消息泵)派送到相应的窗口过程(窗口回调函数WndProc)处理。
2. 消息循环(Message Loop)
应用程序通常有一个消息循环,它不断从消息队列中提取消息,并根据消息的类型将其传递给相应的窗口或控件进行处理。这部分代码通常使用以下函数:
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
- GetMessage: 从线程的消息队列中取出一条消息,如果消息队列为空,则程序会等待。
- TranslateMessage: 用于翻译一些消息,比如将键盘消息转换为字符消息。
- DispatchMessage: 将消息传递给窗口过程(Window Procedure,通常简称为WndProc)。
3. 窗口过程(Window Procedure)
每个窗口都有一个窗口过程(WndProc),它是一个回调函数,用于接收Windows传递给窗口的消息,并处理这些消息。
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_PAINT:
// 处理重绘窗口的消息
break;
case WM_DESTROY:
PostQuitMessage(0); // 通知系统关闭程序
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
当DispatchMessage函数将消息分发到窗口过程时,窗口过程会根据消息的类型和附加数据来执行相应的逻辑,如绘图、更新窗口状态、响应用户输入等。处理完消息后,窗口过程会返回一个值给Windows系统,表示消息已被处理
4. 消息(Message)
- 系统定义的消息:这些消息是由Windows系统定义的,用于处理各种系统级事件,如窗口的创建、销毁、移动、大小调整等。系统消息ID的范围通常是从0到WM_USER-1(即0x0000到0x03FF)。
- 应用程序定义的消息:这些消息是由应用程序自己定义的,用于处理特定的应用程序事件。应用程序消息ID的范围从WM_USER(0x0400)开始,到0x7FFF结束。此外,还有一个范围(0xC000到0xFFFF)用于跨应用程序通信,这些消息ID通常通过RegisterWindowMessage函数注册得到。
5. 消息发送的两种方式
在Windows编程中,消息发送是一种基本的通信机制,用于在不同的应用程序、应用程序内的不同窗口或控件之间传递信息。Windows消息系统允许应用程序通过发送和接收消息来执行各种任务,比如响应用户输入、管理窗口和控件的生命周期等。
- SendMessage:这是一个同步消息发送函数。当调用
SendMessage
函数时,它会立即将消息发送到指定的窗口或控件,并等待该窗口或控件处理完消息后才返回。这意呀着,如果目标窗口或控件处理消息时耗时较长,那么调用SendMessage
的线程将被阻塞,直到消息处理完成。
LRESULT SendMessage(
HWND hWnd, // 目标窗口的句柄
UINT Msg, // 要发送的消息
WPARAM wParam, // 消息附加的额外信息(WPARAM)
LPARAM lParam // 消息附加的额外信息(LPARAM)
);
- PostMessage:这是一个异步消息发送函数。与
SendMessage
不同,PostMessage
将消息放入目标窗口的消息队列后立即返回,而不等待消息被处理。这意味着调用PostMessage
的线程不会被阻塞。
BOOL PostMessage(
HWND hWnd, // 目标窗口的句柄
UINT Msg, // 要发送的消息
WPARAM wParam, // 消息附加的额外信息(WPARAM)
LPARAM lParam // 消息附加的额外信息(LPARAM)
);
示例
假设我们想要向一个窗口发送一个简单的WM_USER
消息(一个自定义消息,其值在WM_USER
和0x7FFF
之间):
// 假设hWnd是目标窗口的句柄
const UINT WM_MY_MESSAGE = WM_USER + 1;
// 使用SendMessage发送消息
SendMessage(hWnd, WM_MY_MESSAGE, (WPARAM)0, (LPARAM)0);
// 或者使用PostMessage发送消息
PostMessage(hWnd, WM_MY_MESSAGE, (WPARAM)0, (LPARAM)0);
处理消息
为了在目标窗口中处理这些消息,你需要在窗口过程中(Window Procedure)添加相应的消息处理代码。窗口过程是一个函数,它定义了窗口如何响应各种消息。
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_MY_MESSAGE:
// 处理WM_MY_MESSAGE消息
break;
// 其他消息处理...
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
通过结合使用消息发送函数(如SendMessage
和PostMessage
)和适当的消息处理代码,你可以在Windows应用程序中实现复杂的交互逻辑。