利用SendMessage实现winform与wpf之间的消息传递

引言

   有一次心血来潮,突然想研究一下进程间的通信,能够实现消息传递的方法有几种,其中win32api中的sendmessage就是当中的一种比较简单的方法。于是参考了网上各种资料,做了一个小demo。

发送方Winform

   1.新建一个Winform项目,添加控件,如下

2.界面做好,接着来编写代码,首先利用DllImport来声明SendMessage函数原型,如下:

[DllImport("User32.dll")]
        private static extern int SendMessage(IntPtr hWnd,int Msg, int wParam, IntPtr lParam );

3.其中,lParam参数说明如下

lParam指向一个COPYDATASTRUCT的结构:  
 typedef  struct  tagCOPYDATASTRUCT
 {  
             DWORD  dwData;  //用户定义数据  
             DWORD  cbData;  //数据大小  
            PVOID  lpData;  //指向数据的指针  
 } COPYDATASTRUCT;

4.所以为了方便起见,还需要定义个一个结构,如下

 public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }

5.相应地,sendmessage函数更改为如下:

[DllImport("User32.dll")]
        private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam );

6.至此,sendmessage函数定义完成,但是还不够,我们还需要能找到接收消息的窗体的函数,所以还要声明两个函数:

        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", EntryPoint = "FindWindowEx“)]
        private static extern IntPtr FindWindowEx(IntPtr hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow);

7.接下来,我们可以开始写发送消息具体实现。
   发送到form的textbox按钮的方法实现如下:

            IntPtr WINDOW_HANDLER = FindWindow(null, "Win32窗体");

            if (WINDOW_HANDLER != IntPtr.Zero)
            {

                IntPtr hwndThree = FindWindowEx(WINDOW_HANDLER, 0, null, "");
                hwndThree =new IntPtr(GetWindow(hwndThree.ToInt32(), 2));
                hwndThree = new IntPtr(GetWindow(hwndThree.ToInt32(), 2));   //获取按钮的句柄  找3次才找到目标textbox

                SendMessage(hwndThree, WM_SETTEXT, 0, this.sendtext.Text);
            }

发送到Winform按钮的方法实现如下:

     IntPtr WINDOW_HANDLER = FindWindow(null, "Win32窗体");
            if (WINDOW_HANDLER != IntPtr.Zero)
            {
                string text = this.sendtext.Text;
                byte[] sarr = System.Text.Encoding.Default.GetBytes(text);
                int len = sarr.Length;
                COPYDATASTRUCT cds;
                cds.dwData = (IntPtr)100;
                cds.lpData = text;
                cds.cbData = len + 1;
                SendMessage(WINDOW_HANDLER, WM_COPYDATA, 0, ref cds);
            }

发送到WPF按钮的方法实现如下:

IntPtr WINDOW_HANDLER = FindWindow(null, "WPF窗体");
            if (WINDOW_HANDLER != IntPtr.Zero)
            {
                string text = this.sendtext.Text;
                byte[] sarr = System.Text.Encoding.Default.GetBytes(text);
                int len = sarr.Length;
                COPYDATASTRUCT cds;
                cds.dwData = (IntPtr)100;
                cds.lpData = text;
                cds.cbData = len + 1;
                SendMessage(WINDOW_HANDLER, WM_COPYDATA, 0, ref cds);
            }

8.至此,发送端的编码完成,其中第一个按钮的功能是将消息直接发送到winform接收方的textbox上,第二个按钮是将消息发送到winform接收方的窗体上,再由窗体的方法处理,第三个按钮是将消息发送到wpf接收方的窗体上,再由wpf的方法处理。为什么没有直接发送到wpf的textbox的方法呢,那是因为wpf里面的控件是没有句柄的,只有窗体才有句柄,然后发送消息需要接收方的句柄,所以无法实现。

 接收方winform

  1.新建winform项目,编写界面如下:

2.编写后台代码,定义结构COPYDATASTRUCT和重写winform的消息处理方法WndProc,代码如下:

public const int WM_COPYDATA = 0x004A;

 public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }

 protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case WM_COPYDATA:
                    COPYDATASTRUCT MyKeyboardHookStruct = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
                    this.textBox2.Text = MyKeyboardHookStruct.lpData;
                    break;
                default:
                    base.WndProc(ref m);   // 调用基类函数处理其他消息。
                    break;
            }
        }  

3.至此,winform接收端编码完成,我们只需在WndProc处理一下消息类型为WM_COPYDATA的消息即可。

接收方wpf

   1.新建wpf项目,界面如下

2.编写后台代码,wpf没有消息处理方法WndProc,所以处理上复杂些。主要利用HwndSource实现接收消息,具体代码如下:

 public MainWindow()
        {
            InitializeComponent();

            this.Loaded += Window_Loaded;
        }

        #region 定义常量消息值
        public const int WM_GETTEXT = 0x0D;
        public const int WM_SETTEXT = 0x0C;
        public const int WM_SIZEING = 0x0214;
        public const int WM_COPYDATA = 0x004A;
        public const int WM_LBUTTONDBLCLK = 0x0203;
        #endregion

        #region 定义结构体
       public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }
        #endregion

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            HwndSource hWndSource;
            WindowInteropHelper wih = new WindowInteropHelper(this);
            hWndSource = HwndSource.FromHwnd(wih.Handle);
            //添加处理程序
            hWndSource.AddHook(MainWindowProc);
        }
        private IntPtr MainWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {

                case WM_COPYDATA:
                    {

                        COPYDATASTRUCT mystr = new COPYDATASTRUCT();
                        Type mytype = mystr.GetType();

                        COPYDATASTRUCT MyKeyboardHookStruct = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT));
                         this.textbox.Text = MyKeyboardHookStruct.lpData;
                        break;

                    }
                     default:
                    {
                             break;
                    }

            }
            return IntPtr.Zero;
        }

3.wpf接收端完成。
最终界面效果

小结

     本文介绍了如何用sendmessage函数在窗体间发送消息,sendmessage函数是win32api的一种,然而win32api又是一个好庞大的话题了,我现在还只是入门未遂,渐行渐学罢了.另外,消息的传递方法不只一种,例如我们还可以用wcf进行通信,有时间再研究.最后,如果您有更好的建议,请不吝指教,感激不尽!

时间: 2024-08-29 15:34:16

利用SendMessage实现winform与wpf之间的消息传递的相关文章

WinForm 与WPF 窗体之间的想到调用

先放置一个容器控件,并设计 好WinForm(或WPF)窗口 winform 调用 wpf ElementHost el = new ElementHost(); el.Dock = DockStyle.Fill; this.panelStation.Controls.Add(el); ucStationMess_WPF stat = new ucStationMess_WPF(); el.Child = stat; 其中,panelStation 为winform 的窗口控件 ucStatio

Prism 4 文档 ---第10章 Silverlight和WPF之间共享代码

本主题帮助你理解来自Prism的多目标和它的优缺点.多目标的代码针对两个不同的平台有大致相同的代码库.这允许同时保持代码尽可能多一样能够产生针对两种不同技术的二进制文件.在这种情况下,本节介绍的技术是WPF和Silverlight.本主题包含了一些你在使用这些技术开发多目标应用程序的时候的注意事项. 目标和有点 当在编写具有相似功能和能力的WPF和Silverlight应用程序的时候,努力使用一个代码库很有意义.尽管WPF和Silverlight平台非常相似,但他们只有有限的二进制兼容性.仅Si

Winform and WPF 第二遍双击快捷方式或应用程序打开原来的应用程序而不新建一个实例[进程通信 1]

private void Window_Loaded(object sender, RoutedEventArgs e)         {             Process[] pro = Process.GetProcesses();             int n = pro.Where(p => p.ProcessName.Equals("进程名称")).Count();             if (n > 1)             {      

利用DNode实现php和nodejs之间的通信

一,安装DNode, 1, for nodejs, 执行 $ sudo npm install dnode 2, for php, 利用composer来安装DNode php 执行下列语句下载composer $ wget http://getcomposer.org/composer.phar 创建一个文件composer.json,然后填入如下语句, {     "require": {         "dnode/dnode": "0.2.0&q

如何去掉WinForm或者WPF的最大化和最小化按钮

博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何去掉WinForm或者WPF的最大化和最小化按钮.

基于Winform、WPF等的客户端文件下载

有时候,我们用C#写一些客户端应用程序需要从服务器下载一些资源,如图片.dll.配置文件等.下面就来说一下,在Winform及WPF中如何下载文件. 我们的资源大多放在自己的网站上,或者从其他网站下载资源,我们需要给客户端一个URL,先给出代码: /// <summary> /// 下载文件 /// </summary> /// <param name="URL">下载文件地址</param> /// <param name=&qu

在Winform或WPF中System.Diagnostics.Process.Start的妙用

我们经常会遇到在Winform或是WPF中点击链接或按钮打开某个指定的网址, 或者是需要打开电脑中某个指定的硬盘分区及文件夹, 甚至是"控制面板"相关的东西, 那么如何做呢? 答案是使用System.Diagnostics.Process.Start().它的作用是调用外部的命令. 先来看看它的调用方法:Process.Start () Process.Start (ProcessStartInfo) Process.Start (String)Process.Start (Strin

【MVC架构】——怎样利用Json在View和Controller之间传递数据

在MVC架构中,尽管非常多东西和三层非常相似,可是也有非常大的差别.就比方传递数据.在三层架构中,传递数据就仅仅要一层返回,另外一层用同样类型的变量来接收即可了.在MVC中,事实上原理是一样的,Controller中的方法返回Json字符串.然后View来接收.或者反过来,不同的就是这之间须要一个序列化和反序列化的过程. 本文就简介利用Json在View和Controller之间传递数据的一个方面,大致从双方面介绍,一是什么是Json,二是怎样实现. 什么是Json 一.概念 百度百科说:JSO

逆天通用水印支持Winform,WPF,Web,WP,Win10。支持位置选择(9个位置 ==》[X])

好几天没上QQ了,今天上了个QQ,,额....额...貌似消息还挺多,没及时回复的还请见谅~~刚好昨天无聊把水印这快封装出来了,支持图片水印,文字水印,索引图水印和非索引图水印,支持位置选择(9个位置 ==>[X]).好吧不高兴屁话了,软件是WPF的(只满足我的需求,如果有需要可以出第个二版本),水印核心代码封装了个Helper类(通用:支持Winform,WPF,Web,WP,Win10)软件共享一下==>http://pan.baidu.com/s/1qWDwv4C 源码看下面 水印类 /