
























Win From Version:
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Management;
using System.Runtime.InteropServices;namespace SyncContactDemo
{
class DriverWindow : NativeWindow, IDisposable
{
// Contains information about a logical volume.
[StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_VOLUME
{
public int dbcv_size; // size of the struct
public int dbcv_devicetype; // DBT_DEVTYP_VOLUME
public int dbcv_reserved; // reserved; do not use
public int dbcv_unitmask; // Bit 0=A, bit 1=B, and so on (bitmask)
public short dbcv_flags; // DBTF_MEDIA=0x01, DBTF_NET=0x02 (bitmask)
}private const int WM_DEVICECHANGE = 0x0219; // device state change
private const int DBT_DEVICEARRIVAL = 0x8000; // detected a new device
private const int DBT_DEVICEQUERYREMOVE = 0x8001; // preparing to remove
private const int DBT_DEVICEREMOVECOMPLETE = 0x8004; // removed
private const int DBT_DEVTYP_VOLUME = 0x00000002; // logical volume
public DriverWindow()
{
// create a generic window with no class name
base.CreateHandle(new CreateParams());
}public void Dispose()
{
base.DestroyHandle();
GC.SuppressFinalize(this);
}protected override void WndProc(ref Message message)
{
base.WndProc(ref message);if ((message.Msg == WM_DEVICECHANGE) && (message.LParam != IntPtr.Zero))
{
switch (message.WParam.ToInt32())
{
case DBT_DEVICEARRIVAL:
SignalDeviceChange(UsbStateChange.Added);
break;case DBT_DEVICEQUERYREMOVE:
// can intercept
break;case DBT_DEVICEREMOVECOMPLETE:
SignalDeviceChange(UsbStateChange.Removed);
break;
}
}
}
public event UsbStateChangedEventHandler StateChanged;private void SignalDeviceChange(UsbStateChange state)
{if (StateChanged != null)
{
StateChanged(new UsbStateChangedEventArgs(state));
}
}
}
public delegate void UsbStateChangedEventHandler(UsbStateChangedEventArgs e);Override the WndProc(ref Message message) method is core code, which need winform support, so it can not be used in console application and WPF application.
in the win from code, we can use it like
DriverWindow dw = new DriverWindow();
dw.StateChanged += new UsbStateChangedEventHandler(dw_StateChanged);
The WPF version:
代码
using System.Runtime.InteropServices;
using System;
namespace Lenovo.Common.Devices
{
public class Win32
{public const int DEVICE_NOTIFY_SERVICE_HANDLE = 1;
public const int DEVICE_NOTIFY_WINDOW_HANDLE = 0;
public const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 4;
[Flags]
public enum DEVICE_NOTIFY : uint[DllImport(
"user32.dll", SetLastError = true)][DllImport(
"user32.dll", CharSet = CharSet.Auto)][StructLayout(LayoutKind.Sequential, CharSet
= CharSet.Unicode)][StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_HDR[StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_HANDLE
代码
using System.Runtime.InteropServices;
using System;namespace Lenovo.Common.Devices
{
public delegate void UsbStateChangedEventHandler(bool arrival);
public class UsbDetector
{
public enum WM_DEVICECHANGE_WPPARAMS
{
DBT_DEVICEARRIVAL = 0x8000,
DBT_DEVICEQUERYREMOVE = 0x8001,
DBT_DEVICEREMOVECOMPLETE = 0x8004,
DBT_CONFIGCHANGECANCELED = 0x19,
DBT_CONFIGCHANGED = 0x18,
DBT_CUSTOMEVENT = 0x8006,
DBT_DEVICEQUERYREMOVEFAILED = 0x8002,
DBT_DEVICEREMOVEPENDING = 0x8003,
DBT_DEVICETYPESPECIFIC = 0x8005,
DBT_DEVNODES_CHANGED = 0x7,
DBT_QUERYCHANGECONFIG = 0x17,
DBT_USERDEFINED = 0xFFFF
}
const int WM_DEVICECHANGE = 0x0219;public IntPtr HwndHandler(IntPtr hwnd, int msg, IntPtr wParam, IntPtr LParam, ref bool handled)
{
ProcessWinMessage(msg, wParam, LParam);
// handled = false;
return IntPtr.Zero;
}public event UsbStateChangedEventHandler StateChanged;public void ProcessWinMessage(int msg, IntPtr wParam, IntPtr LParam)
{
// if ((msg == WM_DEVICECHANGE) && (LParam != IntPtr.Zero))
if (msg == WM_DEVICECHANGE)
{
switch (wParam.ToInt32())
{
case Win32.DBT_DEVICEARRIVAL:
if (StateChanged != null)
{
StateChanged(true);
}
break;
case Win32.DBT_DEVICEREMOVECOMPLETE:
if (StateChanged != null)
{
StateChanged(false);
}
break;
case Win32.DBT_DEVNODES_CHANGED:
if (StateChanged != null)
{
StateChanged(false);
}
break;
default:
break;
}
}
}
In the WPF application, we should register the DeviceNotification after the window is ready, so we should put them in the load event,
in the constructor:
代码
UsbDetector usbDetector;
public MainWindow()
{
InitializeComponent();
usbDetector = new UsbDetector();
usbDetector.StateChanged += new Lenovo.Common.Devices.UsbStateChangedEventHandler(usbDetector_StateChanged);this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
WindowInteropHelper interop = new WindowInteropHelper(this);
HwndSource hwndSource = HwndSource.FromHwnd(interop.Handle);
HwndSourceHook hool = new HwndSourceHook(usbDetector.HwndHandler);
hwndSource.AddHook(hool); ;
usbDetector.RegisterDeviceNotification(interop.Handle);
}void usbDetector_StateChanged(bool arrival)
{
if (arrival)
MessageBox.Show("add");
else
MessageBox.Show("removed");
}
In generally, the wParam should be DBT_DEVICEARRIVAL or DBT_DEVICEREMOVECOMPLETE, but some time , it keep be the wParam =7 (DBT_DEVNODES_CHANGED) and LParam = 0, that is that the usb driver isn't correctly installed.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。