如何检测新监视器的添加?

时间:2013-05-30 16:14:10

标签: c++ winapi windows-messages

我有一个无窗口程序,可以处理一些窗口管理热键。我想提供诸如在监视器之间移动窗口的功能。我已经使用EnumDisplayMonitors来枚举系统中所有现有的监视器,并且我编写了代码来处理WM_DEVICECHANGE,但我实际上并没有收到消息。

这是我的消息循环:

// I've tried GetMessage(&msg, (HWND) NULL, 0, 0) here too
while (GetMessage(&msg, (HWND) -1, 0, 0) > 0)
{
    int key;
    int mod;

    MessageBox(NULL, (LPCWSTR) ((std::wostringstream&) (std::wostringstream() << L"You got a message: " << msg.message)).str().c_str(), L"Got Message", MB_OK);

    switch (msg.message)
    {
    case WM_HOTKEY:
        key = HIWORD(msg.lParam);
        mod = LOWORD(msg.lParam);

        if (mod != MOD_WIN) continue;
        ProcessHotkey(key);
        break;
    case WM_DEVICECHANGE:
        InitMonitorInfo();
    }
}

程序编译并运行正常,热键工作。添加或删除监视器后,没有任何反应。用于指示已收到消息的消息框永远不会出现。

我想我可以每隔5秒轮询显示器配置,但这不是解决问题的正确方法。

我是否需要实际创建一个窗口来接收WM_DEVICECHANGE?因为我没有。热键在发送时将消息发布到NULL,因为它们没有绑定到窗口,由主线程处理。

1 个答案:

答案 0 :(得分:7)

您必须创建一个窗口以获取WM_DEVICECHANGE消息。

WM_DEVICECHANGE是一种广播的消息,SendMessage(HWND_BROADCAST,...)样式。只有顶级窗口才能接收它。窗口不需要是可见的,因此没有理由寻找替代方案。

RegisterDeviceNotification()是另一种选择。但那仍然需要一个窗口。或服务句柄,但您不希望从服务移动窗口。它们与自己的桌面在一个独立的会话中运行。所以创建一个窗口是一个很难的要求。