Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何连接到WPF窗口句柄以侦听USB事件_C#_.net_Wpf_Usb - Fatal编程技术网

C# 如何连接到WPF窗口句柄以侦听USB事件

C# 如何连接到WPF窗口句柄以侦听USB事件,c#,.net,wpf,usb,C#,.net,Wpf,Usb,我在工作中需要为WPF应用程序连接Windows事件。我需要听USB事件。我发现了零散和不完整的答案,所以我想在一个整合的位置记录我的方法 我最初的问题是在尝试复制此处的代码示例时出现的: 我能够连接到Windows事件并接收设备通知,但是它们非常通用,没有给我太多可以用于我的应用程序的信息 进一步阅读该页面后,我在同一页面上找到了一个不同的答案,该答案直接连接到窗口句柄以监视事件: 这个答案提供了一个链接: 通过遵循codeproject教程并稍加修改以挂接到WPF的窗口句柄,我能够获得

我在工作中需要为WPF应用程序连接Windows事件。我需要听USB事件。我发现了零散和不完整的答案,所以我想在一个整合的位置记录我的方法

我最初的问题是在尝试复制此处的代码示例时出现的:

我能够连接到Windows事件并接收设备通知,但是它们非常通用,没有给我太多可以用于我的应用程序的信息

进一步阅读该页面后,我在同一页面上找到了一个不同的答案,该答案直接连接到窗口句柄以监视事件:

这个答案提供了一个链接:

通过遵循codeproject教程并稍加修改以挂接到WPF的窗口句柄,我能够获得WM_DEVICECHANGE消息,但在解码wParam时,我只接收到DBT_DEVNODES_更改,因为我没有注册以侦听USB事件。快速的谷歌搜索让我找到了一个旧的MSDN论坛帖子:

在这个帖子里,我找到了我想要的答案。我注册窗口不是为了专门查找USB事件,所以我从Windows获得了一般事件代码。进一步的研究让我回到StackOverflow:


这最后一个答案为我解答了难题。我已经提供了一些代码片段,通过挂接到WPF窗口,然后创建一个侦听器来注册该窗口以侦听USB事件,从而概述了侦听Windows事件所需的内容。

要访问USB事件,我们需要一些东西

namespace Example
{
    public class UsbEventRegistration : IDisposable
    {
        private const int DBT_DEVTYP_DEVICEINTERFACE = 5;

        private static readonly s_guidDevInterfaceUsbDevice =
            new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED");

        private readonly IntPtr _windowHandle;
        private IntPtr _notificationHandle = IntPtr.Zero;

        public bool IsRegistered => _notificationHandle != IntPtr.Zero;

        public UsbEventRegistration(IntPtr windowHandle)
        {
            _windowHandle = windowHandle;
        }

        public void Register()
        {
            var dbdi = new DEV_BROADCAST_DEVICE_INTERFACE
            {
                DeviceType = DBT_DEVTYP_DEVICEINTERFACE,
                Reserved = 0,
                ClassGuid = s_guidDevInterfaceUsbDevice,
                Name = 0,
            };
            dbdi.Size = Marshal.SizeOf(dbdi);

            IntPtr buffer = Marshal.AllocHGlobal(dbdi.Size);
            Marshal.StructureToPtr(dbdi, buffer, true);
            _notificationHandle = Win32Native.RegisterDeviceNotification(
                _windowHandle, 
                buffer, 
                0);
        }

        // Call on window unload.
        public void Dispose()
        {
            Win32Native.UnregisterDeviceNotification(_notificationHandle);
        }
    }
}
首先,我们需要链接到user32.dll中的一些方法

namespace Example
{
    // https://www.pinvoke.net/default.aspx/Structures.DEV_BROADCAST_DEVICEINTERFACE
    [StructLayout(LayoutKind.Sequential)]
    public struct DEV_BROADCAST_DEVICE_INTERFACE
    {
        public int Size;
        public int DeviceType;
        public int Reserved;
        public Guid ClassGuid;
        public short Name;
    }

    public class Win32Native
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr RegisterDeviceNotification(
            IntPtr hRecipient,
            IntPtr notificationFilter,
            uint flags);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern uint UnregisterDeviceNotification(IntPtr hHandle);
    }
}
我们需要它来注册我们的WPF窗口来监听USB事件

namespace Example
{
    public class UsbEventRegistration : IDisposable
    {
        private const int DBT_DEVTYP_DEVICEINTERFACE = 5;

        private static readonly s_guidDevInterfaceUsbDevice =
            new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED");

        private readonly IntPtr _windowHandle;
        private IntPtr _notificationHandle = IntPtr.Zero;

        public bool IsRegistered => _notificationHandle != IntPtr.Zero;

        public UsbEventRegistration(IntPtr windowHandle)
        {
            _windowHandle = windowHandle;
        }

        public void Register()
        {
            var dbdi = new DEV_BROADCAST_DEVICE_INTERFACE
            {
                DeviceType = DBT_DEVTYP_DEVICEINTERFACE,
                Reserved = 0,
                ClassGuid = s_guidDevInterfaceUsbDevice,
                Name = 0,
            };
            dbdi.Size = Marshal.SizeOf(dbdi);

            IntPtr buffer = Marshal.AllocHGlobal(dbdi.Size);
            Marshal.StructureToPtr(dbdi, buffer, true);
            _notificationHandle = Win32Native.RegisterDeviceNotification(
                _windowHandle, 
                buffer, 
                0);
        }

        // Call on window unload.
        public void Dispose()
        {
            Win32Native.UnregisterDeviceNotification(_notificationHandle);
        }
    }
}
最后,准备好WPF窗口代码

namespace Example
{
    public partial class WPFWindow : Window
    {

        private UsbEventRegistration _usbEventRegistration;

        public WPFWindow()
        {
            InitializeComponent();
        }

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);

            // IMO this should be abstracted away from the code-behind.
            var windowSource = (HwndSource)PresentationSource.FromVisual(this);
            _usbEventRegistration = new UsbEventRegistration(windowSource.Handle);
           // This will allow your window to receive USB events.
           _usbEventRegistration.Register();
           // This hook is what we were aiming for. All Windows events are listened to here. We can inject our own listeners.
           windowSource.AddHook(WndProc);
        }

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // Here's where the help ends. Do what you need here.
            // Get additional info from http://www.pinvoke.net/
            // USB event message is msg == 0x0219 (WM_DEVICECHANGE).
            // USB event plugin is wParam == 0x8000 (DBT_DEVICEARRIVAL).
            // USB event unplug is wParam == 0x8004 (DBT_DEVICEREMOVECOMPLETE).
            // Your device info is in lParam. Filter that.
            // You need to convert wParam/lParam to Int32 using Marshal.
            return IntPtr.Zero;
        }
    }
}

虽然自我回答的问题是你仍然需要一个好的问题,这是有用的。目前,这个问题过于宽泛,一次解决几个问题,无法被视为规范。别忘了,其他人应该能够用更好的答案回答你的问题,现在的问题是,太多的答案是可以接受的。另外,如果你能提供答案的来源,你可以把你的,你知道的,包括其他人的作品在内的东西结合起来。