【问题标题】:Using IMessageFilter not working under windows 7 64bit (C#, .net 2.0)使用 IMessageFilter 在 windows 7 64 位 (C#, .net 2.0) 下不起作用
【发布时间】:2011-03-24 12:19:42
【问题描述】:

我们正在开发 USB 设备程序。以下代码 sn-p 是我的 UsbComponent 类。 它在 windows XP 甚至 windows 64 32bit 下都能正常工作。 但是在 windows 7 64bit 下,每当我插入/删除我们的 USB 设备时,PreFilterMessage 永远不会被输入。我是否错过了使以下代码在 Windows 7 64 位下工作的任何内容?

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

【问题讨论】:

    标签: c# components


    【解决方案1】:

    设备驱动程序负责广播 WM_DEVICECHANGE。确保您拥有该设备的更新驱动程序并验证该设备是否支持 Windows 7

    【讨论】:

    • 我更改了代码以使用表单的 WndProc 来获取 WM_DEVICECHANGE,它工作正常,但在组件中使用 IMessageFilter 时却不行。我猜设备驱动程序确实在 windows 7 64bit 下广播了 WM_DEVICECHANGE。
    【解决方案2】:

    代码项目中的一篇文章指出,使用IMessageFilter 接口无法处理WM_DEVICECHANGE 消息,它建议使用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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-03-01
      • 2011-02-07
      • 2016-09-20
      • 2012-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多