我创build了一个通用的USB HID通信驱动程序,能够监视USB事件并向设备发送/接收数据包。 自从我的WinForms
日子以来,我一直在成功地使用它,因为很多代码都是从MSDN中挑选出来的,实现方式与此处build议的方式非常相似。 我的问题是:我看到的例子继续依赖于什么似乎是旧的“Windows消息”体系结构,即System.Runtime.InteropServices
,WM_xxxxxxxtypes的消息,注册/处理这些纯粹的C# WPF
应用程序与HwndHandler
,重写WndProc
等等。我想知道有没有办法处理USB事件使用更现代的,事件驱动的方法,与delegates
说,订阅EventHandlers
等? 即使这个 SOpostbuild议不要使用这种古老的方法,我想也必须有USB事件的解决scheme。 感谢名单。
在做了一些研究之后,似乎Windows消息传递是处理USB设备更改通知的必要部分。 我有一个工作的USB通信驱动程序类,其中包括一个简单的实现。 该解决方案由两部分组成:1)产生事件的EventNotifier
类,2)订阅事件的“接收器”(即获得USB事件通知的客户端)。 示例代码是C ++ / CLI,尽管我没有订阅将可执行代码放在头文件中的做法,为了简洁起见,我在这里这样做。
#pragma once #include <Windows.h> // Declares required datatypes. #include <Dbt.h> // Required for WM_DEVICECHANGE messages. #include <initguid.h> // Required for DEFINE_GUID definition (see below). namespace USBComms { using namespace System; using namespace System::Runtime::InteropServices; using namespace System::Windows; using namespace System::Windows::Forms; // This function is required for receieving WM_DEVICECHANGE messages. // Note: name is remapped "RegisterDeviceNotificationUM" [DllImport("user32.dll" , CharSet = CharSet::Unicode, EntryPoint="RegisterDeviceNotification")] extern "C" HDEVNOTIFY WINAPI RegisterDeviceNotificationUM( HANDLE hRecipient, LPVOID NotificationFilter, DWORD Flags); // Generic guid for usb devices (see eg http://msdn.microsoft.com/en-us/library/windows/hardware/ff545972%28v=vs.85%29.aspx). // Note: GUIDs are device and OS specific and may require modification. Using the wrong guid will cause notification to fail. // You may have to tinker with your device to find the appropriate GUID. "hid.dll" has a function `HidD_GetHidGuid' that returns // "the device interfaceGUID for HIDClass devices" (see http://msdn.microsoft.com/en-us/library/windows/hardware/ff538924%28v=vs.85%29.aspx). // However, testing revealed it does not always return a useful value. The GUID_DEVINTERFACE_USB_DEVICE value, defined as // {A5DCBF10-6530-11D2-901F-00C04FB951ED}, has worked with cell phones, thumb drives, etc. For more info, see eg // http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx. DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED); /// <summary> /// Declare a delegate for the notification event handler. /// </summary> /// <param name="sender">The object where the event handler is attached.</param> /// <param name="e">The event data.</param> public delegate void NotificationEventHandler(Object^ sender, EventArgs^ e); /// <summary> /// Class that generetaes USB Device Change notification events. /// </summary> /// <remarks> /// A Form is not necessary. Any type wherein you can override WndProc() can be used. /// </remarks> public ref class EventNotifier : public Control { private: /// <summary> /// Raises the NotificationEvent. /// </summary> /// <param name="e">The event data.</param> void RaiseNotificationEvent(EventArgs^ e) { NotificationEvent(this, e); } protected: /// <summary> /// Overrides the base class WndProc method. /// </summary> /// <param name="message">The Windows Message to process. </param> /// <remarks> /// This method receives Windows Messages (WM_xxxxxxxxxx) and /// raises our NotificationEvent as appropriate. Here you should /// add any message filtering (eg for the WM_DEVICECHANGE) and /// preprocessing before raising the event (or not). /// </remarks> virtual void WndProc(Message% message) override { if(message.Msg == WM_DEVICECHANGE) { RaiseNotificationEvent(EventArgs::Empty); } __super::WndProc(message); } public: /// <summary> /// Creates a new instance of the EventNotifier class. /// </summary> EventNotifier(void) { RequestNotifications(this->Handle); // Register ourselves as the Windows Message processor. } /// <summary> /// Registers an object, identified by the handle, for /// Windows WM_DEVICECHANGE messages. /// </summary> /// <param name="handle">The object's handle.</param> void RequestNotifications(IntPtr handle) { GUID InterfaceClassGuid = GUID_DEVINTERFACE_USB_DEVICE; DEV_BROADCAST_DEVICEINTERFACE MyDeviceBroadcastHeader; MyDeviceBroadcastHeader.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; MyDeviceBroadcastHeader.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); MyDeviceBroadcastHeader.dbcc_reserved = 0; MyDeviceBroadcastHeader.dbcc_classguid = InterfaceClassGuid; RegisterDeviceNotificationUM((HANDLE)handle, &MyDeviceBroadcastHeader, DEVICE_NOTIFY_WINDOW_HANDLE); } /// <summary> /// Defines the notification event. /// </summary> virtual event NotificationEventHandler^ NotificationEvent; }; }
然后,在“接收者”(订阅和使用我们的NotificationEvent
的对象中,你所要做的就是:
void Receiver::SomeFunction(void) { USBComms::EventNotifier usb = gcnew USBComms::EventNotifier(); usb->NotificationEvent += gcnew USBComms::NotificationEventHandler(this, &Receiver::USBEvent); } void Receiver::USBEvent(Object^ sender, EventArgs^ e) { // Handle the event notification as appropriate. }