Device Notification - präziser darstellen anhand lParam und wParam
-
Hallo nochmal
@Mox habe dein Vorschlag eingebaut und Fehler beseitigt. Also bekomme schonmal verschiedene Ausgaben. Danke für den Tipp!Habe nun folgende bibliothek "#include "hidsdi.h"" eingebunden.
Nun bekomme ich auch keine Linker Fehler und ich bekomme interessante Ausgaben:
Message 1: DBT_DEVNODES_CHANGED //Beim abstecken eines bereits angeschlossenen HID-Device
Message 2: DBT_DEVICEREMOVECOMPLETE
Message 3: DBT_DEVICEREMOVECOMPLETEMessage 4: DBT_DEVNODES_CHANGED //Beim wieder anstecken
Message 5: DBT_DEVNODES_CHANGED
Message 6: DBT_DEVNODES_CHANGED
Message 7: DBT_DEVNODES_CHANGED
Message 8: DBT_DEVNODES_CHANGED
Message 9: DBT_DEVNODES_CHANGED
Message 10: DBT_DEVNODES_CHANGED
Message 11: DBT_DEVICEARRIVAL
Message 12: DBT_DEVNODES_CHANGED
Message 13: DBT_DEVICEARRIVAL
Message 14: DBT_DEVNODES_CHANGEDDas ist schonmal gut!
Aber mein Problem ist, will ich nun das geöffnete Fenster mit dem x rechts oben schließen, bekomm ich einen Windows(??)-fehler:UnregisterDeviceNotification failed with error 1784: Der angegebene Benutzerpuffer ist für den angeforderten Vorgang nicht zulässig.
Wo schau ich denn jetzt am besten nach dem Fehler für den Puffer?
-
pargus schrieb:
Das ist schonmal gut!
Na siehste.
pargus schrieb:
Aber mein Problem ist, will ich nun das geöffnete Fenster mit dem x rechts oben schließen, bekomm ich einen Windows(??)-fehler:
UnregisterDeviceNotification failed with error 1784: Der angegebene Benutzerpuffer ist für den angeforderten Vorgang nicht zulässig.
Wo schau ich denn jetzt am besten nach dem Fehler für den Puffer?
Wie ich vorhin schon sagte, Du musst Dir den Rückgabewert von RegisterDeviceNotification merken. Also:
h = RegisterDeviceNotification(..); . . . UnregisterDeviceNotification(h);
-
case WM_CLOSE: if (!UnregisterDeviceNotification(RegisterDeviceNotification)) { ErrorHandler(TEXT("UnregisterDeviceNotification")); } DestroyWindow(hWnd); break;
Hab ich ja gemacht kommt aber immer noch der Fehler beim Schließen des Fensters
(Aber siehste so dumm bin ich auch net
;))
Haste irgendwelche Ideen?
oder auch zu oben?
-
Habe weiter geforscht und denke dass ich zumindest weiß wo der Fehler entsteht:
void ErrorHandler( LPTSTR lpszFunction ) // Routine Description: // Support routine. // Retrieve the system error message for the last-error code // and pop a modal alert box with usable info. // Parameters: // lpszFunction - String containing the function name where // the error occurred plus any other relevant data you'd // like to appear in the output. // Return Value: // None // Note: // This routine is independent of the other windowing routines // in this application and can be used in a regular console // application without modification. { LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); // Display the error message and exit the process. lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR)lpDisplayBuf, g_pszAppName, MB_OK); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); }
irgendwie gibt er diesen Fehler aus. Ich denke (vllt stimmts auch nciht) dass in einen der drei folgenden Funktionen etwas nicht stimmt:
-lpszFunction,
-dw = GetLastError() und
-lpMsgBufIch update ich sobald ich was neues hab. Bitte zu jedem Post wenn ihr Anmerkungen habt einfach reinschreiben
-
pargus schrieb:
if (!UnregisterDeviceNotification(RegisterDeviceNotification))
Hilfe! Du sollst hier keinen Funktionszeiger übergeben, sondern den Rückgabewert des vorherigen Aufrufs von RegisterDeviceNotification. Das, was Du da geschrieben hast, ist genau so ein Nonsens wie dieses hier:
free(malloc));
Ich hoffe, es brennt Dir jetzt ebenso in den Augen wie mir.
-
Mox schrieb:
free(malloc));
Ich hoffe, es brennt Dir jetzt ebenso in den Augen wie mir.
ok leuchtet mir jetzt auch ein.
Hab das jetzt mit nem HANDLE h; und h = RegisterDeviceNotification(..); und UnregisterDeviceNotification(h) wieder wegbekommen.
Wie gesagt kenn mich mit den Bedeutungen von den Windows Funktionen auch nicht gut aus. (Wusste also nicht das RegisterDeviceNotification ein Funktionszeiger ist.)
Darum bitte ich euch ja um Hilfe.
Hast du auch noch vorschläge wie ich eventuell genauere Details über folgende Nachrichten bekommen kann (oder ist das nciht möglich?):
Registered for USB device notification... Message 1: DBT_DEVNODES_CHANGED Message 2: DBT_DEVICEREMOVECOMPLETE Message 3: DBT_DEVICEREMOVECOMPLETE Message 4: DBT_DEVNODES_CHANGED Message 5: DBT_DEVNODES_CHANGED Message 6: DBT_DEVNODES_CHANGED Message 7: DBT_DEVNODES_CHANGED Message 8: DBT_DEVNODES_CHANGED Message 9: DBT_DEVNODES_CHANGED Message 10: DBT_DEVNODES_CHANGED Message 11: DBT_DEVICEARRIVAL Message 12: DBT_DEVNODES_CHANGED Message 13: DBT_DEVICEARRIVAL Message 14: DBT_DEVNODES_CHANGED
-
pargus schrieb:
Hast du auch noch vorschläge wie ich eventuell genauere Details über folgende Nachrichten bekommen kann (oder ist das nciht möglich?):
Die Details findest Du unter Device Management Events. Konzentriere Dich aber auf DBT_DEVICEARRIVAL und DBT_DEVICEREMOVECOMPLETE, das sind für Deine Anwendung die einzig interessanten Notifications. Den Rest darfst Du zunächst ruhigen Gewissens ignorieren.
-
pargus schrieb:
Wie gesagt kenn mich mit den Bedeutungen von den Windows Funktionen auch nicht gut aus. (Wusste also nicht das RegisterDeviceNotification ein Funktionszeiger ist.)
Was hast Du denn gedacht was das sonst ist? Ein Funktions-Aufruf kann es ja schließlich nicht sein, denn dafür hätte sich ja wohl mindestens noch eine Klammer öffnen müssen. Das passiert aber nicht, der Name der Funktion steht einfach nur da.
Und das hat mit Windows nichts zu tun, Das sind C-Grundlagen.
-
Hallo nochmal
ich bin noch bei dem selben Thema mit dem USB Port und den Notficiations aber schon bissal weiter.
da ich ja folgende Ausgabe kriege:
Nachrichten beim Abstecken
Message: DBT_DEVNODES_CHANGED Message: DBT_DEVICEREMOVECOMPLETE Message: DBT_DEVICEREMOVECOMPLETE Message: DBT_DEVNODES_CHANGED
Nachrichten beim ANstecken
Message: DBT_DEVNODES_CHANGED Message: DBT_DEVNODES_CHANGED Message: DBT_DEVNODES_CHANGED Message: DBT_DEVNODES_CHANGED Message: DBT_DEVNODES_CHANGED Message: DBT_DEVNODES_CHANGED Message: DBT_DEVICEARRIVAL Message: DBT_DEVNODES_CHANGED Message: DBT_DEVICEARRIVAL Message: DBT_DEVNODES_CHANGED
Dies kommt wenn ich meine Platine an oder abstecke, darum habe ich mit meinem Prof ausgemacht , wir kümmern uns nur um das erste "arrival" und das erste "removal" notification.
Mein Problem ist nur wie kann ich das in dem unten stehenden code anbauen, dass er mir die erste Nachricht von Removal ausspuckt und die nächste drei ignoriert, aber trotzdem bei einem erneuten abstecken eines anderen GErätes wieder eine removal nachricht ausgibt und wieder die restlichen ignoriert.
Code:
// // WinProcCallback // INT_PTR WINAPI WinProcCallback( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) // Routine Description: // Simple Windows callback for handling messages. // This is where all the work is done because the example // is using a window to process messages. This logic would be handled // differently if registering a service instead of a window. // Parameters: // hWnd - the window handle being registered for events. // message - the message being interpreted. // wParam and lParam - extended information provided to this // callback by the message sender. // For more information regarding these parameters and return value, // see the documentation for WNDCLASSEX and CreateWindowEx. { 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. ErrorHandler(TEXT("CreateWindow: Edit Control")); 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. // PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE) lParam; TCHAR strBuff[256]; // Output some messages to the window. switch (wParam) { case DBT_DEVICEARRIVAL: msgCount++; StringCchPrintf( strBuff, 256, TEXT("Message %d: DBT_DEVICEARRIVAL\n"), msgCount); break; case DBT_DEVICEREMOVECOMPLETE: msgCount++; StringCchPrintf( strBuff, 256, TEXT("Message %d: DBT_DEVICEREMOVECOMPLETE\n"), msgCount); break; case DBT_DEVNODES_CHANGED: msgCount++; StringCchPrintf( strBuff, 256, TEXT("Message %d: DBT_DEVNODES_CHANGED\n"), msgCount); break; default: msgCount++; StringCchPrintf( strBuff, 256, TEXT("Message %d: WM_DEVICECHANGE message received, value %d unhandled.\n"), msgCount, wParam); break; } OutputMessage(hEditWnd, wParam, (LPARAM)strBuff); } break; case WM_CLOSE: if ( ! UnregisterDeviceNotification(hDeviceNotify) ) { ErrorHandler(TEXT("UnregisterDeviceNotification")); } DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: // Send all other messages on to the default windows handler. lRet = DefWindowProc(hWnd, message, wParam, lParam); break; } return lRet; }
Mittlerweile schauen meine Cases wie folgt aus
case WM_DEVICECHANGE: { // declaration of the structures for later usage // new structur for the output of every table item, to allocate memory for the structure and fill it with the function "hid_devchange" HID_INFO_INTERN *hid_info3 = (HID_INFO_INTERN*)malloc(sizeof(HID_INFO_INTERN)); int i = 0; //HID_INFO_INTERN *hid_info2; // for test below //HID_INFO_PUBLIC hid_public2; // // 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. // PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE)lParam; TCHAR strBuff[256]; // Output some messages to the window. switch (wParam) { // wParam = 0x8004 // lParam = A pointer to a structure identifying the device inserted. // The structure consists of an event-independent header, followed by // event-dependent members that describe the device. To use this structure, // treat the structure as a DEV_BROADCAST_HDR structure, then check its dbch_devicetype // member to determine the device type. case DBT_DEVICEARRIVAL: { msgCount++; // Output message of Arrival-Notification logprintf(L"Message: DBT_DEVICEARRIVAL\n"); // deallocate the allocated memory free(hid_info3); } break; // wParam = 0x8004 // lParam = A pointer to a structure identifying the device removed. // The structure consists of an event-independent header, // followed by event-dependent members that describe the device. // To use this structure, treat the structure as a DEV_BROADCAST_HDR structure, // then check its dbch_devicetype member to determine the device type. case DBT_DEVICEREMOVECOMPLETE: msgCount++; logprintf(L"Message: DBT_DEVICEREMOVECOMPLETE\r\n"); // deallocate the allocated memory free(hid_info3); break; // wParam = 0x0007 // lParam = Set to zero. case DBT_DEVNODES_CHANGED: //F12 msgCount++; //hid_devchange(hid_info3, i); logprintf(L"Message: DBT_DEVNODES_CHANGED\n"); // deallocate the allocated memory free(hid_info3); break; default: msgCount++; loggprintf(L"WM_DEVICECHANGE message received, value %d unhandled.\n", wParam); break; } } break;
Falls einer ne Idee hat wie ich nur in einmal in den Case reingehe und danach für dieses eine Abstecken nicht mehr (also die drei anderen "Removals" ignoriere) wäre ich sehr dankbar weil ich grad aufm Schlauch stehe.
Danke Markus
-
pargus schrieb:
Falls einer ne Idee hat wie ich nur in einmal in den Case reingehe und danach für dieses eine Abstecken nicht mehr (also die drei anderen "Removals" ignoriere) wäre ich sehr dankbar weil ich grad aufm Schlauch stehe.
Welche drei anderen Removals? Du bekommst doch insgesamt nur zwei gesendet, ich zitiere:
pargus schrieb:
Message: DBT_DEVNODES_CHANGED
Message: DBT_DEVICEREMOVECOMPLETE
Message: DBT_DEVICEREMOVECOMPLETE
Message: DBT_DEVNODES_CHANGEDAnsonsten sollst Du gefälligst beide Removals bearbeiten. Oder woher weißt Du, welche der beiden Nachrichten für Dich interessant ist? Bislang schaust Du nicht nach, ob es überhaupt ein Removal für Dein Gerät ist. Du schaust Dir die Informationen gleich gar nicht an.
Du wartest doch auf Ereignisse, die Device-Interfaces betreffen. Schau nach, ob Du per LPARAM Strukturen des Typs DBT_DEVTYP_DEVICEINTERFACE übermittelt bekommst. Dann schaust Du, ob es Dein Gerät betrifft. Und wenn Du dieses Gerät nicht oder nicht mehr geöffnet hast, machst Du eben auch nichts.
Nur auf das erste Removal zu reagieren, geht definitiv in die Büx. Aber schön, dass Du zumindest mit Deinem Prof einig bist. Man, man...