C#中使用RegisterWindowMessage进行进程之间进行通讯

勇哥注:

大家都知道在window里,进程之间通讯可以用消息通讯。

但是有个较冷门的知识就是RegisterWindowMessage。一般的sendmessage和postmessage是需要在窗体程序间进行通讯,你得知道对方窗口的句柄。

这个句柄每次启动程序时是系统分配的,每次不一样。

有了这个RegisterWindowMessage,两个进程可以共同持有一个相同的“句柄”,然后两者的顶层窗体间可以持这个“句柄”进行通讯。你不需要知道对方的窗体句柄是什么!


下面是引用自网络的文章,作者用C++讲述。

进程间通信的方法有很多,比如使用注册消息,内存映射,WM_COPYDATA等,下面先讲使用注册消息实现的方法。

使用注册消息比较简单,核心是消息的接收端和消息的发送端(接收端和发送端在两个不同的进程)必须注册相同的消息,这样发送消息才能识别。
下面看看具体实现:

一,发送消息进程

1, 在发送消息程序A注册消息:
const UINT WM_UPDATE_ALARMFILTER = ::RegisterWindowMessage(_T("UpdateAlarmFilter"));

2,在程序需要发送消息时调用:
    ::PostMessage(HWND_BROADCAST, WM_UPDATE_ALARMFILTER, 0, 0);
参数HWND_BROADCAST表示将该消息发送到所有top-level的窗口,including disabled or invisible unowned windows, overlapped windows, and pop-up windows. The message is not posted to child windows.

如果不想发给所有顶层窗口,只想发给指定窗口,就不使用HWND_BROADCAST参数,获得要发送窗口的句柄即可:
    CWnd *pWnd = CWnd::FindWindow(NULL,_T("NMS Server")); // 查找A进程

    if(pWnd != NULL)
    {
        pWnd->PostMessage(WM_UPDATE_ALARMFILTER, 0, 0);
    }

二,接收消息进程
1,在接收消息程序B,同样注册消息:
const UINT WM_UPDATE_ALARMFILTER = ::RegisterWindowMessage(_T("UpdateAlarmFilter"));
2,定义消息映射:
ON_REGISTERED_MESSAGE(WM_UPDATE_ALARMFILTER, OnUpdateAlarmFilter) 
3, 在头文件声明:
afx_msg LRESULT OnUpdateAlarmFilter(WPARAM wParam, LPARAM lParam);
4,在cpp文件定义函数:
LRESULT CMainFrame::OnUpdateAlarmFilter(WPARAM wParam, LPARAM lParam)
{
    // 消息处理
    return 1;
}
注意:要在消息的发送进程和接收进程注册同样的消息ID。
在接收端,如果不用消息宏定义,可以重载PreTranslateMessage,截取消息,然后处理:
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
 if(pMsg->message == WM_UPDATE_ALARMFILTER)
 {
    // 消息处理
 }
 return CDialog::PreTranslateMessage(pMsg);
}


下面是勇哥编写的C#版演示程序。


首先是接收端:

image.png

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern uint RegisterWindowMessage(string lpString);

        uint h = 0;
        public IntPtr hwndTest;

        public Form1()
        {
            InitializeComponent();
            h=RegisterWindowMessage("lxy123456");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            hwndTest = this.Handle;
        }

        protected override void DefWndProc(ref Message msg)
        {
            if (msg.Msg == h)
            {
                MessageBox.Show("kkkkk");
            }
            base.DefWndProc(ref msg);
        }

        public override bool PreProcessMessage(ref Message msg)
        {
            if(msg.Msg== h)
            {
                MessageBox.Show("kkkkk");
            }
            return base.PreProcessMessage(ref msg);
        }

      
    }
}


下面是发送端:

image.png


发送端注释了一部分代码,是想试试用sendmessage,postmessage发送不同的数据类型。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
     

        public class Win32API
        {

            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern uint RegisterWindowMessage(string lpString);


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

            [DllImport("User32.dll", EntryPoint = "FindWindowEx")]
            public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);

            /// <summary>
            /// 自定义的结构
            /// </summary>
            public struct My_lParam
            {
                public int i;
                public string s;
            }
            /// <summary>
            /// 使用COPYDATASTRUCT来传递字符串
            /// </summary>
            [StructLayout(LayoutKind.Sequential)]
            public struct COPYDATASTRUCT
            {
                public IntPtr dwData;
                public int cbData;
                [MarshalAs(UnmanagedType.LPStr)]
                public string lpData;
            }
            //消息发送API
            [DllImport("User32.dll", EntryPoint = "SendMessage")]
            public static extern int SendMessage(
                IntPtr hWnd,        // 信息发往的窗口的句柄
                int Msg,            // 消息ID
                int wParam,         // 参数1
                int lParam          //参数2
            );


            //消息发送API
            [DllImport("User32.dll", EntryPoint = "SendMessage")]
            public static extern int SendMessage(
                IntPtr hWnd,        // 信息发往的窗口的句柄
                int Msg,            // 消息ID
                int wParam,         // 参数1
                ref My_lParam lParam //参数2
            );

            //消息发送API
            [DllImport("User32.dll", EntryPoint = "SendMessage")]
            public static extern int SendMessage(
                IntPtr hWnd,        // 信息发往的窗口的句柄
                int Msg,            // 消息ID
                int wParam,         // 参数1
                ref COPYDATASTRUCT lParam  //参数2
            );

            //消息发送API
            [DllImport("User32.dll", EntryPoint = "PostMessage")]
            public static extern int PostMessage(
                IntPtr hWnd,        // 信息发往的窗口的句柄
                int Msg,            // 消息ID
                int wParam,         // 参数1
                int lParam            // 参数2
            );



            //消息发送API
            [DllImport("User32.dll", EntryPoint = "PostMessage")]
            public static extern int PostMessage(
                IntPtr hWnd,        // 信息发往的窗口的句柄
                int Msg,            // 消息ID
                int wParam,         // 参数1
                ref My_lParam lParam //参数2
            );

            //异步消息发送API
            [DllImport("User32.dll", EntryPoint = "PostMessage")]
            public static extern int PostMessage(
                IntPtr hWnd,        // 信息发往的窗口的句柄
                int Msg,            // 消息ID
                int wParam,         // 参数1
                ref COPYDATASTRUCT lParam  // 参数2
            );



        }
    

       uint handle = 0;
        public IntPtr hwndTest=(IntPtr)0xffff;

        public Form1()
        {
            InitializeComponent();
            handle =Win32API.RegisterWindowMessage("lxy123456");
            //hwndTest=Win32API.FindWindow(null, "lxy1");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string strTest = "25425";
            Win32API.COPYDATASTRUCT cds;
            cds.dwData = (IntPtr)100;
            cds.lpData = strTest;
            byte[] sarr = System.Text.Encoding.UTF8.GetBytes(strTest);
            int len = sarr.Length;
            cds.cbData = len + 1;

            Win32API.My_lParam lp = new Win32API.My_lParam();
            lp.i = 3;
            lp.s = "test";

            if (hwndTest != (IntPtr)0)
            {
                //if (DateTime.Now.Second % 2 == 0)
                //{
                //    Win32API.SendMessage(hwndTest, /*0x60*/(int)handle, 1, 3);//传递2个整型参数成功
                //}
                //if (DateTime.Now.Second % 3 == 0)
                //{
                //    Win32API.SendMessage(hwndTest, /*0x61 */ (int)handle, 5, ref lp);//传递整型参数和结构类型成功,这个方法加以改变后可以传递对象
                //}
                //if (DateTime.Now.Second % 5 == 0)
                //{
                //    Win32API.SendMessage(hwndTest, /*0x62 */ (int)handle, 5, ref cds);//传递整型参数和不定长的字符串成功
                //}
                //if (DateTime.Now.Second % 7 == 0)
                //{
                //    Win32API.PostMessage(hwndTest, /*0x63 */ (int)handle, 5, 6);//传递2个整型参数成功
                //}
                //if (DateTime.Now.Second % 9 == 0)
                //{
                //    Win32API.PostMessage(hwndTest, /*0x64 */ (int)handle, 3, ref lp);//传递整型参数成功,但是传递参数lp失败,3可以传递成功。
                //}
                //if (DateTime.Now.Second % 11 == 0)
                //{
                //    Win32API.PostMessage(hwndTest, /*0x65 */ (int)handle, 3, ref cds);//传递整型参数成功,传递参数cds失败,3可以传递成功。
                //}
                Win32API.PostMessage(hwndTest, /*0x65 */ (int)handle, 3,ref lp);//传递整型参数成功,传递参数cds失败,3可以传递成功。
            }
        }





    
    }
}


不过,由于postmessage在C#中没办法传送对象和字符串,所以也是一点小遗憾。(C++中是有办法的)

另外,HWND_BROADCAST枚举值是0xffff,万能的度娘没办法告诉我这个。

如果不使用RegisterWindowMessage的话,你得在sendmessage的时候由某个ini获取对方程序启动后写入的自己的窗口句柄,还是比较麻烦的。

当然,你也可以findwindow自己来找,还是比较麻烦。



你可以付费下载源码:


2元收费下载源码:

支付2元,才能查看本内容!立即支付查询订单


--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864