勇哥注:
大家都知道在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#版演示程序。
首先是接收端:

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);
}
}
}下面是发送端:

发送端注释了一部分代码,是想试试用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元收费下载源码:
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!


少有人走的路



















