2

我正在尝试检测何时插入 USB 驱动器。现在,我正在创建一个虚拟窗口并RegisterDeviceNotification对其进行编译。但是,我认为我的方法不正确,因为窗口似乎没有收到消息。

#include <iostream>
#define WINVER 0x501
#include <windows.h>
#include <dbt.h>
#include "devicehandler.h"
#include "remover.h"

DeviceHandler::DeviceHandler(Remover* remover)
{
    this->remover = remover;
    this->hWnd = this->createHandleWindow();
    this->registerDeviceHandler();
    this->messageLoop(this->hWnd);
}

DeviceHandler::~DeviceHandler()
{
    this->unregisterDeviceHandler();
}

void DeviceHandler::messageLoop(HWND hWnd)
{
    std::cerr << "Entering message loop." << std::endl; // Gets here!

    MSG msg;
    while (GetMessage(&msg, this->hWnd, 0, 0)) {
        std::cerr << "Loop!" << std::endl; // Does not get here!
        switch (msg.message) {
            case WM_DEVICECHANGE:
                {
                    PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR) msg.lParam;
                    switch(msg.wParam) {
                        case DBT_DEVICEARRIVAL:
                            std::cerr << "Device added!" << std::endl;
                            break;
                        default:
                            std::cerr << "Other device event." << std::endl;
                            break;
                    }
                    break;
                }
            default:
                break;
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

HWND DeviceHandler::createHandleWindow()
{
    std::cerr << "Creating handle window... ";

    HWND hWnd = CreateWindow(NULL, NULL, WS_ICONIC, 0, 0, CW_USEDEFAULT, 0,
                             NULL, NULL, GetModuleHandle(NULL), NULL);
    ShowWindow(hWnd, SW_HIDE);

    std::cerr << "done!" << std::endl;
    return hWnd;
}

void DeviceHandler::registerDeviceHandler()
{
    std::cerr << "Device notification handling... ";
    // GUID guid = { 0xa5dcbf10, 0x6530, 0x11d2, { 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed } };
    GUID guid = { 0x25dbce51, 0x6c8f, 0x4a72, { 0x8a, 0x6d, 0xb5, 0x4c, 0x2b, 0x4f, 0xc8, 0x35 } };
    DEV_BROADCAST_DEVICEINTERFACE notificationFilter;
    ZeroMemory(&notificationFilter, sizeof(notificationFilter));
    notificationFilter.dbcc_size       = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    notificationFilter.dbcc_classguid  = guid;

    this->deviceNotifier = RegisterDeviceNotification(this->hWnd,
                                                      &notificationFilter,
                                                      DEVICE_NOTIFY_WINDOW_HANDLE);
    std::cerr << "done!" << std::endl;
}

void DeviceHandler::unregisterDeviceHandler()
{
    UnregisterDeviceNotification(this->deviceNotifier);
}

我猜这不是放置消息循环的正确位置,但我对 WinAPI 不是很好。如何让我的程序进入消息循环?(并且最好注册设备通知。)

4

2 回答 2

2

您应该只创建一条消息 Window。它可以接收它注册的消息,如设备通知和电源事件,但它永远不会显示。

仅消息窗口必须使用 RegisterClassEx 注册

注册窗口类后,您可以将窗口类名称与 HWND_MESSAGE 作为父级一起传递给 CreateWindowEx。您的 CreateWindow 应该使用CreateWindowEx如下所示:

HWND hWnd = CreateWindowEx(0, myClassName, _T("This is not the class name"), 
                0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, this);

您仍将使用 GetMessage 以及TranslateMessageDispathMessage,它们会像回调一样调用您的 WNDPROC。这没有错,但是您在 Windows 过程中丢失了指向您的 DeviceHandler 类的指针。

这就是为什么您this作为CreateWindowEx. 您可以在收到消息时检索它,并使用和WM_CREATE将其设置为您的 windows 类用户数据。之后的每个调用都将检索指针并将其转换为 DeviceHandler 对象。SetWindowLongPtrGWLP_USERDATAGetWindowLongPtr

这是该技术的一个很好的例子

遵守规则,您应该注册自己的窗口类来使用GWLP_USERDATA,尽管它仍然可以使用STATIC窗口类。

最后一点:一定要为你不处理的消息调用DefWindowProc 。

于 2012-09-25T13:12:27.107 回答
1

看起来问题是您的窗口没有创建,因为您没有指定有效的类名。HWND在这种情况下返回的是NULL并且设备无法注册它并向其发送消息。

正如其他答案中所建议的那样,您可以使用Message-Only Window来接收设备通知。但想提一下,在这种情况下不需要注册窗口类,您可以使用预定义的类名,例如STATIC(因为您实际上不需要指定自己的窗口过程):

HWND hwnd = CreateWindowEx(0, "STATIC", 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
于 2012-09-25T14:33:45.607 回答