2.03 消息基础

消息组成(windows平台下)

6大部分(固定),linux则可以由程序员规定

  • 窗口句柄
  • 消息ID
  • 消息的两个参数(两个附带信息)
  • 消息产生的时间
  • 消息产生时的鼠标位置
  1. /*
  2. * Message structure
  3. */
  4. typedef struct tagMSG {
  5. HWND hwnd;
  6. UINT message;
  7. WPARAM wParam;
  8. LPARAM lParam;
  9. DWORD time;
  10. POINT pt;
  11. #ifdef _MAC
  12. DWORD lPrivate;
  13. #endif
  14. } MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

消息的作用

当系统通知窗口工作时,(DispatchMessage)就采用消息的方式派发给窗口(的窗口处理函数 (自己定义的那个))。

  1. // 伪代码
  2. DispatchMessage(&nMsg){
  3. 1.nMsg.hwnd-->保存窗口数据的内存-->WndProc(自定义窗口函数名称)
  4. 2.WndProc( // 派发前4个函数给窗口处理函数, 派发 = 调用这个函数
  5. nMsg.hwnd, // 窗口句柄
  6. nMsg.message, // 消息ID(数字 微软提供约1000种)
  7. nMsg.wParam, // 第一个附带信息
  8. nMsg.lParam // 第二个附带信息
  9. )
  10. 3.返回自己的函数
  11. }

窗口处理函数

每个窗口必须有窗口处理函数

  1. LRESULT CALLBACK WindowProc(
  2. HWND hwnd // 窗口句柄
  3. UINT uMsg // 消息ID
  4. WPARAM wParam // 消息参数1
  5. LPARAM lParam // 消息参数2
  6. )

当系统通知窗口时, 会调用窗口处理函数, 同时将消息ID和消息参数传递给该函数.

在处理函数中, 不处理的消息, 使用缺省窗口处理函数. 例如DefWindowProc

  1. // 示例
  2. LRESULT CALLBACK WndProd(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) {
  3. switch (msgID) {
  4. case WM_DESTROY: // 窗口退出时,退出该程序
  5. PostQuitMessage(0);
  6. break;
  7. }
  8. if (GetAsyncKeyState(VK_ESCAPE)) { // ESC键 退出该程序
  9. PostQuitMessage(0);
  10. }
  11. return DefWindowProc(hWnd, msgID, wParam, lParam); // 默认处理函数 Windows处理剩下的情况
  12. }

浅谈消息相关函数

GetMessage

获取本进程的消息

  1. BOOL GetMessage(
  2. LPMSG lpMsg, // 存放获取到消息BUFF. 获取消息后,将消息参数存入MSG结构中
  3. HWND hWnd, // 窗口句柄. 获取到hWnd指定窗口的消息(NULL代表该进程所有消息)
  4. UINT wMsgFilterMin,// 获取消息最小ID. 消息范围, 都是0代表都抓
  5. UINT wMsgFilterMax,// 获取消息最大ID
  6. )
  1. while (GetMessage(&nMsg, NULL, 0, 0)) {
  2. TranslateMessage(&nMsg); // 翻译消息
  3. DispatchMessage(&nMsg); // 派发消息(谁处理消息 就派发给谁 -> 窗口处理函数)
  4. }

话外:PostQuitMessage(0) 向”消息队列”中发送了 WN_QUIT, 被GetMessage抓取到, 从而程序退出

TranslateMessage

翻译消息。将键盘按键消息(可见字符),翻译成字符消息。

可见字符: A-Z这种, 比如按不按Caps, 结果不一样, 所以要翻译

不可见:上下左右 F1F2

先检查是不是按键消息,如果不是,直接跳过

  1. BOOL TranslateMessage(
  2. CONST MSG*lpMsg//要翻译的消息地址
  3. );

检查消息是否是按键的消息,如果不是按键消息,不做任何处理,继续执行。

DispatchMessage

派发消息

  1. LRESULT DispatchMessage(
  2. CONST MSG *lpmsg//要派发的消息
  3. );

将消息派发到该消息所属窗口的窗口处理函数上。