我正在尝试检测何时插入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(¬ificationFilter, sizeof(notificationFilter));
notificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
notificationFilter.dbcc_classguid = guid;
this->deviceNotifier = RegisterDeviceNotification(this->hWnd,
¬ificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE);
std::cerr << "done!" << std::endl;
}
void DeviceHandler::unregisterDeviceHandler()
{
UnregisterDeviceNotification(this->deviceNotifier);
}
我猜这不是放置消息循环的正确位置,但我对WinAPI不太满意。如何让程序进入消息循环? (还最好注册设备通知。)
答案 0 :(得分:2)
您应该创建一个message only Window。它可以接收它注册的消息,如设备通知和电源事件,但它永远不会显示。
仅留言window must be registered with 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以及TranslateMessage和DispathMessage,这会将您的WNDPROC称为回调。没错,但是你在Windows程序中丢失了指向DeviceHandler类的指针。
这就是您将this
作为CreateWindowEx
的最后一个参数传递的原因。您可以在收到WM_CREATE
消息时对其进行检索,并使用SetWindowLongPtr
和GWLP_USERDATA
将其设置为您的Windows类用户数据。之后的每次调用都将使用GetWindowLongPtr
检索指针并将其强制转换为DeviceHandler对象。
这是a good example of the technique。
要play by the rules,您应该注册自己的窗口类以使用GWLP_USERDATA
,尽管它仍然可以使用STATIC
窗口类。
最后注意事项:请务必致电DefWindowProc查看您未处理的邮件。
答案 1 :(得分:1)
看起来问题是您的窗口未创建,因为您没有指定有效的类名。在这种情况下返回的HWND
为NULL
,设备无法注册并向其发送消息。
正如在其他答案中提出的那样,您可以使用Message-Only Window来接收设备通知。但是想提一下,在这种情况下不需要注册窗口类,你可以使用预定义的类名,例如STATIC
(因为您实际上不需要指定自己的窗口proc):
HWND hwnd = CreateWindowEx(0, "STATIC", 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);