永远的SKYFEI
喜欢在阳光下,光着脊梁,挥汗如雨地工作,每次回头擦汗,看到的都是成就!

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);
    
public enum UsbStateChange
    {

        
/// <summary>
        
/// A device has been added and is now available.
        
/// </summary>

        Added,


        
/// <summary>
        
/// A device is about to be removed;
        
/// allows consumers to intercept and deny the action.
        
/// </summary>

        Removing,


        
/// <summary>
        
/// A device has been removed and is no longer available.
        
/// </summary>

        Removed
    }

    
public class UsbStateChangedEventArgs : EventArgs
    {

        
/// <summary>
        
/// Initialize a new instance with the specified state and disk.
        
/// </summary>
        
/// <param name="state">The state change code.</param>
        
/// <param name="disk">The USB disk description.</param>

        
public UsbStateChangedEventArgs(UsbStateChange state)
        {
            
this.State = state;
        }

        
/// <summary>
        
/// Gets the state change code.
        
/// </summary>

        
public UsbStateChange State
        {
            
get;
            
private set;
        }
    }
}

 

 

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
        {
            DEVICE_NOTIFY_WINDOW_HANDLE 
= 0x00000000,
            DEVICE_NOTIFY_SERVICE_HANDLE 
= 0x00000001,
            DEVICE_NOTIFY_ALL_INTERFACE_CLASSES 
= 0x00000004
        }


        
public const int SERVICE_CONTROL_STOP = 0x00000001;
        
public const int SERVICE_CONTROL_DEVICEEVENT = 0x00000011;
        
public const int SERVICE_CONTROL_SHUTDOWN = 0x00000005;
   
        
/*DBT_DEVTYP_DEVICEINTERFACE 0x00000005
            Class of devices. This structure is a DEV_BROADCAST_DEVICEINTERFACE structure.
 
            DBT_DEVTYP_HANDLE   0x00000006
            File system handle. This structure is a DEV_BROADCAST_HANDLE structure.
 
            DBT_DEVTYP_OEM  0x00000000
            OEM- or IHV-defined device type. This structure is a DEV_BROADCAST_OEM structure.
 
            DBT_DEVTYP_PORT 0x00000003
            Port device (serial or parallel). This structure is a DEV_BROADCAST_PORT structure.
 
            DBT_DEVTYP_VOLUME 0x00000002
            Logical volume. This structure is a DEV_BROADCAST_VOLUME structure.
 
*/

        
public const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005;
        
public const int DBT_DEVTYP_HANDLE = 0x00000006;
        
public const int DBT_DEVTYP_OEM = 0x00000000;
        
public const int DBT_DEVTYP_PORT = 0x00000003;
        
public const int DBT_DEVTYP_VOLUME = 0x00000002;


        
public const int WM_DEVICECHANGE = 0x0219;                // device state change
        public const int DBT_DEVICEARRIVAL = 0x8000;            // detected a new device
        public const int DBT_DEVICEQUERYREMOVE = 0x8001;        // preparing to remove
        public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;    // removed 
        public const int DBT_DEVNODES_CHANGED = 0x0007//A device has been added to or removed from the system.


        [DllImport(
"user32.dll", SetLastError = true)]
        
public static extern IntPtr RegisterDeviceNotification(IntPtr intPtr, IntPtr notificationFilter, uint flags);

        [DllImport(
"user32.dll", CharSet = CharSet.Auto)]
        
public static extern uint UnregisterDeviceNotification(IntPtr hHandle);

        [StructLayout(LayoutKind.Sequential, CharSet 
= CharSet.Unicode)]
        
public struct DEV_BROADCAST_DEVICEINTERFACE
        {
            
public int dbcc_size;
            
public int dbcc_devicetype;
            
public int dbcc_reserved;
            
//public IntPtr dbcc_handle;
            
//public IntPtr dbcc_hdevnotify;
            [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 16)]
            
public byte[] dbcc_classguid;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst 
= 128)]
            
public Char[] dbcc_name;
            
//public byte dbcc_data;
            
//public byte dbcc_data1; 
        
        }

        [StructLayout(LayoutKind.Sequential)]
        
public struct DEV_BROADCAST_HDR
        {
            
public int dbcc_size;
            
public int dbcc_devicetype;
            
public int dbcc_reserved;
        }

        [StructLayout(LayoutKind.Sequential)]
        
public struct DEV_BROADCAST_HANDLE
        {
            
public int dbch_size;
            
public int dbch_devicetype;
            
public int dbch_reserved;
            
public IntPtr dbch_handle;
            
public IntPtr dbch_hdevnotify;
            
public Guid dbch_eventguid;
            
public long dbch_nameoffset;
            
public Byte dbch_data;
            
public Byte dbch_data1;
        }
    }
}

 

 

 

代码
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;
                }

            }
        }

       
// private const string USBClassID = "c671678c-82c1-43f3-d700-0049433e9a4b";
        
//http://msdn.microsoft.com/en-us/library/ff545972.aspx
        private const string USBClassID = "A5DCBF10-6530-11D2-901F-00C04FB951ED";
        
public IntPtr RegisterDeviceNotification(IntPtr hwnd)
        {
            Win32.DEV_BROADCAST_DEVICEINTERFACE deviceInterface 
= new Win32.DEV_BROADCAST_DEVICEINTERFACE();
            
int size = Marshal.SizeOf(deviceInterface);
            deviceInterface.dbcc_size 
= size;
        
//    deviceInterface.dbcc_devicetype = Win32.DBT_DEVTYP_VOLUME;
            deviceInterface.dbcc_reserved = 0;
            
//deviceInterface.dbcc_handle = hwnd;
            
//deviceInterface.dbcc_hdevnotify = (IntPtr)0;
            deviceInterface.dbcc_classguid = new Guid(USBClassID).ToByteArray();
            IntPtr buffer 
= IntPtr.Zero;
            buffer 
= Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(deviceInterface, buffer, 
true);
            IntPtr r 
= IntPtr.Zero;
            r 
= Win32.RegisterDeviceNotification(hwnd, buffer, 
                (Int32)(Win32.DEVICE_NOTIFY.DEVICE_NOTIFY_ALL_INTERFACE_CLASSES  
                        
| Win32.DEVICE_NOTIFY.DEVICE_NOTIFY_SERVICE_HANDLE | 
                        Win32.DEVICE_NOTIFY.DEVICE_NOTIFY_WINDOW_HANDLE)
                );
            
            
return r;
        }
    }
}

 


 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.

 

posted on 2010-12-23 14:41  skyfei  阅读(3703)  评论(1编辑  收藏  举报