win32 API编程之常用消息详解

一、发送消息的函数

  • sendmessage
  • postmessage
  • postthreadmessage:向消息队列添加一个消息

实例代码:

#include<windows.h>
#include<stdio.h>
//自定义消息
#define  WM_AAA    WM_USER+1

HWND  hWnd; 
HWND  hWnd2;

//自定义的窗口过程
LRESULT  CALLBACK    MyWindowProc(HWND hWnd, UINT Msg,
    WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);//可以使GetMessage返回0    
        return 0; 

    case WM_AAA:
        MessageBoxA(NULL, "窗口过程:WM_AAA", "测试", MB_OK);
        return 0;
    }
    return DefWindowProc(hWnd, Msg, wParam, lParam);
}

int  WINAPI   WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance,
    LPSTR lpCmdLine, int  nShowCmd)
{
    //1.注册窗口类
    WNDCLASS  wnd;
    wnd.cbClsExtra = 0;
    wnd.cbWndExtra = 0;
    wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色
    wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标
    wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
                                                //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息
    wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数
    wnd.lpszClassName = L"MrHuang";//窗口类名
    wnd.lpszMenuName = NULL;//菜单资源名称
    wnd.style = CS_HREDRAW;//窗口类、样式
    wnd.hInstance = hInstance;//实例句柄
    RegisterClass(&wnd);

    //创建窗口(返回之前发送WM_CREATE)
    hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序",
        WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL);

    //显示窗口
    ShowWindow(hWnd, nShowCmd);
    //更新窗口(发送WM_PAINT)
    UpdateWindow(hWnd);

    //创建窗口2(返回之前发送WM_CREATE)
    hWnd2 = CreateWindow(L"MrHuang", L"第二个窗口程序",
        WS_OVERLAPPEDWINDOW, 100, 500, 300, 300, NULL, NULL, hInstance, NULL);
    //显示窗口
    ShowWindow(hWnd2, nShowCmd);
    //更新窗口(发送WM_PAINT)
    UpdateWindow(hWnd2);
//消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { //说明两个窗口公用一个消息循环和线程消息队列 if (msg.message == WM_LBUTTONDOWN) { //char str[64]; //sprintf(str,"窗口句柄:%p", msg.hwnd); //MessageBoxA(NULL, str,"测试", MB_OK); //SendMessage直接发给窗口过程函数,并且阻塞,除非被窗口过程处理才返回 //SendMessage(hWnd, WM_AAA, 0, 0); //PostMessage放到线程消息队列里,并且立即返回,通过消息循环到窗口过程处理 //PostMessage(hWnd, WM_AAA, 0, 0); //PostThreadMessage放到线程消息队列里,不进入窗口过程 //PostThreadMessage(GetCurrentThreadId(), WM_AAA, 0, 0); //PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0); PostQuitMessage(0);//等价于上面的一行调用 int a = 100; } if (msg.message == WM_AAA) { MessageBoxA(NULL, "消息循环:WM_AAA","测试", MB_OK); } TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }

二、windows各种消息

  • 标准消息:所有以WM开头的消息,WM_COMMAND除外。为了避免系统消息与用户定义的消息冲突,微软定义了一个宏WM_USER,小于WM_USER的ID被系统使用,大于的被用户使用。
  • 命令消息:来自菜单、工具栏按钮或者加速键的消息,以WM_COMMAND呈现。
  • 通告消息:由控件产生的消息。

三、响应窗口创建和删除

代码实例

#include<windows.h>
#include<stdio.h>

//自定义的窗口过程
LRESULT  CALLBACK    MyWindowProc(HWND hWnd, UINT Msg,
    WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
        ///////////////////////////创建窗口///////////////////////////////
    case WM_NCCREATE:

        SetWindowTextA(hWnd, "改变标题");

        char str[64];
        sprintf(str, "WM_NCCREATE消息:%p!
", hWnd);
        OutputDebugStringA(str);
        return  true;//这里必须返回true,否则不会发WM_CREATE消息,CreateWindow返回NULL

    case WM_CREATE:
    {
        CREATESTRUCT  *p = (CREATESTRUCT*)lParam; 
        sprintf(str, "WM_CREATE消息:%p!
", hWnd); 

        OutputDebugStringA(str);
        return true;
    }

        ///////////////////////////销毁窗口/////////////////////////////// 
    case WM_CLOSE:
        sprintf(str, "WM_CLOSE消息:%p!
", hWnd);
        OutputDebugStringA(str); 
        DestroyWindow(hWnd);//销毁窗口,发出WM_DESTROY消息
        return 0;

    case WM_DESTROY: 
        sprintf(str, "WM_DESTROY消息:%p!
", hWnd);
        OutputDebugStringA(str);
        PostQuitMessage(0);//可以使GetMessage返回0    
        return 0;
    case WM_NCDESTROY: 
        sprintf(str, "WM_NCDESTROY消息:%p!
", hWnd);
        OutputDebugStringA(str);
        return 0;
    }
    return DefWindowProc(hWnd, Msg, wParam, lParam);
}

int  WINAPI   WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance,
    LPSTR lpCmdLine, int  nShowCmd)
{
    //1.注册窗口类
    WNDCLASS  wnd;
    wnd.cbClsExtra = 0;
    wnd.cbWndExtra = 0;
    wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色
    wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标
    wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
                                                //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息
    wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数
    wnd.lpszClassName = L"MrHuang";//窗口类名
    wnd.lpszMenuName = NULL;//菜单资源名称
    wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式
    wnd.hInstance = hInstance;//实例句柄
    RegisterClass(&wnd);

    //创建窗口(返回之前发送WM_CREATE)
    HWND  hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序",
        WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL);
    char str[64];
    sprintf(str, "CreateWindow返回:%p!
", hWnd);
    OutputDebugStringA(str); 

    //显示窗口
    ShowWindow(hWnd, nShowCmd);
    //更新窗口(发送WM_PAINT)
    UpdateWindow(hWnd);

    //消息循环(收到WM_QUIT消息退出)
    MSG  msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);//翻译消息
        DispatchMessage(&msg);//分发消息到窗口过程
    }
}

 四、WM_PAINT消息

1)以下操作会触发WM_PAINT消息

注:

代码实例:

#include<windows.h>
#include<stdio.h>

//自定义的窗口过程
LRESULT  CALLBACK    MyWindowProc(HWND hWnd, UINT Msg,
    WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
      case WM_DESTROY:
        PostQuitMessage(0);//可以使GetMessage返回0    
        return 0; 

      case WM_ERASEBKGND:
      {  
          static  int  j = 0;
          char str[64];
          sprintf(str, "第%d次产生WM_ERASEBKGND!
", ++j);
          OutputDebugStringA(str);//在输出窗口打印信息
          return  1; 
      }

      case WM_PAINT:
      {  PAINTSTRUCT  ps;
      HDC  hdc = BeginPaint(hWnd, &ps);//使无效区域变得有效

      static  int  i = 0;
      char str[64];
      sprintf(str, "第%d次产生WM_PAINT!
", ++i);
      OutputDebugStringA(str);//在输出窗口打印信息

      EndPaint(hWnd, &ps);
      return 0;
      }
      case  WM_LBUTTONDOWN:
          //InvalidateRect(hWnd, NULL, true);//添加更新区域
          //UpdateWindow(hWnd);//更新区域不为空,则马上发出WM_PAINT消息
        
          //不管窗口的任何部分是否无效,都会导致WM_PAINT消息被发布到窗口。
          RedrawWindow(hWnd, NULL, NULL, RDW_INTERNALPAINT);
          break;

      case  WM_NCPAINT://自定义绘制非客户区
          HDC  hdc = GetWindowDC(hWnd); 
          RECT  r;
          r.left = 0;
          r.top = 0;
          r.right = 300;
          r.bottom = 30;
          HBRUSH  brh = CreateSolidBrush(RGB(255, 0, 0));
          FillRect(hdc, &r, brh);
          SetBkMode(hdc, TRANSPARENT);
          TextOutA(hdc, 5, 5, "自定义窗口标题", 14);//最后一个参数为字符串长度
          DeleteObject(brh);
          ReleaseDC(hWnd,  hdc);
          return  true;
          //break;
    }
    return DefWindowProc(hWnd, Msg, wParam, lParam);
 }

    int  WINAPI   WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance,
        LPSTR lpCmdLine, int  nShowCmd)
    {
        //1.注册窗口类
        WNDCLASS  wnd;
        wnd.cbClsExtra = 0;
        wnd.cbWndExtra = 0;
        wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色
        wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标
        wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
                                                    //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息
        wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数
        wnd.lpszClassName = L"MrHuang";//窗口类名
        wnd.lpszMenuName = NULL;//菜单资源名称
        wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式
        wnd.hInstance = hInstance;//实例句柄
        RegisterClass(&wnd);

        //创建窗口(返回之前发送WM_CREATE)
        HWND  hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序",
            WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL);

        //显示窗口
        ShowWindow(hWnd, nShowCmd);
        //更新窗口(发送WM_PAINT)
        UpdateWindow(hWnd);

        //消息循环(收到WM_QUIT消息退出)
        MSG  msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);//翻译消息
            DispatchMessage(&msg);//分发消息到窗口过程
        }
    }

五、WM_ERASEBKGND消息

代码实例:见上面WM_PAINT的代码实例。

六、更新窗口的函数

代码实例:见上面WM_PAINT的代码实例。

七、WM_NCPAINT消息

代码实例:见上面WM_PAINT的代码实例。

八、窗口鼠标键盘消息

代码实例:

#include<windows.h>
#include<stdio.h>

//自定义的窗口过程
LRESULT  CALLBACK    MyWindowProc(HWND hWnd, UINT Msg,
    WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);//可以使GetMessage返回0    
        return 0; 

        //鼠标消息
    case  WM_LBUTTONDOWN:
        char str[64];
        sprintf(str, "鼠标左键按下:  %d, %d
", LOWORD(lParam), HIWORD(lParam));
        OutputDebugStringA(str);
        break;
    case  WM_LBUTTONUP: 
        sprintf(str, "鼠标左键弹起:  %d, %d
", LOWORD(lParam), HIWORD(lParam));
        OutputDebugStringA(str);
        break;
    case  WM_MOUSEMOVE: 
        sprintf(str, "鼠标移动:  %d, %d
", LOWORD(lParam), HIWORD(lParam));
        OutputDebugStringA(str);
        break;
    case  WM_LBUTTONDBLCLK: 
        sprintf(str, "鼠标左键双击:  %d, %d
", LOWORD(lParam), HIWORD(lParam));
        OutputDebugStringA(str);
        break;
         //键盘消息
    case  WM_KEYDOWN:
        sprintf(str, "键盘按下:  %X, %c
", wParam , wParam);
        OutputDebugStringA(str);
        break;
    case  WM_CHAR:
        sprintf(str, "字符消息:  %X, %c
", wParam, wParam);
        OutputDebugStringA(str);
        break; 
    case  WM_KEYUP:
        sprintf(str, "键盘弹起:  %X, %c
", wParam, wParam);
        OutputDebugStringA(str);
        break;

    case  WM_SYSKEYDOWN: //alt同时按下的键
        sprintf(str, "系统按键按下:  %X, %c
", wParam, wParam);
        OutputDebugStringA(str);
        break;
    case  WM_SYSCHAR:  
        sprintf(str, "系统字符:  %X, %c
", wParam, wParam);
        OutputDebugStringA(str);
        break;
    case  WM_SYSKEYUP:
        sprintf(str, "系统按键弹起:  %X, %c
", wParam, wParam);
        OutputDebugStringA(str);
        break;
    }
    return DefWindowProc(hWnd, Msg, wParam, lParam);
}


int  WINAPI   WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance,
    LPSTR lpCmdLine, int  nShowCmd)
{
    //1.注册窗口类
    WNDCLASS  wnd;
    wnd.cbClsExtra = 0;
    wnd.cbWndExtra = 0;
    wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色
    wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标
    wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
                                                //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息
    wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数
    wnd.lpszClassName = L"MrHuang";//窗口类名
    wnd.lpszMenuName = NULL;//菜单资源名称
    wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式,只有添加CS_DBLCLKS才能响应双击消息
    wnd.hInstance = hInstance;//实例句柄
    RegisterClass(&wnd);

    //创建窗口(返回之前发送WM_CREATE)
    HWND  hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序",
        WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL);

    //显示窗口
    ShowWindow(hWnd, nShowCmd);
    //更新窗口(发送WM_PAINT)
    UpdateWindow(hWnd);
//消息循环(收到WM_QUIT消息退出) MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//分发消息到窗口过程 } }

注:wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式,只有添加CS_DBLCLKS才能响应双击消息

原文地址:https://www.cnblogs.com/mango1997/p/14607520.html