C# 如何接收插头&;不使用windows窗体播放设备通知

C# 如何接收插头&;不使用windows窗体播放设备通知,c#,overriding,console-application,winforms,wndproc,C#,Overriding,Console Application,Winforms,Wndproc,我正在尝试编写一个类库,该类库可以捕获windows消息,以便在设备已连接或删除时通知我。通常,在windows窗体应用程序中,我只会覆盖WndProc方法,但在本例中没有WndProc方法。有没有其他方法可以让我收到这些信息?你需要一个窗口,没有办法。下面是一个示例实现。为DeviceChangeNotifier.DeviceNotify事件实现事件处理程序以获取通知。在程序开始时调用DeviceChangeNotifier.Start()方法。在程序结束时调用DeviceChangeNoti

我正在尝试编写一个类库,该类库可以捕获windows消息,以便在设备已连接或删除时通知我。通常,在windows窗体应用程序中,我只会覆盖WndProc方法,但在本例中没有WndProc方法。有没有其他方法可以让我收到这些信息?

你需要一个窗口,没有办法。下面是一个示例实现。为DeviceChangeNotifier.DeviceNotify事件实现事件处理程序以获取通知。在程序开始时调用DeviceChangeNotifier.Start()方法。在程序结束时调用DeviceChangeNotifier.Stop()。请注意,DeviceNotify事件是在后台线程上引发的,请确保根据需要锁定,以确保代码线程安全

using System;
using System.Windows.Forms;
using System.Threading;

class DeviceChangeNotifier : Form {
  public delegate void DeviceNotifyDelegate(Message msg);
  public static event DeviceNotifyDelegate DeviceNotify;
  private static DeviceChangeNotifier mInstance;

  public static void Start() {
    Thread t = new Thread(runForm);
    t.SetApartmentState(ApartmentState.STA);
    t.IsBackground = true;
    t.Start();
  }
  public static void Stop() {
    if (mInstance == null) throw new InvalidOperationException("Notifier not started");
    DeviceNotify = null;
    mInstance.Invoke(new MethodInvoker(mInstance.endForm));
  }
  private static void runForm() {
    Application.Run(new DeviceChangeNotifier());
  }

  private void endForm() {
    this.Close();
  }
  protected override void SetVisibleCore(bool value) {
    // Prevent window getting visible
    if (mInstance == null) CreateHandle();
    mInstance = this;
    value = false;
    base.SetVisibleCore(value);
  }
  protected override void WndProc(ref Message m) {
    // Trap WM_DEVICECHANGE
    if (m.Msg == 0x219) {
      DeviceNotifyDelegate handler = DeviceNotify;
      if (handler != null) handler(m);
    }
    base.WndProc(ref m);
  }
}

我有一个正在工作的USB通信类,如果有人感兴趣,它以稍微不同的方式实现设备更改通知。它非常紧凑(没有注释),不依赖于客户机中的
线程
OnSourceInitialized
HwndHandler
内容。此外,您不需要前面提到的
表单
或窗口。可以使用任何可以覆盖
WndProc()
的类型。我使用
控件

该示例仅包含通知所需的代码,而不包含其他内容。示例代码是C++/CLI,虽然我不赞成将可执行代码放入头文件的做法,但为了简洁起见,我在这里这样做

#pragma一次
#include//声明所需的数据类型。
#包含//WM_设备更改消息所需。
#包含//定义GUID定义所需的内容(见下文)。
命名空间USBComms
{
使用名称空间系统;
使用名称空间System::Runtime::InteropServices;
使用名称空间系统::Windows;
使用命名空间System::Windows::Forms;
//接收WM_设备更改消息时需要此功能。
//注意:名称重新映射为“RegisterDeviceNotificationUM”
[DllImport(“user32.dll”,CharSet=CharSet::Unicode,EntryPoint=“RegisterDeviceNotification”)]
外部“C”HDEVNOTIFY WINAPI注册表设备(
处理诚信问题,
LPVOID通知过滤器,
德沃德旗);
//usb设备的通用guid(参见。http://msdn.microsoft.com/en-us/library/windows/hardware/ff545972%28v=vs.85%29.aspx).
//注意:guid是特定于设备和操作系统的,可能需要修改。使用错误的guid将导致通知失败。
//您可能需要修改设备以找到合适的GUID。“hid.dll”有一个返回的函数“HidD_GetHidGuid”
//“HIDClass设备的设备接口GUID”(请参阅http://msdn.microsoft.com/en-us/library/windows/hardware/ff538924%28v=vs.85%29.aspx).
//但是,测试显示它并不总是返回有用的值
//{A5DCBF10-6530-11D2-901F-00C04FB951ED},曾使用手机、拇指驱动器等。有关更多信息,请参阅例如。
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx. 
定义GUID(GUID设备接口USB设备,0xA5DCBF10L、0x6530、0x11D2、0x90、0x1F、0x00、0xC0、0x4F、0xB9、0x51、0xED);
/// 
///为通知事件处理程序声明委托。
/// 
///附加事件处理程序的对象。
///事件数据。
公共委托无效NotificationEventHandler(对象^sender,事件参数^e);
/// 
///类,该类生成USB设备更改通知事件。
/// 
/// 
///表单不是必需的。可以使用任何可以重写WndProc()的类型。
/// 
public ref类EventNotifier:公共控件
{
私人:
/// 
///引发NotificationEvent。
/// 
///事件数据。
作废RaiseNotificationEvent(事件参数^e){
通知事件(本,e);
}
受保护的:
/// 
///重写基类WndProc方法。
/// 
///要处理的Windows消息。
/// 
///此方法接收Windows消息(WM_uxxxxxxxxx)和
///适当地引发我们的通知事件。您应该
///添加任何消息过滤(例如,用于WM_设备更改)和
///在引发事件(或不引发)之前进行预处理。
/// 
虚拟无效WndProc(消息%Message)覆盖{
如果(message.Msg==WM_DEVICECHANGE)
{
RaiseNotificationEvent(EventArgs::Empty);
}
__super::WndProc(消息);
}
公众:
/// 
///创建EventNotifier类的新实例。
/// 
事件通知程序(无效){
RequestNotifications(此->句柄);//注册为Windows消息处理器。
}
/// 
///为注册由句柄标识的对象
///Windows WM_设备更改消息。
/// 
///对象的句柄。
bool请求通知(IntPtr句柄){
开发广播设备接口通知过滤器;
零内存(&NotificationFilter,sizeof(NotificationFilter));
NotificationFilter.dbcc_devicetype=DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_size=sizeof(设备接口);
NotificationFilter.dbcc_reserved=0;
NotificationFilter.dbcc_classguid=GUID\u设备接口\u USB\u设备;
返回RegisterDeviceNotificationUM((句柄)句柄和NotificationFilter,设备\u NOTIFY\u WINDOW\u HANDLE)!=NULL;
}
/// 
///定义通知事件。
/// 
虚拟事件NotificationEventHandler^NotificationEvent;
};
}
然后,在“接收者”(订阅并使用我们的
NotificationEvent
的对象)中,您所拥有的
  public class MsgWindow : Microsoft.WindowsCE.Forms.MessageWindow {

    public const int WM_SER = 0x500;
    public const int WM_SER_SCANDONE = WM_SER + 0;

    frmMain msgform { get; set; }

    public MsgWindow(frmMain msgform) {
      this.msgform = msgform;
    }

    protected override void WndProc(ref Microsoft.WindowsCE.Forms.Message m) {
      switch (m.Msg) {
        case WM_SER_SCANDONE:
          this.msgform.RespondToMessage(WM_SER_SCANDONE);
          break;
        default:
          break;
      }
      base.WndProc(ref m);
    }

  }

  public partial class frmMain : Form {

    public frmMain() {
      InitializeComponent();
    }

    public void RespondToMessage(int nMsg) {
      try {
        switch (nMsg) {
          case MsgWindow.WM_SER_SCANDONE:
            // do something here based on the message
            break;
          default:
            break;
        }
      } catch (Exception ex) {
        MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.ToString()), "RespondToMessage() Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
        // throw;
      }
    }

  }