您的当前位置:首页>全部文章>文章详情

【C#】C# Winform程序之间通讯

CrazyPanda发表于:2024-01-30 23:19:29浏览:381次TAG:


实现原理

通过Windows系统中 User32.dll 中的 FindWindow 方法来寻找系统正在运行的程序句柄,通过 SendMessage 方法来发送消息,winform 中的 WndProc 方法来接收消息,下面是SendMessage,FindWindow 这两个参数的具体介绍:


1.SendMessage

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

IntPtr SendMessage(int hWnd, int msg, IntPtr wParam, IntPtr lParam);

参数
hWnd
其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口
Msg
指定被发送的消息
wParam
指定附加的消息指定信息
IParam
指定附加的消息指定信息
返回值
返回值指定消息处理的结果,依赖于所发送的消息
备注
需要用HWND_BROADCAST通信的应用程序应当使用函数RegisterWindowMessage来为应用程序间的通信取得一个唯一的消息。


2.FindWindow

函数获得一个顶层窗体的句柄,该窗体的类名和窗体名与给定的字符串相匹配。这个函数不查找子窗体。在查找时不区分大写和小写
函数原型

int FindWindow(string lpClassName, string lpWindowName);

参数
IpClassName
指向一个指定了类名的空结束字符串,或一个标识类名字符串的成员的指针。假设该參数为一个成员,则它必须为前次调用theGlobafAddAtom函数产生的全局成员。该成员为16位,必须位于IpClassName的低 16位,高位必须为 0
IpWindowName
指向一个指定了窗体名(窗体标题)的空结束字符串。假设该參数为空,则为全部窗体全匹配
返回值
假设函数成功,返回值为具有指定类名和窗体名的窗体句柄;假设函数失败,返回值为NULL


下面的 Demo 是基于 .NET Framework 框架写的,经测试有效,但在最新的 .Net6 框架中,下面的代码无法收到消息,具体原因还不太清楚,有知道的大佬,欢迎留言告诉我。


程序1

界面:

1.png

代码:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
namespace SendDemo1st
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        public struct CopyDataStruct
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }
 
        public const int WM_COPYDATA = 0x004A;
 
        //通过窗口标题来查找窗口句柄   
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);
 
        //在DLL库中的发送消息函数  
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage
            (
            int hWnd,                        // 目标窗口的句柄    
            int Msg,                         // 在这里是WM_COPYDATA  
            int wParam,                      // 第一个消息参数  
            ref CopyDataStruct lParam        // 第二个消息参数  
           );
 
        //发送消息
        private void button1_Click(object sender, EventArgs e)
        {
            string strURL = textBox1.Text;
            CopyDataStruct cds;
            cds.dwData = (IntPtr)1; //这里可以传入一些自定义的数据,但只能是4字节整数        
            cds.lpData = strURL;    //消息字符串  
            cds.cbData = System.Text.Encoding.Default.GetBytes(strURL).Length + 1; //注意,这里的长度是按字节来算的  
            SendMessage(FindWindow(null, "Form2"), WM_COPYDATA, 0, ref cds);       // 窗口标题
        }
 
        //接收消息方法  
        protected override void WndProc(ref System.Windows.Forms.Message e)
        {
            if (e.Msg == WM_COPYDATA)
            {
                CopyDataStruct cds = (CopyDataStruct)e.GetLParam(typeof(CopyDataStruct));
                textBox2.Text = cds.lpData.ToString();
            }
            base.WndProc(ref e);
        }
    }
}


程序2

界面:

1.png

代码:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
namespace SendDemo2nd
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
 
        public struct CopyDataStruct
        {
            public IntPtr dwData;
            public int cbData;
 
            [MarshalAs(UnmanagedType.LPStr)]
 
            public string lpData;
        }
 
        public const int WM_COPYDATA = 0x004A;
 
        //通过窗口标题来查找窗口句柄   
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);
 
        //在DLL库中的发送消息函数  
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage
            (
            int hWnd,                        // 目标窗口的句柄    
            int Msg,                         // 在这里是WM_COPYDATA  
            int wParam,                      // 第一个消息参数  
            ref CopyDataStruct lParam        // 第二个消息参数  
           );
 
        private void button1_Click(object sender, EventArgs e)
        {
            string strURL = textBox1.Text;
            CopyDataStruct cds;
            cds.dwData = (IntPtr)1; //这里可以传入一些自定义的数据,但只能是4字节整数        
            cds.lpData = strURL;    //消息字符串  
            cds.cbData = System.Text.Encoding.Default.GetBytes(strURL).Length + 1;  //注意,这里的长度是按字节来算的  
            SendMessage(FindWindow(null, "Form1"), WM_COPYDATA, 0, ref cds);       // 窗口标题
        }
 
 
        //接收消息方法  
        protected override void WndProc(ref System.Windows.Forms.Message e)
        {
            if (e.Msg == WM_COPYDATA)
            {
                CopyDataStruct cds = (CopyDataStruct)e.GetLParam(typeof(CopyDataStruct));
                textBox2.Text = cds.lpData.ToString();
            }
            base.WndProc(ref e);
        }
    }
}


测试

运行两个程序,界面几乎没什么区别,下面测试下效果:

1.png

 经过测试,发送消息,和接收消息都是正常可以使用的,但是WndProc这个方法只能运行在winfrom项目中,这也是个缺点。


结束

如果这个帖子对你有用,欢迎给我点赞 + 留言,谢谢

end


原文链接C# Winfrom程序之间通讯_c#桌面应用程序如何连接即时通讯-CSDN博客

猜你喜欢

【C#】C# Winform 日志系统
目录一、效果1.刷新日志效果2.单独日志的分类3.保存日志的样式二、概述三、日志系统API1.字段Debug.IsScrollingDebug.VersionDebug.LogMaxLenDebug.LogTitleDebug.IsConsoleShowLog2.方法Debug.Log(string)Debug.Log(string, params object[])Debug.Logs(string)Debug.Logs(string, params object[])Debug.LogSav
发表于:2024-02-18 浏览:361 TAG:
【C#】C#md5加密
using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks;   namespace mdstr {     internal 
发表于:2024-01-30 浏览:267 TAG:
【C#】从零开始用C#写一个桌面应用程序(二)一个表白程序
恶搞表白小程序如何添加按钮,如何添加属性和事件请移步前文。基础操作第一步:新建窗口  在工具箱内找到label和button,拖到form上,设置它们的size属性,autosize属性,text属性。第二步:添加事件为了实现我们的效果,需要给三个按钮分别设计点击事件,鼠标移入事件,鼠标点下事件。分别为click,mouseenter,mousedown事件。第三步:实现移动逻辑this获取form对象,clientsize获取实时大小,使用随机数值,设置对应按钮位置。将对应
发表于:2024-01-30 浏览:294 TAG:
【C#】C# Winfrom Chart 图表控件 柱状图、折线图
目录一、参考二、柱状图1.新建项目2.修改图表样式3.绑定数据4.删除Series1图例1)使用属性窗体删除2)使用代码删除5.自定义X轴的刻度值1)使用List绑定2)使用LabelStyle.Format绑定6.自定义Y轴的刻度值7.X轴刻度值显示不全的解决方法8.修改X Y刻度值的字体样式9.X轴刻度值旋转90°10.禁用Y轴刻度线11.去掉Y轴刻度值12.改变柱子的宽度13.设置网格线的颜色14.设置网格线的线型三、折线图1.图表设置2.绑定数据结束效果:一、参考c# Chart设置样式
发表于:2024-02-02 浏览:412 TAG:
【C#】C#Windows桌面应用开发实践
速览必须功能一览简单下载异步下载如何解决下载文件不完整的问题使用 Downloader 进行 HTTP 多线程下载创建一个下载服务:下载非 HTTP 协议的文件注册表相关的操作(添加与删除)文件占用问题的处理防止重复启动只开一个实例,通用弹窗和提示 使用示例使用 C# 下载文件 (引用自使用 C# 下载文件的十八般武艺)常用接口示例必须功能一览注册表相关的操作(添加与删除)       RegistryKey hkm
发表于:2024-01-28 浏览:362 TAG:
【C#】C# Winform 文本面板带滚动条
在PC软件开发中经常有这样的需求,需要在一个固定大小的面板中显示一些内容,并且面板能上下拖动,将所有的内容完整的展示,有点类似网页上看新闻,如果要在 winfrom 中要如何实现的呢,下面就演示如何实现的吧效果:1.新建一个winform 项目,在界面中拖入一个Panel 将 panel1 的 AutoScroll 设置为 True2.再次拖入一个 Panel ,将高度拉长,这时就自动出现了滚动条,只是此时里面还没有任何内容,下面就在 panel2 中加入一点内容。
发表于:2024-02-03 浏览:323 TAG:
【C#】C# Winform 相册功能,图片缩放,拖拽,预览图分页
一、前言在一些项目中也会用到预览图片的功能,至于为什么有一个添加图片的按钮,是因为有些项目,比如视觉相关的项目,摄像头拍摄图片,然后显示在界面上,拍一次显示一张。另一个,就是分页功能,当预览图位置不够用时就会用到。当前软件的功能1.添加图片如果8个预览图都满了,会自动分页,就可以点击上一页,或者下一页了。2.点击预览图显示大图点击预览图,之前的拖拽和放大会自动复位3.大图可以拖拽,放大,缩小如果图片比较小,有这个功能就看到图片的更多细节了。4.图片倒序排列最后拍摄的图片,始终显示在前面,方便用户
发表于:2024-02-02 浏览:313 TAG:
【C#】Winform NanUI 0.77版本 JS和C#相互调用
目录一、导入插件二、常用方法三、C#和JS相互调用1.C# 调用JS2.JS调用C#方法3.完整版C#代码4.完整版JS代码结束一、导入插件用的NanUI版本0.77参考官方地址:https://docs.formium.net/zh-hans/tutorial/first-app.html二、常用方法基础代码:using NetDimension.NanUI; using NetDimension.NanUI.Browser;   class MainW
发表于:2024-02-06 浏览:384 TAG:
【C#】Winform NanUI 0.77版本 清除Cookie等本地缓存
目录需求NanUI0.88版本的缓存路径NanUI0.77版本的缓存路径试着实现功能添加扩展出现的问题解决问题结束需求清除web前端保存的一些的数据,或者清除浏览器缓存会用到。NanUI0.88版本的缓存路径在NanUI0.88版本中,只要在Program.cs启动模块中调用app.ClearCacheFile();就可以清除浏览的缓存了。0.88版本的缓存路径:"C:\\Users\\Administrator\\AppData\\Roaming\\Net Dimension Stu
发表于:2024-02-08 浏览:308 TAG:
【C#】C# NLua Winform 热更新
一、概述NLua 是一个用于 .NET 平台的 Lua 脚本绑定库。它允许在 C# 代码中嵌入 Lua 脚本,并允许两者之间进行交互。NLua 的主要特点包括:轻量级:NLua 是一个轻量级的库,易于集成到现有的 .NET 项目中。动态类型:Lua 是动态类型的语言,这意味着变量的类型可以在运行时改变。灵活的绑定:NLua 提供了灵活的绑定机制,使得 C# 和 Lua 之间的数据交互变得简单。丰富的 API:NLua 提供了丰富的 API,以便在 Lua 脚本中调用 .NET 的类和方法。调试支
发表于:2024-02-18 浏览:343 TAG: