WPF实现Winform的窗口消息WndProc的例子

昨天在项目开发中,遇到了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;
}

时间: 2024-10-07 06:55:30

WPF实现Winform的窗口消息WndProc的例子的相关文章

WPF弹出自定义窗口的方法_C#教程

本文实例讲述了WPF弹出自定义窗口的方法.分享给大家供大家参考,具体如下: 测试环境: [1]VS2010SP1 [2]WPF(.NET Framework 4)项目 内容简介 WPF工程如何弹出自定义窗口 第一步:自定义个窗口 为当前项目新添个Window项,XAML部份的代码略,下面是C#部份的代码. namespace WorkflowBuilder.MyWindows { /// <summary> /// Interaction logic for InputStringWindow

[WPF疑难]如何禁用窗口上的关闭按钮

哈哈,主要是调用RemoveMenu这个API,所以没什么好说的,直接"干货"吧: namespace VersatileMessageBoxLib { using System; using System.Windows.Interop; using System.Runtime.InteropServices; public class CloseButton { [DllImport("user32", CharSet = CharSet.Ansi, SetL

winform旋转窗口。怎么实现

问题描述 winform旋转窗口.怎么实现 怎么实现像QQ登录界面那样类似的窗口旋转,类似的就可以.不用太相似 解决方案 http://blog.csdn.net/binbin_it/article/details/21395507 解决方案二: 最简单就是用一个ImageList,放上每一步骤的画然后用定时器轮流播出.

关于HGE渲染窗口作为子窗口时无法得到窗口消息的问题以及解决办法

只要稍微了解HGE的人都是知道的,如果在HGE中设置了父窗口,则HGE的渲染窗口作为传入的父窗口的子窗口存在的.如果要嵌入到MFC的窗口中,就需要这样做. 不过,奇怪的是,消息处理回调函数无法收到窗口消息,在System_Initiate()中注册窗口类的时候,是有设置父窗口的句柄的.但是,现在是没有接受到窗口消息,那很显然的事情就是,父窗口设置是失败的. 后来,我查了下资料,WS_POPUP风格的窗口默认父窗口是为空的,除非用::SetParent去特意设置.后面我尝试着在CreateWind

基于WPF或WinForm的应用程序框架

问题描述 最近想做个基于desktop模式的应用程序,因为有很多曲线.图标等复杂的分析功能,传统的b-s模式不太方便.以前一直是在用java的,现在想用java做后台(负责所有复杂计算以及数据库连击和处理),前端用c#,想用WPF或者WinForm来做.想请教一下这里的大侠,什么样的应用程序框架比较适用?我看了DevExpress的xaf,看上去不错,不知道有没有比这个更好用的.谢谢! 解决方案 解决方案二:该回复于2012-02-22 09:52:36被版主删除解决方案三:该回复于2012-0

C# WPF 让你的窗口始终钉在桌面上

原文:C# WPF 让你的窗口始终钉在桌面上 IntPtr hWnd = new WindowInteropHelper(Application.Current.MainWindow).Handle; IntPtr hWndProgMan = FindWindow("Progman", "Program Manager"); SetParent(hWnd, hWndProgMan);   [DllImport("user32.dll", SetL

打开另一个窗口-winform一个窗口隐藏,另一个窗口打开

问题描述 winform一个窗口隐藏,另一个窗口打开 登陆之后,如何隐藏该窗口,打开另一个窗口 解决方案 Form1 f1 = new Form1(); this.Hide(); if (f1.ShowDialog() == DialogResult.OK) { this.Show(); } 解决方案二: 谢谢,我刚才查资料是这样做的 if(num>0) { conn.Close(); UseCar.Load.LoadAdmin LA=new UseCar.Load.LoadAdmin(); L

Windows窗口消息实例详解_C 语言

本文实例总结了Windows窗口消息.分享给大家供大家参考.具体如下: 复制代码 代码如下: //////////////////////////////////////////////////////////////////////////    #include "AFXPRIV.H"//消息值的定义来源    #include "Dde.h"//DDE消息值的定义来源    #include "CPL.H"//控制面板消息值的定义来源   

cocos2d-x 建立自己的层级窗口消息机制

在开发一些窗口层次比复杂的cocos2d项目时,会发现一些由于没有窗口层次而引起的bug.这些bug让一些从windows平台过来的人觉得很无奈.比如,我们有一个列表控件,我们在其中放了一些菜单,当我们滑动列表控件使菜单选项(称为A)滑出列表控件的可视范围时,按理我们是无法再点击到A的,因为它滚动出了父控件可视范围,不被用户所看到.但是cocos2d的默认情况是能点击到的,这是因为cocos2d的消息管理是优先级消息机制,只要控件登记接收消息,那么cocos2d会一如既往的发给他.所以我们刚才讲