WPF 窗口接收 Windows 消息

▪ Windows 消息

在做一些 COM 串口、USB 相关的软件时,我们需要程序实时监测这些端口的状态:比如是否新插入、是否拔出等等,从而让软件做出相应的动作。

实际编写过程中,

▪ WPF 处理 Windows 消息的几种方式

1. Windows API 钩子

WPF 的窗体并没有 Winform 中的 Handle,所以在使用 API 时并不能直接使用设置或者移除钩子。要想使用 API 的 SetWindowsHookEx, UnhookWindowsHookEx, CallNextHookEx 可以首先使用 WindowInteropHelper 得到 Handle。

2. WPF HwndSource

WPF提供的 HwndSource 可以使你更快的实现处理 Windows 消息。通 HwndSource.FromVisual 得到的 HwndSource 可以添加(AddHook)移除(Remove)Hook。HwndSource 有一定的局限性,如果你的 WPF 应用中包含 Winform 控件那你可能要有些失望了,这种方式不能接收到这类消息。

3.ComponentDispatcher

在互操作方案中,启用 Win32 与 WPF 之间的消息泵的共享控件,使用ComponentDispatcher的ThreadFilterMessage等事件可以更好的处理Windows消息。使用这种方式可以避免HwndSource的缺陷。

总结:WPF 也有多种方式处理 Windows 消息,但各种方式各有特点:Windows API 钩子方式功能最强能实现系统级的消息处理,ComponentDispatcher 次之,HwndSource 相对较弱。

WPF 处理 Windows 消息:WPF HwndSource

完整的消息处理代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        
        // ↓ 关键代码
        this.SourceInitialized += new EventHandler(MainWindow_SourceInitialized);
    }

    // ↓ 关键代码
    void MainWindow_SourceInitialized(object sender, EventArgs e)
    {
        IntPtr hwnd = new WindowInteropHelper(this).Handle;
        HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc));
    }

    // ↓ 关键代码
    IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        switch(msg)
        {
            case 1:
                break;
            case 2:
                break;
                
            default :
                break;
        }
        return IntPtr.Zero;
    }

}

代码片段:USB插拔监控

IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    // 初始化常量
    // 设备改变、USB插入、USB拔出
    Int32 WM_DEVICE_CHANGE = 0x219;
    Int32 DBT_DEVICE_ARRIVAL = 0x8000;
    Int32 DBT_DEVICE_REMOVE_COMPLETE = 0x8004;

    // 设备改变
    if( msg == WM_DEVICE_CHANGE ){
        // USB插入
        if( wParam.ToInt32() == DBT_DEVICE_ARRIVAL ){
            // do something ...
        }

        // USB拔出
        if (wParam.ToInt32() == DBT_DEVICE_REMOVE_COMPLETE){
            // do something ...
        }
    }

    return IntPtr.Zero;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值