Skip to content

消息处理


这是WindowsAPI 这不是UWP

UWP是 Window 微软商店版本


消息的输入

大概的分类

  • 键盘消息

  • 鼠标消息

  • 快捷键消息

  • 菜单消息

  • 控件消息

  • 自定义消息


回调函数优化结构 | 如何使用消息

比如我要调用一个WM_CREATE 消息 证明我调用成功

c++
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg)
    {   case WM_CREATE:
          ::MessageBox();
    
        default:
            break;
    }
    //正常是这样的当出现uMsg消息返回WM_CREATE时候 就会出现MessageBox 消息

但是这样太麻烦了 让消息处理 switch 过于庞大

  • 可以选择这种方式来处理
c++
LRESULT CreateS (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
    ::MessageBox(NULL, _T("Create!", _T("OK_is_create", MB_OK);
    return TRUE;
 }

单独设立处理的函数 ,于是乎可以这样处理

c++
LRESULT OnCreate(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    ::MessageBox(NULL, _T("ONCreate"), _T("Create"), MB_OK);
    return TRUE;
}
LRESULT OnClose(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
     ::MessageBox(NULL, _T("Close"), _T("Close"), MB_OK);
     PostQuitMessage(123);  //关闭消息  WM_QUIT消息, 传参到 wParam  
     return TRUE;
}
    
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CREATE :
            return OnCreate(hWnd, uMsg, wParam, lParam);
        case WM_CLOSE  :
            return OnClose(hWnd, uMsg, wParam, lParam);
        default:
            break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);  

}

这样就可以 接收消息 与 之前 也就是上一篇的消息处理函数 相比之下就干净多了


只需要公式化套就行了


客户区域

绘制客户区域 一个界面 是包括客户区域和非客户区域

黑框区域是客户区域(client area) 黄框 为非客户区域由 (Not Client Area)NC操作系统决定


窗口销毁

窗口关闭时候会有销毁的消息 是WM_DESTORY

显然用在WM_CLOSE 消息使用PostQuitMessage是不太好的 用在 这个消息更加合适

c++
LRESULT OnCreate(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    ::MessageBox(NULL, _T("ONCreate"), _T("Create"), MB_OK);
    return TRUE;
}
LRESULT OnClose(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    ::MessageBox(NULL, _T("Close"), _T("Close"), MB_OK);
    return TRUE;
}
LRESULT OnDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    ::MessageBox(NULL, _T("Destory"), _T("SUCCESS"), MB_OK);
    PostQuitMessage(123);  //关闭消息  WM_Destory消息, 传参到 wParam  
    return TRUE;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = FALSE;
    switch (uMsg) {
    case WM_CREATE:
        lResult = OnCreate(hWnd, uMsg, wParam, lParam);
        break;
    case WM_CLOSE:
        lResult = OnClose(hWnd, uMsg, wParam, lParam);
        break;
    case WM_DESTROY:  // 窗口销毁
        lResult = OnDestroy(hWnd, uMsg, wParam, lParam);
        break;
    }
    if (!lResult)
        DefWindowProc(hWnd, uMsg, wParam, lParam);
    return lResult;
}

这样的 优化代码更加友好 按照之前的来看会直接 出现窗口无法销毁的情况


WM_MOVE消息

之前提过一句 再次提一下 LOWORAD(低字节) 的lParam 是x 轴 HIWORD(高字节)的lParam 是y轴\

所以根据 这个原理 通过传参可以获取窗口的移动 参数

c++
#include <Windows.h>
#include <stdio.h>
#include<tchar.h>
LRESULT CALLBACK WindowProc(  HWND hWnd,UINT uMSG, WPARAM wParam,    LPARAM lParam) ;// 回调
/*
    键盘消息
    鼠标消息
    快捷键消息
    菜单消息

    客户区域
    */


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) // 第二个句柄保留适配老版本
{
    TCHAR szWndClassName[] = { _T("Text") };

    WNDCLASSEX wc = { 0 };
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_VREDRAW | CS_HREDRAW; //窗口类型
    wc.lpfnWndProc = WindowProc; // 窗口过程 (回调函数) -> 处理 消息
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL,IDI_SHIELD);
    wc.hCursor = LoadCursor(NULL,IDC_CROSS);
    wc.hbrBackground = CreateSolidBrush(RGB(255, 0, 0));
    wc.lpszMenuName = NULL;
    wc.lpszClassName = szWndClassName;
    if (RegisterClassEx(&wc) == 0) {
        return 0;
    }

    //创建窗口

    TCHAR szWndName[] = { _T("Windows") };
    HWND hWnd = CreateWindowEx(
        0,
        szWndClassName,
        szWndName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL
    );
    if (hWnd == NULL)
        return 0;




    ShowWindow(hWnd, SW_SHOWNORMAL);
   // SetClassLong(hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL,IDC_HAND)); 
    // 二次修改光标





    //消息循环
    BOOL bRet;
    MSG  msg;
    while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)  // 接收所有 的消息
    {
        if (bRet == -1)
        {
            break;
        }
        else
        {
            TranslateMessage(&msg);//虚拟
            DispatchMessage(&msg); //派发消息
        }
    }
    return (msg.wParam); // 接收消息

}LRESULT OnCreate(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    ::MessageBox(NULL, _T("ONCreate"), _T("Create"), MB_OK);
    return TRUE;
}
LRESULT OnClose(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    ::MessageBox(NULL, _T("Close"), _T("Close"), MB_OK);
    return FALSE;
}
LRESULT OnDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    ::MessageBox(NULL, _T("Destory"), _T("SUCCESS"), MB_OK);
    PostMessage(hWnd, WM_QUIT, wParam, lParam);  //关闭消息  WM_Destory消息, 传参到 wParam  
    return TRUE;
}
LRESULT OnMove(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    int xPos = (int)(short)LOWORD(lParam);
    int yPos = (int)(short)HIWORD(lParam);
    TCHAR Space[MAXBYTE];
    wsprintf(Space, _T("xPos:%d yPos:%d"), xPos, yPos);
    ::MessageBox(NULL, Space, _T("too1-666.github.io/docsx/"),MB_OK);
    return TRUE;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = FALSE;
    switch (uMsg) {
    case WM_CREATE:
        lResult = OnCreate(hWnd, uMsg, wParam, lParam);
        break;
    case WM_CLOSE:
        lResult = OnClose(hWnd, uMsg, wParam, lParam);
        break;
    case WM_DESTROY:  // 窗口销毁
        lResult = OnDestroy(hWnd, uMsg, wParam, lParam);
        break;
    case WM_MOVE:
        lResult = OnMove(hWnd, uMsg, wParam, lParam);
        break;
    }
    if (!lResult)
    {
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return lResult;
}

本章节代码展示