廣播自定義消息實現進程間的通訊問題

1、背景

  一個進程的線程窗口(window1)如何在不知道另外一個進程的線程窗口(window2)的狀況下接收到window2發送的自定義消息呢?ios

2、自定義消息

  Windows系統除了預約義一些系統的消息外,還爲用戶預留了自定義消息的範圍(WM_USER~0x7FFF)。經過RegisterWindowMessage函數,咱們能夠註冊一個系統惟一的新消息。兩個不一樣的進程註冊了相同的消息字符串,這些應用將會返回相同的消息。直到整個消息會話結束。windows

3、廣播消息

  SendMessage或PostMessage函數能夠向指定的窗口句柄發送窗口消息。若是窗口句柄是HWND_BOARDCAST,就會向系統全部頂層窗口發生該廣播消息。api

4、代碼驗證

  廣播消息的代碼:函數

 1 #include <iostream>
 2 #include <Windows.h>
 3 
 4 int main()
 5 {
 6     // 註冊窗口消息
 7     UINT seewoDesktopProxyMsg = ::RegisterWindowMessageW(L"Seewo_Desktop_Proxy_Message");
 8 
 9     if (0 == seewoDesktopProxyMsg)
10     {
11         std::cout << "RegisterWindowMessageW fail. error code:" << ::GetLastError();
12         return 1;
13     }
14 
15     // 廣播消息
16     HWND hDesktop = GetDesktopWindow();
17     std::cout << "desktop window:" << hDesktop << std::endl;
18     ::PostMessageW(HWND_BROADCAST, seewoDesktopProxyMsg, reinterpret_cast<WPARAM>(hDesktop), 0);
19     system("pause");
20 
21     std::cout << "Hello World!\n";
22 }

接收廣播消息:spa

#include <iostream>
#include <thread>
#include <Windows.h>

UINT seewoDesktopProxyMsg = 0;

void ListenRegistryWindowMessage()
{
    WNDCLASSEX wndClass;
    wndClass.cbSize = sizeof(WNDCLASSEX);
    wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    wndClass.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
    wndClass.lpfnWndProc = reinterpret_cast<WNDPROC>(DefWindowProc);
    wndClass.cbClsExtra = 0;
    wndClass.cbWndExtra = 0;
    wndClass.hIcon = NULL;
    wndClass.hbrBackground = NULL;
    wndClass.hCursor = LoadCursor(0, IDC_ARROW);
    std::wstring className(L"SeewoDesktopProxy_recevie");
    wndClass.lpszClassName = className.c_str();
    wndClass.lpszMenuName = NULL;
    wndClass.hIconSm = NULL;
    if (!RegisterClassEx(&wndClass))
    {
        std::cout << "RegisterClassEx err:" << GetLastError() << std::endl;
    }
    HWND proxyHwnd = CreateWindowEx(WS_EX_NOACTIVATE,
                                    className.c_str(), NULL,
                                    WS_POPUP,
                                    0, 0, 0, 0,
                                    NULL, NULL, 0, NULL);
    if (proxyHwnd == NULL)
    {
        std::cout << "CreateWindowEx err:" << GetLastError() << std::endl;
    }
    std::cout << "create proxy windows success hWnd :" << proxyHwnd << std::endl;
    MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (msg.message == seewoDesktopProxyMsg)
        {
            std::cout << "receive registry window message." << (HWND)(msg.wParam) << std::endl;
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

int main()
{
    // 註冊窗口消息
    seewoDesktopProxyMsg = ::RegisterWindowMessageW(L"Seewo_Desktop_Proxy_Message");

    if (0 == seewoDesktopProxyMsg)
    {
        std::cout << "RegisterWindowMessageW fail. error code:" << ::GetLastError();
        return 1;
    }

    // 接收消息的窗口
    std::thread listen(ListenRegistryWindowMessage);

    listen.join();

    std::cout << "Hello World!\n";
}

運行效果:線程

 

若是使用Spy++監控窗口消息會更加詳細:code

 

 5、注意事項

  接收方必須在發送方發送廣播消息窗口消息隊列建立完成,不然建立前的全部廣播消息都沒法正常接收到。blog

參考地址:https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerwindowmessagea隊列

相關文章
相關標籤/搜索