zoukankan      html  css  js  c++  java
  • windows消息机制_PostMessage和SendMessage

    1.子线程中建立一个窗口

    为了在后面比较这两个函数,先使用win32 windows程序中建立子线程,在子线程中建立一个窗口。

    (1)新建一个 win32 windows应用程序

    (2)定义子窗口的窗口响应函数

    LRESULT CALLBACK SubWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
         switch (message)
        {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_LBUTTONDOWN:
            MessageBoxA(0,"","SubWndProc",0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }

    (3)定义子线程窗口函数

    void CreateWndInThread(int nWidth, int nHeight)
    {
        WNDCLASSEX wcex2;  
        wcex2.cbSize = sizeof(WNDCLASSEX);
        wcex2.style = CS_HREDRAW | CS_VREDRAW;
        wcex2.lpfnWndProc = SubWndProc;
        wcex2.cbClsExtra = 0;
        wcex2.cbWndExtra = 0;
        wcex2.hInstance = GetModuleHandle(nullptr);
        wcex2.hIcon = 0;
        wcex2.hCursor = LoadCursor(nullptr, IDC_ARROW);
        wcex2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wcex2.lpszMenuName = NULL;
        wcex2.lpszClassName = L"SubWindow";
        wcex2.hIconSm = 0;
        RegisterClassEx(&wcex2);
        HWND g_hWnd = CreateWindowA("SubWindow", nullptr,WS_OVERLAPPEDWINDOW, 0, 0, nWidth, nHeight, NULL, NULL, wcex2.hInstance, 0);
        ShowWindow(g_hWnd, SW_SHOW);
        UpdateWindow(g_hWnd);
        MSG msg;
        while (GetMessage(&msg, nullptr, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    (4)处理主线程的 WM_LBUTTONDOWN 消息

    在里面开启一个子线程,调用 CreateWndInThread

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        int wmId, wmEvent;
        PAINTSTRUCT ps;
        HDC hdc;
        switch (message)
        {
    
        case WM_LBUTTONDOWN:
            {
                std::thread t(CreateWndInThread, 960, 480);
                t.detach();
            }
            break;
            //省略其他消息
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }

    (5)运行程序

    在主窗口上鼠标左键点击,会创建一个子窗口,

    然后在子窗口上鼠标左键点击,会弹出一个MessageBox。

    可以发现两个窗口的消息处理互不影响。

    2.PostMessage和SendMessage

    PostMessage会将消息压入窗口所在线程的消息队列,然后立即返回,非阻塞

    SendMessage则不经过消息队列,SendMessage可认为是直接调用了该窗口的窗口过程,阻塞

    将上面的项目做如下修改:

    (1)定义一个全局遍历来存储子窗体的句柄,定义子窗体自定义消息

    #define WM_SUB_MSG (WM_USER+1)
    HWND subWinHwnd;//子窗口

    (2)修改子窗口的窗口响应函数

    void CreateWndInThread(int nWidth, int nHeight)
    {
        WNDCLASSEX wcex2;  
        wcex2.cbSize = sizeof(WNDCLASSEX);
        wcex2.style = CS_HREDRAW | CS_VREDRAW;
        wcex2.lpfnWndProc = SubWndProc;
        wcex2.cbClsExtra = 0;
        wcex2.cbWndExtra = 0;
        wcex2.hInstance = GetModuleHandle(nullptr);
        wcex2.hIcon = 0;
        wcex2.hCursor = LoadCursor(nullptr, IDC_ARROW);
        wcex2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wcex2.lpszMenuName = NULL;
        wcex2.lpszClassName = L"SubWindow";
        wcex2.hIconSm = 0;
        RegisterClassEx(&wcex2);
        subWinHwnd = CreateWindowA("SubWindow", nullptr,WS_OVERLAPPEDWINDOW, 0, 0, nWidth, nHeight, NULL, NULL, wcex2.hInstance, 0);
        ShowWindow(subWinHwnd, SW_SHOW);
        UpdateWindow(subWinHwnd);
        MSG msg;
        while (GetMessage(&msg, nullptr, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    (3)修改子线程窗口函数

    LRESULT CALLBACK SubWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
         switch (message)
        {
        case WM_SUB_MSG:
            MessageBoxA(0,"WM_SUB_MSG","子窗体",0);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_LBUTTONDOWN:
            MessageBoxA(0,"左键消息","子窗体",0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }

    (4)修改主窗口的窗口函数

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        int wmId, wmEvent;
        PAINTSTRUCT ps;
        HDC hdc;
        switch (message)
        {
        case WM_LBUTTONDOWN:
            {
                std::thread t(CreateWndInThread, 960, 480);
                t.detach();
            }
            break;
        case WM_RBUTTONDOWN:
            {
              SendMessage(subWinHwnd,WM_SUB_MSG,0,0);
              //PostMessage(subWinHwnd,WM_SUB_MSG,0,0);
              MessageBoxA(0,"右键消息","主窗体",0);
            }
            break;
        case WM_COMMAND:
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // 分析菜单选择:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            // TODO: 在此添加任意绘图代码...
            EndPaint(hWnd, &ps);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }

    (5)运行程序

    发现使用SendMessage(subWinHwnd,WM_SUB_MSG,0,0) ,

    MessageBoxA(0,"右键消息","主窗体",0) 对话框在 MessageBoxA(0,"WM_SUB_MSG","子窗体",0) 后面出现

    使用PostMessage(subWinHwnd,WM_SUB_MSG,0,0)

    MessageBoxA(0,"右键消息","主窗体",0) 对话框在MessageBoxA(0,"WM_SUB_MSG","子窗体",0) 前面出现

    (6)完整代码链接:https://www.aliyundrive.com/s/UtrYB42wyi3

    总结:

    PostMessage会将消息压入窗口所在线程的消息队列,然后立即返回,非阻塞

    SendMessage则不经过消息队列,SendMessage可认为是直接调用了该窗口的窗口过程,阻塞

  • 相关阅读:
    Unity 3(一):简介与示例
    MongoDB以Windows Service运行
    动态SQL中变量赋值
    网站发布IIS后堆栈追踪无法获取出错的行号
    GridView Postback后出错Operation is not valid due to the current state of the object.
    Visual Studio 2010 SP1 在线安装后,找到缓存在本地的临时文件以便下次离线安装
    SQL Server 问题之 排序规则(collation)冲突
    IIS 问题集锦
    linux下安装mysql(ubuntu0.16.04.1)
    apt-get update 系列作用
  • 原文地址:https://www.cnblogs.com/hosseini/p/15178064.html
Copyright © 2011-2022 走看看