.Net中封装Windows 消息实现进程间通讯

C#开发实战:基于VS2017的简易即时通讯应用MYQQ设计与实现 set;set;set;set;set;// 绘制头像小图标= null)此方案优势在于:- 解耦数据与视图;- 支持动态更新(修改即刷新 UI);- 可扩展排序、筛选等功能。继承Button类,增加表情编码与图像支持:set;set;= null)使用示例:在 C# 中,接口用于声明一组方法签名而不提供具体实现,使得不同类可以遵循相同的协议进行交互。对于 MYQQ 的本地通信场景,定义两个核心接口:和。 阅读详情

      .NET Framework 中对进程间的通讯支持不多,不过Windows API 已经为我们提供了丰富的进程间通讯的特性。我们可以使用Windows API SendMessage、PostMessage来实现windows 窗体之间的通讯。本文就是将SendMessage封装在一个窗体基类WinMsgData中,把它变成类中的一个方法以方便调用,而接收其他窗体的消息则封装成事件通知的形式提供。其中还对接收到的消息做队列处理,避免对消息发送方造成阻塞。所以只要程序中的WinForm从这个基类继承,就可以很方便的与其他的窗体进行通讯了。

下面看看具体的实现吧。
首先在窗体的构造函数中,我使用RegisterWindowMessage为希望通讯的窗体在系统中注册一个消息值。然后执行一个“Connect”的动作,就是使用PostMessage做广播,看看是否有“志同道合”者。代码如下:

  1.         public event WindowsMessageHandler OnMessage;
  2.         public delegate void WindowsMessageHandler(object sender, 
  3.                                                          WindowsMessageEventArgs e);
  4.         private const string DefaultAttachWindowMessage 
  5.                                                             = "Peanut.DefaultAttachWinMsgString";
  6.         private bool connected = false;
  7.         private int attachMessage;
  8.         private int thisHandle;
  9.         private string attachMessageString;
  10.         private List<IntPtr> AttachWindows;
  11.         private Queue<WindowsMessageEventArgs> incomingMessageQueue 
  12.                                        = new Queue<WindowsMessageEventArgs>();
  13. public WinMsgData() : this (DefaultAttachWindowMessage){}
  14.         public WinMsgData(string attachMessageString)
  15.         {
  16.              this.thisHandle = this.Handle.ToInt32();
  17.             AttachWindows = new List<IntPtr>();
  18.             this.attachMessageString = attachMessageString;
  19.             this.attachMessage = User32.RegisterWindowMessage(attachMessageString);
  20.             Connect();//“连接”
  21.         }
  22.         private void Connect()
  23.         {
  24.             if (User32.PostMessage(User32.HWND_BROADCAST, 
  25.                                  attachMessage, thisHandle ,1) == 0)//连接
  26.                 throw new Exception("PostMessage failed.");
  27.             else
  28.                 connected = true;
  29.         }

调用到Windows API代码如下:
具体如何调用Windows 的API请看Calling Win32 DLLs in C# with P/Invoke。

  1. public struct COPYDATASTRUCT
  2.     {
  3.         public IntPtr dwData;
  4.         public int cbData;
  5.         [MarshalAs(UnmanagedType.LPStr)]
  6.         public string lpData;
  7.     }
  8.     public class User32
  9.     {
  10.         public const int WM_COPYDATA = 0x4A;
  11.         public const int WM_DESTROY = 0x0002;
  12.         public const int WM_QUERYENDSESSION = 0x0011;
  13.         public const int WM_QUEUE_NOTIFY = 0x401;
  14.         [DllImport("user32")]
  15.         public static extern int PostMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
  16.         [DllImport("user32")]
  17.         public static extern int RegisterWindowMessage(string lpString);
  18.         [DllImport("user32")]
  19.         public static extern int SendMessage(IntPtr hWnd, int Msg, 
  20.                        int wParam, ref COPYDATASTRUCT lParam);
  21.         public static IntPtr HWND_BROADCAST
  22.         {
  23.             get { return (IntPtr)0xFFFF; }
  24.         }
  25.     }

 

然后就要重写WndProc来接收处理窗体消息了:

  1.  protected override void WndProc(ref Message m)
  2.         {
  3.             if (m.Msg == attachMessage &
  4.                 m.WParam.ToInt32() != 0 &
  5.                 m.WParam.ToInt32() != thisHandle )
  6.             {
  7.                 if (m.LParam.ToInt32() == 1)
  8.                     User32.PostMessage(m.WParam, attachMessage, thisHandle, 0);//回复
  9.                 if (m.LParam.ToInt32() == -1)
  10.                     AttachWindows.Remove(m.WParam);//删除窗体句柄
  11.                 else //0,1
  12.                     AttachWindows.Add(m.WParam);//保存窗体句柄
  13.             }
  14.             switch (m.Msg)
  15.             {
  16.                 case User32.WM_COPYDATA:
  17.                     COPYDATASTRUCT copyData = new COPYDATASTRUCT();
  18.                     copyData = (COPYDATASTRUCT)m.GetLParam(copyData.GetType());
  19.                     MessageNotify(m.WParam.ToInt32(), copyData.lpData);
  20.                     break;
  21.                 case User32.WM_QUEUE_NOTIFY:
  22.                     if (incomingMessageQueue.Count == 0)
  23.                         break;
  24.                     WindowsMessageEventArgs tempArgs = incomingMessageQueue.Dequeue();
  25.                     if (OnMessage != null)
  26.                         OnMessage(thisHandle, tempArgs);
  27.                     if (incomingMessageQueue.Count > 0)
  28.                         User32.PostMessage(this.Handle, User32.WM_QUEUE_NOTIFY, 0, 0); //下一个
  29.                     break;
  30.                 case User32.WM_QUERYENDSESSION:
  31.                 case User32.WM_DESTROY:
  32.                     User32.PostMessage(User32.HWND_BROADCAST, 
  33.                                   attachMessage, thisHandle, -1);//让其他人删除别再给我发消息
  34.                     break;
  35.             }
  36.             base.WndProc(ref m);
  37.         }

 

假如已经有窗体进程已经在运行,那么它就会收到新窗体起来时是所发送的“Connect”消息。上面的代码中第一个if就时处理这个消息的。首先会给消息发送者一个响应。然后会将发送者(窗体的句柄)保存到的列表AttachWindows中。
窗体后面部分就是真正处理通讯消息的部分了。MessageNotify方法首先将消息入队,接着给自己发送一个PostMessage通知自己处理,然后就马上返回。大家可能已经注意到WM_QUEUE_NOTIFY了,不错,这个就是通知自己处理消息的。“处理消息”的就是从消息队列中取出一个消息,将消息作为事件参数触发事件。子窗体只要订阅这个事件,并做处理即可。

上面已经把处理消息的过程讲完了,但还没看到发送消息的部分。下面马上给出。
还是先看代码吧,下面的代码是上面提到的MessageNotify方法及发送消息的方法SendMessage();

 

 

  1. private void MessageNotify(int target, string message)
  2.         {
  3.             incomingMessageQueue.Enqueue(new WindowsMessageEventArgs(target, message));
  4.             User32.PostMessage(this.Handle, User32.WM_QUEUE_NOTIFY, 0, 0);
  5.         } 
  6. public void SendMessage(int tarWin, string message)
  7.         {
  8.             if (!connected)
  9.                 throw new Exception("not connected!");
  10.             byte[] bytes = System.Text.Encoding.UTF8.GetBytes(message);
  11.             int length = bytes.Length;
  12.             COPYDATASTRUCT copyData = new COPYDATASTRUCT();
  13.             copyData.dwData = (IntPtr)1;
  14.             copyData.lpData = message;
  15.             copyData.cbData = length + 1;
  16.             System.Threading.Thread.Sleep(100);
  17.             try
  18.             {
  19.                 User32.SendMessage((IntPtr)tarWin, User32.WM_COPYDATA, thisHandle, ref copyData);
  20.             }
  21.             catch (Exception e)
  22.             {
  23.                 throw new Exception("windows send message error", e);
  24.             }
  25.         }

还有消息的参数类:

  1. public class WindowsMessageEventArgs : EventArgs
  2.     {
  3.         [ ==== Fields ==== ]#region [ ==== Fields ==== ]
  4.         private int targetWinHandle;
  5.         private string data; 
  6.         #endregion
  7.         public WindowsMessageEventArgs(int targetWinHandle, string data)
  8.         {
  9.             this.targetWinHandle = targetWinHandle;
  10.             this.data = data;
  11.         }
  12.         [ ==== Properties ==== ]#region [ ==== Properties ==== ]
  13.         /**//// <summary>
  14.         /// 消息发送者窗体句柄值
  15.         /// </summary>
  16.         public int TargetWinHandle
  17.         {
  18.             get { return targetWinHandle; }
  19.         }
  20.         public string Data
  21.         {
  22.             get { return data; }
  23.         } 
  24.         #endregion

子窗体只要从WinMsgData继承,并订阅消息事件:
base.OnMessage += new WinMsgData.WindowsMessageHandler(HandleMyMessage);
要发送消息的时候调用base.SendMessage(yourMessageToSend)就可以了。使用方便。
效果图:


 

 

进程间用postMessage发消息 ,在实际开发中的实例, 使用postMessage SendMessage 进程间通讯 管道 剪贴板 邮槽 共享内存 在子父进程间用postmessage通讯,本来用管道是最好的 立即下载

相关推荐

windows 服务操作API封装成函数

将windows 服务操作API封装成函数 该函数使用C语言实现。(C++亦兼容) 调用方式简单。 支持 start,stop,pause,continue,delete五个操作。 使用方法在源文件里面有例子(被注释掉的main函数)。 进行了必要的错误处理。(启动中,再调用启动则会正常返回,相反已经停止的话执行stop亦会正常返回)。 可以作为学习代码,也可以直接拿来当做工具使用。 另外,欢迎补充考虑不周到的地方。

两个winform.exe程序之间的通讯一————————发送消息

1,两个winform.exe在系统里体现是两个进程,而进程是是由系统管理。 2,user32.dll是Windows用户界面相关应用程序接口,用于包括Windows处理,基本用户界面等特性,如创建窗口和发送消息。 3,所有可以通过调用user32.dll的api来进行两个进程之间的通信。 4,发送端exe.源码          using System; using System....

weixin_41609327的博客 7329

参考MFC做的WINDOWS消息封装

参考MFC做的windows消息封装 使用方法: 1 需要处理消息的类需要继承Communication_Unit_Abstract 2 类的声明中最后带MESSAGE_MAP_DECLARE() 3 类的实现文件中带有 MESSAGE_MAP_BEGIN(**类名**) ON_WM_MESSAGE(**消息值**, **成员函数指针**) MESSAGE_MAP_END() 4 类的初始化函数(不是构造函数)中需要调用宏MESSAGE_MAP_INIT() 5 处理消息的部分调用on_message函数即可 欢迎大家批评指正

应用程序间的通讯途径(一):消息

          (本文适用于初中级读者)    在有些应用程序的设计过程中,常常需要在应用程序之间(包括本机上的程序之间和本机程序与网络主机上程序之间)保持着联系,也就是所谓的通信。    应用程序之间的通信实际上就是两个进程之间的通信。在windows程序设计中,应用程序间的通信途径大致有下面这么几种:窗口消息,动态数据交换(DDE),管道机制(pipe),内存映射文件(memory m

Daisy423XU的专栏 1896

Qwen3.6-27B本地部署实战:LM Studio配置、硬件门槛与避坑指南

大语言模型本地部署是当前AI工程落地的核心能力之一,其本质是将高参数量模型(如27B级)在受限硬件环境下实现低延迟、高稳定推理。关键技术原理涵盖量化压缩(如GGUF格式与q4_k_m精度权衡)、GPU显存分配策略(KV Cache管理与Offloading机制)、以及运行时环境兼容性(CUDA驱动、llama.cpp后端版本)。该能力直接决定私有化AI应用的技术可行性与成本边界,广泛应用于企业知识库构建、代码辅助、长文档分析等对数据主权和响应确定性要求高的场景。本文聚焦Qwen3.6-27B这一典型27B模

weixin_33272631的博客 467

OpenCV函数用法之calibrateCamera

参考链接:opencv中标定函数calibrateCamera_ychl87的专栏-优快云博客 世界坐标系的三维点投影到成像坐标系中的二维点的投影公式如下: 其中(X,Y,Z)为世界坐标系中的三维点; (u,v)为成像面坐标系中的二维点; A为相机的内参数矩阵:(cx,cy)为主光轴点,一般为图像的中心;fx和fy为焦距; [R|t]为相机的外参数矩阵:R为旋转矩阵,t为位移矩阵; 上述公式的简单推理过程如下 考虑到镜头畸变 其中,k1,k2,k3,k4,k5和k6为径向畸变,p1和.

tiger&sheep的博客 3万+

postmessage通信

在业务中,有一种开发形式为:多个子系统集成为一个父系统。每个系统之间都管理着不同的业务与逻辑,他们是互不干涉的。那么,我们如何在父系统页面中操作子系统中的内容呢?首先通过初始化两个项目。父系统端口号为3001,子系统端口号为3000。然后在父系统页面中通过一个标签,打开子系统页面: 可以看到在父系统页面,成功打开了子系统页面内容。window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为 https),端口号(443 为

黑猫几绛的博客 2234

Silvaco TCAD仿真例库——肖特基二极管正向特性(例子)

此示例演示了肖特基二极管正向特性的仿真。 展示了: 使用 Atlas 语法形成二极管结构 设置阳极的肖特基势垒高度 正向偏置阳极 代码 第一部分:描述设备 mesh(网格) electrodes locations(电极位置) doping distribution(掺杂分布) 这是位于结构左侧和右侧的,2维n型器件,具有重掺杂浮动 p 型保护环区域, (2D n-type device with heavily doped floating p-type guard ring regio.

weixin_41788560的博客 2万+

PostMessage,SendMessage跨不同权限进程通信失效的解决办法

vista之后的windows引入了UAC(用户账户控制),意味着在t

wlslblue的专栏 2087

【Ultrascale+ MPSOC学习记录】10、PS端以太网使用lwip

还是参考ALINX教程,学习PS端以太网如何使用,从教程中可以看到,开发板使用了一个xilinx默认不支持的phy JL2121,所以需要修改lwip的库源码。

ryo891012的博客 880

【ComfyUI】Z-Image 基础文生图 + 单LoRA

本文介绍了一个基于ComfyUI的Z-Image Turbo基础文生图工作流,采用轻量化UNet模型配合Qwen Image文本理解模型与LoRA风格注入,实现从文本到图像的快速生成。工作流结构清晰,包含模型加载、文本编码、采样解码等标准节点,在人物生成、构图稳定性和出图速度方面表现均衡。通过调整Prompt可控制生成内容,适合日常创作、教学演示及扩展进阶应用。

Mr数据杨 922

15分钟搞定:用Redis构建Windows即时通讯原型

考虑到Redis的发布订阅功能特别适合这种场景,我决定用它来搭建一个Windows平台的简易聊天应用原型。从我的体验来看,用Redis+Windows窗体做原型开发,配合合适的工具平台,真的能在很短时间内看到成果。上尝试部署时特别顺利,他们的环境预装了Redis服务,省去了自己配置的麻烦。整个开发过程最耗时的是调试消息的序列化和反序列化部分,不过用Newtonsoft.Json库后问题迎刃而解。用户上下线通知的实现很巧妙:在连接时发布一条上线消息到系统频道,断开连接时同样通知。

BlackStone33的博客 870

SE80 Repository Information System 在 SAP CRM WebClient UI 组件分析中的实战指南

在 SAP CRM WebClient UI 开发过程中,如何快速定位组件、视图、上下文节点以及各类运行时对象,一直是调试效率的关键。(后文简称RIS)正是隐藏在SE80里的瑞士军刀,帮助开发者按照组件集、数据元素、上下文节点属性等多维条件进行交叉检索。官方博客将它描述为本文结合多年项目经验,系统梳理RIS的功能脉络与实战技巧,同时引入真实案例,示范如何借助它在几分钟内完成以往动辄数小时的排查任务。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2万+

探索现代通讯的新境界:WebQQWeChat —— .NET下的即时通讯利器

探索现代通讯的新境界:WebQQWeChat —— .NET下的即时通讯利器 在快速迭代的技术浪潮中,集成通讯能力成为许多应用程序不可或缺的一部分。今天,我们要向您推荐一个集智慧与便捷于一体的开源宝藏——WebQQWeChat。这款由【huoshan12345】匠心打造的项目,旨在通过.NET平台重新定义网页QQ和网页微信的交互体验,为开发者打开了一扇通往高效通讯解决方案的大门。 项目介绍 Web...

gitblog_00016的博客 812

[Python从零到壹] 十四.机器学习之分类算法五万字总结全网首发(决策树、KNN、SVM、分类对比实验)

分类(Classification)属于有监督学习(Supervised Learning)中的一类,它是数据挖掘、机器学习和数据科学中一个重要的研究领域。分类模型类似于人类学习的方式,通过对历史数据或训练集的学习得到一个目标函数,再用该目标函数预测新数据集的未知属性。本章主要讲述分类算法基础概念,并结合决策树、KNN、SVM分类算法案例分析各类数据集,从而让读者学会使用Python分类算法分析自己的数据集,研究自己领域的知识,从而创造价值。 19.1 分类 19.1.1 分类模型 与前面讲述的聚类模型类似

杨秀璋的专栏 2万+

Arcgis中的模型构建器技术之按属性批量建库并对应输出

好久没更新了,之前我们已经介绍过四至点提取模型,前两天有同事问怎么样按属性批量建数据库并对应输出相关图斑。比如将一个县的永农数据按乡镇建立数据库并将对应乡镇的永农数据输出到相应的数据库里。今天就介绍一下相关的模型构建过程。

weixin_44671081的博客 518

Windows即时通讯消息保留技术解决方案深度解析:RevokeMsgPatcher内存补丁实现原理与企业级应用

RevokeMsgPatcher作为Windows平台下针对主流即时通讯软件的消息保留技术解决方案,通过动态链接库修改和内存补丁技术实现了对微信、QQ、TIM等软件的消息防撤回功能。本技术文档将深入解析该解决方案的架构设计、实现原理以及在企业通信安全领域的应用价值,为技术开发者和系统管理员提供全面的技术参考。 ## 即时通讯撤回机制技术分析 现代即时通讯软件的撤回功能通常基于客户端-服务器协同

gitblog_00543的博客 412

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

对MFC封装Windows通讯API的研究 (转)

对MFC封装Windows通讯API的研究 (转)[@more@]一、引言 Inte.NET进行网际间通讯,在WWW浏览、FTP、Gopher这些常规服务,以及在网络电话、多媒体会议等这些对实时性要求严格的应用中成为研究的热点...

csd3176的博客 125

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

AQS源码级拆解:从Lock到Condition的并发锁实现原理

从并发编程中线程安全的基本概念切入,说明锁在控制多线程竞争、保证共享资源有序访问中的核心作用。Java并发包中的ReentrantLock、Semaphore等同步工具之所以能统一处理排队、唤醒、重入等复杂逻辑,底层都依赖AbstractQueuedSynchronizer(AQS)框架。AQS通过volatile状态变量与CAS原子操作维护同步状态,再借助CLH变体队列管理等待线程,以模板方法模式将锁逻辑与排队机制解耦。理解AQS的获取与释放链路,就能看清公平锁、非公平锁、Condition条件变量以及共

cuiji1279的博客 295

深入解析Windows即时通讯软件防撤回技术实现

在即时通讯软件日益普及的今天,消息撤回功能虽然为用户提供了纠错的机会,但也带来了信息丢失的困扰。当重要的商业信息、技术讨论或珍贵回忆被撤回时,我们往往感到遗憾。今天,让我们一同探索一个开源技术解决方案——RevokeMsgPatcher,它通过二进制补丁技术实现了微信、QQ、TIM等主流即时通讯软件的防撤回功能。 ## 技术原理深度剖析:二进制补丁的艺术 防撤回功能的实现本质上是对软件二进制文

gitblog_00364的博客 310

WINDOWS API 进程间通信,管道(PIPE),Remoting技术

在.NET 直接支持的Remoting技术有IPChannel,TCPChannel,HTTPChannel。      在跨广域网的应用里,推荐使用WCF技术,基于HTTPCHANNEL,而在进程中通讯中,反而IPCChannel更见优秀,但是不能跨局域网。      IPCChannel是.NET Framework 2.0 里面新增的,它使用 Windows 进程间通信 (IPC) 系统

蓝叶菱的专栏 1917

C#进行CAN【控制器局域网】通讯

CAN总线通信系统设计与实现 摘要: 本文介绍了一个基于C#的CAN总线通信系统设计方案,采用Peak公司的PCANBasic.NET接口实现硬件通信功能。系统具备以下主要功能:1) 支持多种波特率配置,实现CAN设备连接与管理;2) 提供消息收发功能,支持标准帧格式;3) 内置信号解析引擎,可自定义信号解析规则;4) 实时数据显示功能,包括网格视图和动态图表;5) 数据记录功能,支持CSV格式导出。系统采用多线程架构处理实时数据,通过MVC模式实现界面与逻辑分离,适用于汽车电子、工业控制等领域的CAN总线

ylq1045的专栏 922

c#/.net(4)windows Form窗体间通讯

通常打开一个新的窗口,如果只需要传递简单的OK或者CANCEL之类的消息到父窗体,可以使用DialogResult 来保存用户选择的结果如果需要在窗体之间实时交换数据,那么最好在构造窗体时把封装的数据类或者存贮数据的那个窗体类传递给新窗体,可以传递对窗体的引用或者直接使用this。 public partial class Form_scene : Form {

欢迎来到musique的blog 1136

C#调用Windows API实现窗口标题栏闪烁:原理、封装与实战

在桌面应用开发中,用户注意力引导是提升交互体验的关键技术之一。其核心原理在于通过视觉动态变化打破界面平衡,从而高效传递状态信息。从技术实现层面看,这通常涉及操作系统底层的窗口消息机制与图形绘制循环。在Windows平台上,系统提供了原生API来标准化这一行为,开发者可通过平台调用(P/Invoke)技术,让托管代码安全高效地访问这些底层能力。这不仅能实现如标题栏闪烁、任务栏按钮高亮等基础功能,更能为监控告警、即时通讯、后台任务通知等应用场景提供非侵入式的强提醒方案。本文将以C#调用FlashWindowEx

weixin_30219613的博客 346
上一篇: C#中四种进程或线程同步互斥的控制方法
下一篇: 解决Fedora 下 RMagic无法安装的问题
forlinux
博客等级 码龄21年 53粉丝 95原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值