使用IMessageFilter不能在Windows 7 64位(C#,.net 2.0)下工作
问题描述:
我们正在研究USB设备程序。以下代码片段是我的UsbComponent类。 它可以在Windows XP或Windows 64 32位下正常工作。 但是在Windows 7 64bit下,无论何时插入/移除我们的USB设备,PreFilterMessage都不会进入。我错过了什么使下面的代码在Windows 7 64位下工作?使用IMessageFilter不能在Windows 7 64位(C#,.net 2.0)下工作
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
public partial class UsbComponent : Component, IMessageFilter {
private const int WM_DEVICECHANGE = 0x219;
public UsbComponent() {
InitializeComponent();
Application.AddMessageFilter(this);
}
public UsbComponent(IContainer container) {
container.Add(this);
InitializeComponent();
Application.AddMessageFilter(this);
}
bool IMessageFilter.PreFilterMessage(ref Message m) {
if(m.Msg == WM_DEVICECHANGE) {
MessageBox.Show("device changed");
return true;
}
return false;
}
}
答
设备驱动程序负责广播WM_DEVICECHANGE。请确保您有该设备的更新驱动程序,并验证该设备支持Windows 7
答
代码项目的文章指出,这是不可能的处理WM_DEVICECHANGE
消息与IMessageFilter
接口方面,它建议使用WndProc
方法是可用在System.Windows.Forms
控件。
以下班级是我班内的私人班级,它执行我从邮件中需要的工作,然后发起一个活动来告诉我有关结果。我必须在我的课堂内创建一个对象并处理它的事件。
此代码检测插入或移除HID类USB设备。
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);
}
}
我改变了代码,使用形式的WndProc得到WM_DEVICECHANGE,它只是正常工作,但在使用组件时IMessageFilter没有。我猜设备驱动程序确实在Windows 7 64bit下广播WM_DEVICECHANGE。 – Allex 2010-08-03 03:11:23