windows消息机制


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_USER0x7FFF之间):

// 假设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;
}

通过结合使用消息发送函数(如SendMessagePostMessage)和适当的消息处理代码,你可以在Windows应用程序中实现复杂的交互逻辑。

6. 消息处理流程

  • 系统消息队列与应用程序消息队列交互
    在这里插入图片描述
  • 单个应用程序消息处理过程
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值