现在位置首页 / 项目实战 /正文

WPF实现Winform的窗口消息WndProc

作者: IT小兵 | 2016年10月28日| 热度:℃ | 评论: |参与:

昨天在项目开发中,遇到了USB口拔插的操作,想在程序中,实现对com口拔插的监控,但是常规的WndProc是在winform实现的,所以查询了一下wpf是怎么实现的。

有下面的方法,测试可行:

1、USB消息结构的定义

 // usb消息定义
        public const int WM_DEVICE_CHANGE = 0x219;
        public const int DBT_DEVICEARRIVAL = 0x8000;
        public const int DBT_DEVICE_REMOVE_COMPLETE = 0x8004;
        public const UInt32 DBT_DEVTYP_PORT = 0x00000003;
        [StructLayout(LayoutKind.Sequential)]
        struct DEV_BROADCAST_HDR
        {
            public UInt32 dbch_size;
            public UInt32 dbch_devicetype;
            public UInt32 dbch_reserved;
        }
        [StructLayout(LayoutKind.Sequential)]
        protected struct DEV_BROADCAST_PORT_Fixed
        {
            public uint dbcp_size;
            public uint dbcp_devicetype;
            public uint dbcp_reserved;
            // Variable?length field dbcp_name is declared here in the C header file.
        }

2、定义钩子方法:WndProc

 /// <summary>
        /// 检测USB串口的拔插
        /// </summary>
        /// <param name="m"></param> 
        public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_DEVICE_CHANGE)        // 捕获USB设备的拔出消息WM_DEVICECHANGE
            {
                switch (wParam.ToInt32())
                {
                    case DBT_DEVICE_REMOVE_COMPLETE:    // USB拔出                        
                        break;
                    case DBT_DEVICEARRIVAL:             // USB插入获取对应串口名称
                        DEV_BROADCAST_HDR dbhdr = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(lParam, typeof(DEV_BROADCAST_HDR));
                        if (dbhdr.dbch_devicetype == DBT_DEVTYP_PORT)
                        {
                            string portName = Marshal.PtrToStringUni((IntPtr)(lParam.ToInt32() + Marshal.SizeOf(typeof(DEV_BROADCAST_PORT_Fixed))));
                            Console.WriteLine("Port '" + portName + "' arrived.");
                        }
                        break;
                }
            }
            return hwnd;
        }

3、在loaded中,注册这个方法

         HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
                if (source != null) source.AddHook(WndProc);


扩展阅读:

Marshal.StructureToPtr方法简介               

1. 功能及位置

                                            
将数据从托管对象封送到非托管内存块,属于.NET Framework 类库 
命名空间:System.Runtime.InteropServices 
程序集:mscorlib(在 mscorlib.dll 中)

2. 语法

                                            
C#:
      [ComVisibleAttribute(true)] public static void StructureToPtr (Object structure,IntPtr ptr,bool fDeleteOld); 
C++:
      [ComVisibleAttribute(true)]public: static void StructureToPtr (Object^ structure, IntPtr ptr, bool fDeleteOld);

3. 参数说明                                            

structure:托管对象,包含要封送的数据。该对象必须是格式化类的实例。 
ptr:指向非托管内存块的指针,必须在调用此方法之前分配该指针。 
fDeleteOld:设置为 true 可在执行Marshal.DestroyStructure方法前对 ptr 参数调用此方法。请注意,传递 false 可导致内存泄漏。

4. 异常

                                            
异常类型:ArgumentException 
条件:structrue参数是泛型类型

5. 备注

StructureToPtr将结构的内容复制到 ptr 参数指向的预分配内存块。如果 fDeleteOld 参数为 true,则使用嵌入指
针上适当的删除 API 来删除最初由 ptr 指向的缓冲区,但该缓冲区必须包含有效数据。此方法为在镜像托管类中指
定的每个引用字段执行清理工作。
                                            
假设 ptr 指向非托管内存块。此内存块的布局由相应的托管类 structure 描述。StructureToPtr将字段值从结构封
送到指针。假设 ptr 块包含引用字段,该字段指向当前包含“abc”的字符串缓冲区。假设托管端上相应的字段是包含“vwxyz”的字符串。如果不另行通知它,StructureToPtr将分配一个新的非托管缓冲区来保存“vwxyz”,并将它挂钩到 ptr 块。这将丢弃旧缓冲区“abc”使之漂移而不将其释放回非托管堆。最后,您将得到一个孤立的缓冲区,它表示在代码中存在内存泄漏。如果将 fDeleteOld 参数设置为真,则 StructureToPtr 在继续为“vwxyz”分配新缓冲区之前释放保存“abc”的缓冲区。

参考:

在Visual的句柄创建后(如OnLoad、OnSourceInitialized代码里),使用下面方法:
方法一:

HwndSource source =PresentationSource.FromVisual(this) as HwndSource;
if(source != null) source.AddHook(WndProc);

方法二:

HwndSource source =HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
if(source != null) source.AddHook(WndProc);

注:两种方法中的this可换成Visual对象。

然后就可以HwndSourceHook委托的WndProc方法了:

private IntPtr WndProc(IntPtr hwnd,int msg,IntPtr wParam,IntPtr lParam,ref bool handled)
{
    // Handle messages...
    return IntPtr.Zero;
}


点击阅读本文所属分类的更多文章: 项目实战 。和高手一起交流:346717337
友荐云推荐

未注明转发、原文均为本站原创。分享本文请注明 原文链接

给您更多信息和帮助

在这里您可以找到更多:

技术交流群:346717337 Jquery插件交流

投稿:[email protected]

承接:企业网站门户/微网站/微商城/CMS系统/微信公众号运营/业务咨询

echarts教程系列
本月最热文章

微信扫一扫,徜徉悠嘻网,您的休闲乐园

微信公众号:快乐每一天

随机文章
标签

技术交流群:346717337

投稿:[email protected]

专业专注:企业网站门户/微网站/微商城/CMS系统/微信公众号运营/付费问题咨询