原文:【Win32 API】利用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, , null, "");
hwndThree =new IntPtr(GetWindow(hwndThree.ToInt32(), ));
hwndThree = new IntPtr(GetWindow(hwndThree.ToInt32(), )); //获取按钮的句柄 找3次才找到目标textbox SendMessage(hwndThree, WM_SETTEXT, , 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);
cds.lpData = text;
cds.cbData = len + ;
SendMessage(WINDOW_HANDLER, WM_COPYDATA, , 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);
cds.lpData = text;
cds.cbData = len + ;
SendMessage(WINDOW_HANDLER, WM_COPYDATA, , 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进行通信,有时间再研究.最后,如果您有更好的建议,请不吝指教,感激不尽!

【Win32 API】利用SendMessage实现winform与wpf之间的消息传递的更多相关文章

  1. 调用win32 api 函数SendMessage() 实现消息直接调用

    简单的调用例子, 适合初学者学习,当然 我也是初学者. #include <windows.h> #include <stdio.h> #include <stdlib. ...

  2. WPF Win32 API 嵌入Form 窗体

    WIn32 API: public class Win32Native { [DllImport("user32.dll", SetLastError = true, CharSe ...

  3. Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用

    前面几篇介绍了Web API的基础信息,以及如何基于混合框架的方式在WInform界面里面整合了Web API的接入方式,虽然我们看似调用过程比较复杂,但是基于整个框架的支持和考虑,我们提供了代码生成 ...

  4. [C++] Win32 API 的多线程Timer管理Trick - 利用PostThreadMessage

    有时候我们需要在程序里定时地完成一些任务, 比如5秒后发送, 10秒后弹窗之类的操作. 这就需要一个类似于定时器的组件. 这个组件在windows.h里被称为Timer. 设置一个Timer 第一步当 ...

  5. C# 调Win32 API SendMessage简单用法及wMsg常量

    函数功能:该函数将指定的消息发送到一个或多个窗口.此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回.该函数是应用程序和应用程序之间进行消息传递的主要手段之一.     函数原型:LRESU ...

  6. 对比MFC和Winform及WPF

    MFC 生成本机代码,自然是很快.可是,消息循环,减缓了界面显示速度.winform 封装了 win32 的api,多次进行P/invoke 操作 (大部分使用p/invoke操作封装),速度慢 .w ...

  7. Winform、WPF、Silverlight、MFC区别与联系

    WinForm 在Windows中,诸如窗体绘制等功能由GDI(图形设备接口)实现,放在操作系统内核中.Windows Forms在底层使用的是GDI+.GDI+是GDI的“面向对象包装”,使用C++ ...

  8. win32 API函数

    cozy的博文 win32 API函数大全   (2008-03-15 16:28) 分类: 个人日记 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WN ...

  9. 利用SendMessage实现窗口拖动

    原文:利用SendMessage实现窗口拖动 利用SendMessage实现窗口拖动                                            周银辉 想想以前用跟踪鼠标位 ...

随机推荐

  1. Python学习笔记之——requests库

    requests库一个优雅而简单的用于Python的HTTP库,可以极大的简化我们发送http请求及获取响应的代码. requests是python的第三方库,所以使用之前需要先安装. 1.安装之后就 ...

  2. Adobe Flash Builder 4.6 打开时提示Failed to create the Java Virtual Machine

    最近使用actionscript来编程,用到Adobe Flash Builder 工具,之前一直用着都没事的,今天打开突然就报了这个错误,然后就打不开了 好了,不多说,直接来吧. 首先在你的Adob ...

  3. [Linux]《鸟哥的私房菜》笔记 (缓慢更新)

    暂时不更新了..这几天一看起书来发现内容很多,这样写blog太慢,也没意义.所以现在是每天看书,在笔记本上记笔记,再配合着<操作系统>和 linux内核 加深理解.往后会以心得体会为主写一 ...

  4. Lodash学习笔记

    有多年开发经验的工程师,往往都会有自己的一套工具库,称为utils.helpers等等,这套库一方面是自己的技术积累,另一方面也是对某项技术的扩展,领先于技术规范的制订和实现. Lodash就是这样的 ...

  5. windows 远程连接

    * 方法1:windows自带的远程工具 缺点:如果操作系统是家庭版,会一致连接不上:尽管想办法把这个功能打开: 步骤: * 打开允许远程连接: 点进去自己设置就行,没有什么好说的 设置完之后,需要允 ...

  6. 服务器重启可能会导致SQL Server中部分数据库变为single user mode

    今天检查公司生产服务器的SQL Server数据库,惊讶的发现有三个生产数据库变为了single user mode.奇怪的是没有任何人和程序执行过SQL语句将这三个数据库设置为single user ...

  7. nc 命令使用详解

    nc 命令介绍: Ncat is a feature-packed networking utility which reads and writes data across networks fro ...

  8. October 23rd, 2017 Week 43rd Monday

    Champions have the courage to keep turning the pages because they know a better chapter lies ahead. ...

  9. DevExpress10、RichEditControl

    1.概述 传统.NET界面也有一个RichTextBox控件,一个富文本控件,可存储图片文字,有自己的文件格式RTF. 在DevExpress控件组里面也有一个同等的控件,RichEditContro ...

  10. ab参数详解 – 压力测试

    命令参数:    -n requests     Number of requests to perform    //在测试会话中所执行的请求个数.默认时,仅执行一个请求    -c concurr ...