广播自定义消息实现进程间的通讯问题

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队列

相关文章
相关标签/搜索