C# Winfrom程序之间通讯

实现原理

通过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

界面:

代码:

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

界面:

代码:

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);
        }
    }
}

测试

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

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

结束

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

end

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊思宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值