Un article dans le projet de code a déclaré qu'il est impossible de gérer WM_DEVICECHANGE
messages avec IMessageFilter
Interface, il suggère d'utiliser la méthode WndProc
qui est disponible dans System.Windows.Forms
contrôles.
La classe suivante est une classe privée dans ma classe, elle effectue le travail dont j'ai besoin à partir des messages, puis elle monte un événement pour me parler du résultat. Je dois en faire un objet dans ma classe et gérer son événement.
Ce code détecte l'insertion ou le retrait de périphériques USB de classe HID.
private class MyControl : Form, IMessageFilter
{
Guid InterfaceClassGuid = new Guid(0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30);
//Constant definitions for certain WM_DEVICECHANGE messages
private const uint WM_DEVICECHANGE = 0x0219;
private const uint DBT_DEVICEARRIVAL = 0x8000;
private const uint DBT_DEVICEREMOVEPENDING = 0x8003;
private const uint DBT_DEVICEREMOVECOMPLETE = 0x8004;
private const uint DBT_CONFIGCHANGED = 0x0018;
//Other constant definitions
private const uint DBT_DEVTYP_DEVICEINTERFACE = 0x05;
private const uint DEVICE_NOTIFY_WINDOW_HANDLE = 0x00;
private struct DEV_BROADCAST_DEVICEINTERFACE
{
internal uint dbcc_size; //DWORD
internal uint dbcc_devicetype; //DWORD
internal uint dbcc_reserved; //DWORD
internal Guid dbcc_classguid; //GUID
internal char[] dbcc_name; //TCHAR array
}
//Need this function for receiving all of the WM_DEVICECHANGE messages. See MSDN documentation for
//description of what this function does/how to use it. Note: name is remapped "RegisterDeviceNotificationUM" to
//avoid possible build error conflicts.
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr RegisterDeviceNotification(
IntPtr hRecipient,
IntPtr NotificationFilter,
uint Flags);
public MyControl()
{
//Register for WM_DEVICECHANGE notifications. This code uses these messages to detect plug and play connection/disconnection events for USB devices
DEV_BROADCAST_DEVICEINTERFACE DeviceBroadcastHeader = new DEV_BROADCAST_DEVICEINTERFACE();
DeviceBroadcastHeader.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
DeviceBroadcastHeader.dbcc_size = (uint)Marshal.SizeOf(DeviceBroadcastHeader);
DeviceBroadcastHeader.dbcc_reserved = 0; //Reserved says not to use...
DeviceBroadcastHeader.dbcc_classguid = InterfaceClassGuid;
//Need to get the address of the DeviceBroadcastHeader to call RegisterDeviceNotification(), but
//can't use "&DeviceBroadcastHeader". Instead, using a roundabout means to get the address by
//making a duplicate copy using Marshal.StructureToPtr().
IntPtr pDeviceBroadcastHeader = IntPtr.Zero; //Make a pointer.
pDeviceBroadcastHeader = Marshal.AllocHGlobal(Marshal.SizeOf(DeviceBroadcastHeader)); //allocate memory for a new DEV_BROADCAST_DEVICEINTERFACE structure, and return the address
Marshal.StructureToPtr(DeviceBroadcastHeader, pDeviceBroadcastHeader, false); //Copies the DeviceBroadcastHeader structure into the memory already allocated at DeviceBroadcastHeaderWithPointer
RegisterDeviceNotification(this.Handle, pDeviceBroadcastHeader, DEVICE_NOTIFY_WINDOW_HANDLE);
}
public event EventHandler DeviceConnected;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_DEVICECHANGE)
{
if (((int)m.WParam == DBT_DEVICEARRIVAL) || ((int)m.WParam == DBT_DEVICEREMOVEPENDING) || ((int)m.WParam == DBT_DEVICEREMOVECOMPLETE) || ((int)m.WParam == DBT_CONFIGCHANGED))
{
//Rise the event, more processing is needed to check for a certain device.
DeviceConnected(this, null);
}
}
base.WndProc(ref m);
}
}
j'ai changé le code à utiliser WndProc de formulaire pour obtenir WM_DEVICECHANGE, et il fonctionne très bien, mais pas lors de l'utilisation IMessageFilter dans le composant. Je suppose que le pilote de périphérique a diffusé WM_DEVICECHANGE sous Windows 7 64bit. – Allex