How to receive Plug & Play device notifications without a windows form

前端 未结 3 1877
星月不相逢
星月不相逢 2020-11-27 14:35

I am trying to write a class library that can catch the windows messages to notify me if a device has been attached or removed. Normally, in a windows forms app I would just

3条回答
  •  清酒与你
    2020-11-27 15:09

    I have a working USB communication class that implements device change notification in a slightly different way if anyone is interested. It's pretty compact (w/o the comments) and doesn't rely on Threading or the OnSourceInitialized and HwndHandler stuff in the client. Also, you do not need a Form or Window as mentioned. Any type where you can override WndProc() can be used. I use a Control.

    The sample contains only code needed for notification and nothing else. 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     // Declares required datatypes.
    #include         // Required for WM_DEVICECHANGE messages.
    #include    // 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);
    
        /// 
        /// Declare a delegate for the notification event handler.
        /// 
        /// The object where the event handler is attached.
        /// The event data.
        public delegate void NotificationEventHandler(Object^ sender, EventArgs^ e);
    
        /// 
        /// Class that generetaes USB Device Change notification events.
        /// 
        /// 
        /// A Form is not necessary. Any type wherein you can override WndProc() can be used.
        /// 
        public ref class EventNotifier : public Control
        {
        private:
            /// 
            /// Raises the NotificationEvent.
            /// 
            /// The event data.
            void RaiseNotificationEvent(EventArgs^ e) {
                NotificationEvent(this, e);
            }
    
        protected:
            /// 
            /// Overrides the base class WndProc method.
            /// 
            /// The Windows Message to process. 
            /// 
            /// 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).
            /// 
            virtual void WndProc(Message% message) override {
                if(message.Msg == WM_DEVICECHANGE)
                {
                    RaiseNotificationEvent(EventArgs::Empty);
                }
                __super::WndProc(message);
            }
    
        public:
            /// 
            /// Creates a new instance of the EventNotifier class.
            /// 
            EventNotifier(void) {
                RequestNotifications(this->Handle); // Register ourselves as the Windows Message processor.
            }
    
            /// 
            /// Registers an object, identified by the handle, for
            /// Windows WM_DEVICECHANGE messages.
            /// 
            /// The object's handle.
            bool RequestNotifications(IntPtr handle) {
                DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
    
                ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
                NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
                NotificationFilter.dbcc_reserved = 0;
                NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
                return RegisterDeviceNotificationUM((HANDLE)handle, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE) != NULL;
            }
    
            /// 
            /// Defines the notification event.
            /// 
            virtual event NotificationEventHandler^ 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.
    }
    

提交回复
热议问题