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可认为是直接调用了该窗口的窗口过程,阻塞

  • 相关阅读:
    第24课 #pragma使用分析
    第23课 #error和#line使用分析
    第22课 条件编译使用分析
    第21课 宏定义与使用分析
    Codeforces Round #142 (Div. 2)B. T-primes
    SPOJ XMAX
    Uva 10036
    Timus 1009. K-based Numbers
    MBLAST
    ROADS
  • 原文地址:https://www.cnblogs.com/hosseini/p/15178064.html
Copyright © 2011-2022 走看看