处理的Windows USB事件 [英] Handling Windows USB events

查看:554
本文介绍了处理的Windows USB事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了能够监测USB事件并发送/接收数据包,并从器件的通用USB HID通讯科的驱动程序。我一直在使用它成功,因为我的的WinForms 尽可能多的code日从MSDN扑杀并实施了非常相似的方式提出<一个href="http://stackoverflow.com/questions/16245706/check-for-device-change-add-remove-events">here.我的问题是:我看到的例子继续依靠什么似乎是旧的Windows消息的架构,即了System.Runtime.InteropServices ,WM_xxxxxxx类型的消息,注册/在纯 C#WPF 应用与 HwndHandler 处理这些,覆盖的WndProc ,等我想知道有没有办法用一个更现代,事件驱动的方式来处理USB事件,说与代表,订阅事件处理等?即使,以便帖子建议不采取使用这种古老的方法和我想象必须有USB事件的溶液为好。感谢名单。

I created a generic USB HID comms driver capable of monitoring USB events and sending/receiving data packets to and from devices. I've been using it successfully since my WinForms days as much of the code was culled from MSDN and implemented very similarly to the way suggested here. My question is: The examples I see continue to rely on what seem to be the old "Windows Messaging" architecture, i.e. System.Runtime.InteropServices, WM_xxxxxxx type messages, registering/handling these in a purely C# WPF app with HwndHandler, overriding WndProc, etc. I was wondering is there not a way to handle USB events using a more modern, event-driven approach, say with delegates, subscribing to EventHandlers, etc? Even this SO posts suggest refraining from using such archaic methods and I imagine there must be a solution for USB events as well. Thanx.

推荐答案

做了一些研究之后,似乎Windows消息是处理USB设备更改通知的必要组成部分。我有包括一个简单的实施工作USB通讯科的驱动程序类。这个解决方案由两部分组成,1)的事件通知器类,其产生的事件和2)接收器,其中所预订的事件(即一个是被通知的客户端的USB事件)。样品code是C ++ / CLI,虽然我不同意把可执行code头文件中,为简便起见的做法,我这样做是在这里。

After doing a bit of research, it seems that Windows messaging is a necessary part of handling USB Device Change notifications. I have a working usb comms driver class which includes a simple implementation. This solution consists of two parts, 1) the EventNotifier class, which generates the events and 2) the 'receiver', which subscribes to the events (i.e. a client that gets notified of USB events). The sample code is C++/CLI and although I don't subscribe to the practice of putting executable code in header files, for the sake of brevity, I do so here.

#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 e.g. 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 e.g.
    // 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 (e.g. 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 ,所有你需要做的是:

Then, in the 'receiver' (the object that subscribes to and consumes our NotificationEvent, all you have to do is:

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.
}

这篇关于处理的Windows USB事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆