Ho lavorato per rilevare l'inserimento/rimozione USB. Ho implementato il codice utilizzando CreateWindowEx(), passando un WNCLASSEX che con la mia finestra elabora il callback. Inserendo e rimuovendo il mio usb, ricevo correttamente il messaggio WM_DEVICECHANGE, ma wParam è sempre impostato su DBT_DEVNODES_CHANGED.C++ Win32 Non riceve DBT_DEVICEARRIVAL o DBT_DEVICEREMOVECOMPLETE su WM_DEVICECHANGE
Non ottengo mai DBT_DEVICEARRIVAL o DBT_DEVICEREMOVECOMPLETE. Ho usato quello che sto ottenendo, ma ho davvero bisogno di essere in grado di distinguere tra l'arrivo e la rimozione del dispositivo, in modo da poter intraprendere azioni diverse a seconda di ciò che ricevo.
In questo momento, devo mettere un timer dopo aver ricevuto DBT_DEVNODES_CHANGED, e quindi testare per vedere se ci sono nuovi rimovibili sul sistema, o se qualcuno nel mio elenco non ci sono più. Sono sicuro che non è giusto, quindi ho pensato di chiederlo. Preferisco di gran lunga liberarmi del timer e semplicemente ricevere questi due messaggi. Ciò aiuterebbe molto in quello che dovevo fare. Eventuali suggerimenti?
Ecco il codice che ho per la registrazione del callback, così come il callback per sé:
NOTA: la funzione di codice aggiornato per mostrare GUID reale e la definizione della DoRegisterDeviceInterfaceToHwnd(): 2015/03/12 .):
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;
}
Hai visto https://msdn.microsoft.com/en-us/library/windows/desktop/aa363215(v=vs.85).aspx?Dice che in realtà non è necessario registrarsi per ricevere notifiche di arrivo dei media. Mi chiedo se il fatto che tu ** stia ** registrando potrebbe interferire in qualche modo. –
Hmm, la mia sfera di cristallo dice che stai facendo questo il modo del programmatore, semplicemente strappando il dispositivo senza passare attraverso il "Safely Remove Hardware" spiel. E poi sperare che Windows possa indovinare cosa potrebbe essere successo. Beh, lo ha fatto, te ne ha parlato. –
In realtà, ho sicuramente eseguito il processo "Rimozione sicura dell'hardware". La notifica che ottengo lì ha un valore di 7, che è DBT_DEVNODES_CHANGED. Ricevo un numero di messaggi provenienti da quell'unica azione (non avendo ancora estratto il dispositivo dallo slot), che hanno tutti un valore di 7. Ovviamente, quando tiro il dispositivo, ottengo lo stesso valore. L'inserimento del dispositivo ha gli stessi esatti risultati. Ricevo un numero di messaggi e tutti hanno il valore 7 per DBT_DEVNODES_CHANGED. – bmahf