进程间通信主要包括管道, 系统IPC(Inter-Process Communication,进程间通信)(包括消息队列,信号,共享存储), 套接字(SOCKET)。
由于近期工作需要,初略的学习了下相关知识,简单的了解下windows消息方式进行通信。简单举个例子,如下:
一、主要windows API准备:
[DllImport("user32")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int
lParam);
[DllImport("user32.dll")]
public
static extern int PostMessage(int hWnd, uint Msg, int wParam, int
lParam);
[DllImport("user32.dll")]
public
static extern uint RegisterWindowMessage(string sMessageName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string
lpWindowName);
SendMessage:用于向窗体发消息,但是必须等待消息被接收方处理完成才算真正完成。
hWnd:窗体句柄;
Msg:消息名称;
wParam、lParam:消息附加的参数
PostMessage:也是用于向窗体发消息,不过这种方式是只管发送消息,不管消息是否被处理,发送之后便完成。
RegisterWindowMessage:注册消息,目的是在系统声明这个消息,这个消息便是有效的,在系统中被识别。
FindWindow: 找到指定窗体。
lpClassName:类名(测试不好用,可能使用有问题);
lpWindowName:窗体名称,即:Form的Text属性
二、详细实例代码
1、消息发送方窗体:
using System;
using System.Collections.Generic;
using
System.ComponentModel;
using System.Data;
using System.Drawing;
using
System.Text;
using System.Windows.Forms;
using
System.Runtime.InteropServices;
using System.Diagnostics;
namespace 消息发送方
{
public partial class
FrmSendMsg : Form
{
public
FrmSendMsg()
{
InitializeComponent();
}
uint MyMsg = 1000;
#region 声明winAPI系统函数
[DllImport("user32")]
public
static extern int SendMessage(int hWnd, uint Msg, int wParam, int
lParam);
[DllImport("user32.dll")]
public
static extern int PostMessage(int hWnd, uint Msg, int wParam, int
lParam);
[DllImport("user32.dll")]
public
static extern uint RegisterWindowMessage(string
sMessageName);
[DllImport("user32.dll")]
public
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
#endregion
int sendHandleWind =
0;//接收方的窗体句柄
private void
FrmSendMsg_Load(object sender, EventArgs
e)
{
//窗体加载时注册自定义的消息“testMsg”
MyMsg =
RegisterWindowMessage("testMsg");
//1、使用.net
Process操作类,根据进程名获取该进程主窗体的句柄
Process[] process =
Process.GetProcessesByName("主进程");
if (process != null && process.Length >
0)
{
sendHandleWind =
process[0].MainWindowHandle.ToInt32();
}
else
{
//先打开消息接收方窗体,再打开本消息发送方窗体。
}
//2、直接根据
winAPI,通过指定的窗体名称,即:Form的Text属性值,获取该窗体句柄
//sendHandleWind=
FindWindow(null,"主消息处理").ToInt32();
}
private void
btnSendMsg2_Click(object sender, EventArgs
e)
{
//PostMessage方式发送消息,wParam为100,lParam为2,区别消息1,测试在接收方给予不同处理
//可以防止在发送消息后,接收方响应慢,导致的卡死问题(只负责将消息发送,不管是否响应处理完成!)
PostMessage(sendHandleWind, MyMsg, 100,
2);
MessageBox.Show("发送消息2");
}
private void
btnSendMsg1_Click(object sender, EventArgs
e)
{
//发送-1,则系统所有的进程或窗体句柄都可以捕获此消息,而sendHandleWind指定了,则只要该消息接收方能接收到此消息。
// SendMessage(-1, MyMsg, 100,
1);
SendMessage(sendHandleWind, MyMsg, 100,
1);
MessageBox.Show("发消息1");
}
}
}
2、消息接收方窗体:
winAPI函数声明相同,也是在Load方法中对消息进行注册,重点的要重载一个消息处理方法WndProc,如下:
uint benDenMsg =
1;//本地消息
protected override void
WndProc(ref Message m)
{
if
(m.Msg ==
MyMsg)
{
//此处目的是,将外来捕获的消息,如:MyMsg,是其他进程发送的自定义消息,进行本地消息处理;
//将消息再次发送给本窗体句柄,则此消息变成了本地内容消息,进入本地消息队列,经过此转递,可以提高性能
PostMessage(this.Handle.ToInt32(), benDenMsg, m.WParam.ToInt32(),
m.LParam.ToInt32());
return;
}
if
(m.Msg ==
benDenMsg)
{
if (m.LParam.ToInt32() ==
1)
{
//对消息1进行一定的响应处理。。。
}
if (m.LParam.ToInt32() ==
2)
{
//对消息2进行一定的响应处理。。。
}
}
base.WndProc(ref m);
}
三、总结:
[本人能力有限,对于其原理理解的也不太深入,将近期的一点经验记录下来,希望能给学习者带来一点帮助。]
采用winform类似的系统中,进程以windows窗体形式存在的,则采用windows消息方式进行通信,比较方便简单,而且性能和效率比较高。
原文:http://www.cnblogs.com/Buchq-NET/p/windows_Message.html