gpt4 book ai didi

C++ Win32 在 WM_DEVICECHANGE 上未收到 DBT_DEVICEARRIVAL 或 DBT_DEVICEREMOVECOMPLETE

转载 作者:可可西里 更新时间:2023-11-01 15:56:59 27 4
gpt4 key购买 nike

我一直致力于检测 USB 插入/移除。我已经使用 CreateWindowEx() 实现了代码,通过我的窗口进程回调传递了一个 WNCLASSEX。在插入和移除 USB 时,我成功收到 WM_DEVICECHANGE 消息,但 wParam 始终设置为 DBT_DEVNODES_CHANGED。

我从来没有得到 DBT_DEVICEARRIVAL 或 DBT_DEVICEREMOVECOMPLETE。我一直在使用我得到的东西,但我确实需要能够区分设备到达和移除之间的区别,以便我可以根据收到的设备采取不同的操作。

现在,我必须在收到 DBT_DEVNODES_CHANGED 后设置一个计时器,然后测试系统上是否有任何新的可移动设备,或者我的列表中是否不再存在。我确定这是不对的,所以我想我会问。我宁愿摆脱计时器而只接收这两条消息。这对我必须做的事情有很大帮助。有什么建议吗?

这是我用于注册回调的代码,以及回调本身:

注意:3/12/2015:更新代码以显示实际 GUID 和 DoRegisterDeviceInterfaceToHwnd() 函数的定义。:

GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72, 0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 };
//GUID WusbrawGUID = {0xa5dcbf10, 0x6530, 0x11d2, 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed };
//GUID WusbGUID = {0x88BAE032, 0x5A81, 0x49f0, 0xBC, 0x3D, 0xA4, 0xFF, 0x13, 0x82, 0x16, 0xD6 };

INT_PTR WINAPI WinProcCallback(HWND __hWnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL DoRegisterDeviceInterfaceToHwnd(GUID InterfaceClassGuid, HWND __hWnd, HDEVNOTIFY *hDeviceNotify);

bool UsbController::startNotifyUsbAddedRemoved(QString &errmsg)
{
WNDCLASSEX wndClass;

wndClass.cbSize = sizeof(wndClass);
wndClass.style = 0;
wndClass.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
wndClass.lpfnWndProc = reinterpret_cast<WNDPROC>(WinProcCallback);
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndClass.hCursor = LoadCursor(0, IDC_ARROW);
wndClass.lpszClassName = WND_CLASS_NAME;
wndClass.lpszMenuName = NULL;
wndClass.hIconSm = LoadIcon(0, IDI_APPLICATION);

if (!RegisterClassEx(&wndClass))
{
FormatErrorMsg("RegisterClassEx: ", errmsg);
return false;
}

HINSTANCE hInstance = (HINSTANCE)::GetModuleHandle(NULL);
__hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE | WS_EX_APPWINDOW,
WND_CLASS_NAME,
WND_APP_NAME,
WS_OVERLAPPEDWINDOW, // style
CW_USEDEFAULT, 0,
0, 0,
NULL, NULL,
hInstance,
NULL);

if ( __hWnd == NULL )
{
FormatErrorMsg("CreateWindowEx: ", errmsg);
return false;
}

return true;
}

INT_PTR WINAPI WinProcCallback(HWND __hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lRet = 1;
static HDEVNOTIFY hDeviceNotify;
static HWND hEditWnd;
static ULONGLONG msgCount = 0;

switch (message)
{
case WM_CREATE:
//
// This is the actual registration., In this example, registration
// should happen only once, at application startup when the window
// is created.
//
// If you were using a service, you would put this in your main code
// path as part of your service initialization.
//
if ( ! DoRegisterDeviceInterfaceToHwnd( WceusbshGUID, __hWnd, &hDeviceNotify) )
{
// Terminate on failure.
//ErrorHandler(TEXT("DoRegisterDeviceInterfaceToHwnd"));
ExitProcess(1);
}

//
// Make the child window for output.
//
hEditWnd = CreateWindow(TEXT("EDIT"),// predefined class
NULL, // no window title
WS_CHILD | WS_VISIBLE | WS_VSCROLL |
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
0, 0, 0, 0, // set size in WM_SIZE message
__hWnd, // parent window
(HMENU)1, // edit control ID
(HINSTANCE) GetWindowLong(__hWnd, GWL_HINSTANCE),
NULL); // pointer not needed

if ( hEditWnd == NULL )
{
// Terminate on failure.
ExitProcess(1);
}
// Add text to the window.
SendMessage(hEditWnd, WM_SETTEXT, 0,
(LPARAM)TEXT("Registered for USB device notification...\n"));

break;

case WM_SETFOCUS:
SetFocus(hEditWnd);

break;

case WM_SIZE:
// Make the edit control the size of the window's client area.
MoveWindow(hEditWnd,
0, 0, // starting x- and y-coordinates
LOWORD(lParam), // width of client area
HIWORD(lParam), // height of client area
TRUE); // repaint window

break;

case WM_DEVICECHANGE:
{
//
// This is the actual message from the interface via Windows messaging.
// This code includes some additional decoding for this particular device type
// and some common validation checks.
//
// Note that not all devices utilize these optional parameters in the same
// way. Refer to the extended information for your particular device type
// specified by your GUID.
//

// Output some messages to the window.
UsbController *pusbctl;
switch (wParam)
{
case DBT_DEVICEARRIVAL:
msgCount++;
pusbctl = UsbController::instance();
pusbctl->signalDeviceArrival();
break;
case DBT_DEVICEREMOVECOMPLETE:
msgCount++;
pusbctl = UsbController::instance();
pusbctl->signalDeviceRemoval();
break;
case DBT_DEVNODES_CHANGED:
msgCount++;
pusbctl = UsbController::instance();
pusbctl->signalDeviceAddedRemoved();
break;
default:
msgCount++;
break;
}
}
break;

default:
// Send all other messages on to the default windows handler.
lRet = DefWindowProc(__hWnd, message, wParam, lParam);
break;
}

return lRet;
}

BOOL DoRegisterDeviceInterfaceToHwnd(GUID InterfaceClassGuid, HWND __hWnd, HDEVNOTIFY *hDeviceNotify)
{
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;

ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
//NotificationFilter.dbcc_devicetype = DEVICE_NOTIFY_ALL_INTERFACE_CLASSES;
NotificationFilter.dbcc_classguid = InterfaceClassGuid;

*hDeviceNotify = RegisterDeviceNotification(
__hWnd, // events recipient
&NotificationFilter, // type of device
DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle
);

if ( NULL == *hDeviceNotify )
{
return FALSE;
}

return TRUE;
}

最佳答案

如果您阅读 MSDN 的文档,它会说:

Detecting Media Insertion or Removal

Windows sends all top-level windows a set of default WM_DEVICECHANGE messages when new devices or media (such as a CD or DVD) are added and become available, and when existing devices or media are removed. You do not need to register to receive these default messages. See the Remarks section in RegisterDeviceNotification for details on which messages are sent by default.

RegisterDeviceNotification function

Any application with a top-level window can receive basic notifications by processing the WM_DEVICECHANGE message. Applications can use the RegisterDeviceNotification function to register to receive device notifications.
...
The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events are automatically broadcast to all top-level windows for port devices. Therefore, it is not necessary to call RegisterDeviceNotification for ports, and the function fails if the dbch_devicetype member is DBT_DEVTYP_PORT.

DEV_BROADCAST_HDR structure

DBT_DEVTYP_PORT
0x00000003

Port device (serial or parallel). This structure is a DEV_BROADCAST_PORT structure.

USB 设备不是串行/并行端口。它是一个设备接口(interface) (DBT_DEVTYP_DEVICEINTERFACE)。 DBT_DEVICEARRIVAL/DBT_DEVICEREMOVECOMPLETE DBT_DEVICEERFACE 设备默认情况下 不会发送。如果您需要它们,您必须使用 RegisterDeviceNotification() 来请求它们。

看起来您的代码是基于这个 MSDN 示例:

Registering for Device Notification

在该代码中,WceusbshGUID 被定义为 {25dbce51-6c8f-4a72-8a6d-b54c2b4fc835},它被注释为 USB 的类 guid串行主机 PnP 驱动程序。根据这个 MSDN 页面:

System-Defined Device Setup Classes Available to Vendors

该 guid 是 Windows CE USB ActiveSync Devices 的类 guid(与代码中使用的 Wceusb... 前缀更一致)。在同一页面上还有 {88BAE032-5A81-49f0-BC3D-A4FF138216D6} 用于USB 设备(所有不属于另一个的 USB 设备类)。

以下 CodeProject 文章:

Detecting Hardware Insertion and/or Removal

提及 {a5dcbf10-6530-11d2-901f-00c04fb951ed} 用于 USB 原始设备。同样的 guid 在 MSDN 上记录为 GUID_DEVINTERFACE_USB_DEVICE (其命名可能源于 XP 之前的日子,当时类 guid 和接口(interface) guid 的命名为 was not well separated)。

因此,当您使用特定类 guid 调用 RegisterDeviceNotification() 时,确保它是正确类 guid,因为您要仅获取该特定 类型设备的设备事件。很可能您的 USB 设备使用的类 guid 与您正在注册的类 guid 不同,这就是您没有获得预期的设备事件的原因。

如果您想检测任何 USB 设备而不考虑其类 guid(并且定义了多个 USB 类 guid),您可以在调用时使用 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES 标志 RegisterDeviceNotification(),则类 guid 将被忽略。在 DBT_DEVICEARRIVALDBT_DEVICEREMOVECOMPLETE 消息中(假设您现在可以获取它们),报告的 dbcc_classguid 将告诉您实际的类 guid,并且报告的 dbcc_name 将以 \\?\USB: 前缀开头。

最后一件事 - 如果在您的应用程序已经运行时插入/移除 USB 设备,您只会收到 DBT_DEVICE... 消息。要在您的应用程序启动时检测 USB 设备是否已插入,您必须使用 SetupAPI函数(SetupDiGetClassDevs()SetupDiEnumDeviceInterfaces()SetupDiGetDeviceInterfaceDetail() 等)枚举可用设备。

关于C++ Win32 在 WM_DEVICECHANGE 上未收到 DBT_DEVICEARRIVAL 或 DBT_DEVICEREMOVECOMPLETE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28998625/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com