C#进程(应⽤程序)间通信
SendMessage⽤法:
函数功能:该函数将指定的消息发送到⼀个或多个窗⼝。此函数为指定的窗⼝调⽤窗⼝程序,直到窗⼝程序处理完消息再返回。该函数是应⽤程序和应⽤程序之间进⾏消息传递的主要⼿段之⼀。
函数原型:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
参数:
hWnd:其窗⼝程序将接收消息的窗⼝的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗⼝,包括⽆效或不可见的⾮⾃⾝拥有的窗⼝、被覆盖的窗⼝和弹出式窗⼝,但消息不被发送到⼦窗⼝。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。
返回值:返回值指定消息处理的结果,依赖于所发送的消息。
备注:需要⽤HWND_BROADCAST通信的应⽤程序应当使⽤函数RegisterWindowMessage来为应⽤程序间的通信取得⼀个唯⼀的消息。
如果指定的窗⼝是由调⽤线程创建的,则窗⼝程序⽴即作为⼦程序调⽤。如果指定的窗⼝是由不同线程创建的,则系统切换到该线程并调⽤恰当的窗⼝程序。线程间的消息只有在线程执⾏消息检索代码时才被处理。发送线程被阻塞直到接收线程处理完消息为⽌。
C#中使⽤该函数⾸先导⼊命名空间:
using System.Runtime.InteropServices;
然后写API引⽤部分的代码,放⼊ class 内部
[DllImport("user32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
这个函数有四个参数,第⼀个是窗⼝句柄,窗⼝可以是任何类型的屏幕对象;第⼆个是⽤于区别其他消
息的常量值;第三个通常是⼀个与消息有关的常量值,也可能是窗⼝或控件的句柄,第三个参数是可选参数,有的消息要,有的不需要,⽐如单击就不需要这个参数,
别的消息,⽐如⿏标移动的可能需要在这⾥加上⼀些⿏标的参数;第四个通常是⼀个指向内存中数据的指针。在C#中消息需要定义成windows系统中的原始的16进制数字,⽐如 const int WM_Lbutton = 0x201; //定义了⿏标的左键点击消息。详细值在最后。
const int BM_CLICK = 0xF5;
IntPtr maindHwnd = FindWindow(null, "窗体标题名"); //获得已知窗体标题名的句柄
if (maindHwnd != IntPtr.Zero)
{
IntPtr childHwnd = FindWindowEx(maindHwnd, IntPtr.Zero, null, "⼦窗体"); //获得⼦窗体的句柄
if (childHwnd != IntPtr.Zero)
{
SendMessage(childHwnd, BM_CLICK, 0, 0); //发送点击按钮的消息
}
else
{
MessageBox.Show("没有到⼦窗⼝");
}
}
else
{
MessageBox.Show("没有到窗⼝");
}
/
/wMsg参数常量值:
//创建⼀个窗⼝
const int WM_CREATE = 0x01;
//当⼀个窗⼝被破坏时发送
const int WM_DESTROY = 0x02;
//移动⼀个窗⼝
const int WM_MOVE = 0x03;
//改变⼀个窗⼝的⼤⼩
const int WM_SIZE = 0x05;
//⼀个窗⼝被激活或失去激活状态
const int WM_ACTIVATE = 0x06;
/
/⼀个窗⼝获得焦点
const int WM_SETFOCUS = 0x07;
//⼀个窗⼝失去焦点
const int WM_KILLFOCUS = 0x08;
//⼀个窗⼝改变成Enable状态
const int WM_ENABLE = 0x0A;
//设置窗⼝是否能重画
const int WM_SETREDRAW = 0x0B;
//应⽤程序发送此消息来设置⼀个窗⼝的⽂本
const int WM_SETTEXT = 0x0C;
//应⽤程序发送此消息来复制对应窗⼝的⽂本到缓冲区
const int WM_GETTEXT = 0x0D;
//得到与⼀个窗⼝有关的⽂本的长度(不包含空字符)
const int WM_GETTEXTLENGTH = 0x0E;
//要求⼀个窗⼝重画⾃⼰
const int WM_PAINT = 0x0F;
//当⼀个窗⼝或应⽤程序要关闭时发送⼀个信号
const int WM_CLOSE = 0x10;
//当⽤户选择结束对话框或程序⾃⼰调⽤ExitWindows函数
const int WM_QUIT = 0x12;
//当⽤户窗⼝恢复以前的⼤⼩位置时,把此消息发送给某个图标
const int WM_QUERYOPEN = 0x13;
/
/当窗⼝背景必须被擦除时(例在窗⼝改变⼤⼩时)
const int WM_ERASEBKGND = 0x14;
//当系统颜⾊改变时,发送此消息给所有顶级窗⼝
const int WM_SYSCOLORCHANGE = 0x15;
//当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应⽤程序,通知它对话是否结束
const int WM_ENDSESSION = 0x16;
//当隐藏或显⽰窗⼝是发送此消息给这个窗⼝
const int WM_SHOWWINDOW = 0x18;
//发此消息给应⽤程序哪个窗⼝是激活的,哪个是⾮激活的
const int WM_ACTIVATEAPP = 0x1C;
//当系统的字体资源库变化时发送此消息给所有顶级窗⼝
const int WM_FONTCHANGE = 0x1D;
//当系统的时间变化时发送此消息给所有顶级窗⼝
const int WM_TIMECHANGE = 0x1E;
//发送此消息来取消某种正在进⾏的摸态(操作)
const int WM_CANCELMODE = 0x1F;
//如果⿏标引起光标在某个窗⼝中移动且⿏标输⼊没有被捕获时,就发消息给某个窗⼝
const int WM_SETCURSOR = 0x20;
//当光标在某个⾮激活的窗⼝中⽽⽤户正按着⿏标的某个键发送此消息给//当前窗⼝
const int WM_MOUSEACTIVATE = 0x21;
//发送此消息给MDI⼦窗⼝//当⽤户点击此窗⼝的标题栏,或//当窗⼝被激活,移动,改变⼤⼩
const int WM_CHILDACTIVATE = 0x22;
/
/此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK的hook程序分离出⽤户输⼊消息
const int WM_QUEUESYNC = 0x23;
//此消息发送给窗⼝当它将要改变⼤⼩或位置
const int WM_GETMINMAXINFO = 0x24;
//发送给最⼩化窗⼝当它图标将要被重画
const int WM_PAINTICON = 0x26;
//此消息发送给某个最⼩化窗⼝,仅//当它在画图标前它的背景必须被重画
const int WM_ICONERASEBKGND = 0x27;
//发送此消息给⼀个对话框程序去更改焦点位置
const int WM_NEXTDLGCTL = 0x28;
//每当打印管理列队增加或减少⼀条作业时发出此消息
const int WM_SPOOLERSTATUS = 0x2A;
//当button,combobox,listbox,menu的可视外观改变时发送
const int WM_DRAWITEM = 0x2B;
//当button, combo box, list box, list view control, or menu item 被创建时
const int WM_MEASUREITEM = 0x2C;
//此消息有⼀个LBS_WANTKEYBOARDINPUT风格的发出给它的所有者来响应WM_KEYDOWN消息
const int WM_VKEYTOITEM = 0x2E;
//此消息由⼀个LBS_WANTKEYBOARDINPUT风格的列表框发送给他的所有者来响应WM_CHAR消息
const int WM_CHARTOITEM = 0x2F;
//当绘制⽂本时程序发送此消息得到控件要⽤的颜⾊
const int WM_SETFONT = 0x30;
/
/应⽤程序发送此消息得到当前控件绘制⽂本的字体
const int WM_GETFONT = 0x31;
//应⽤程序发送此消息让⼀个窗⼝与⼀个热键相关连
const int WM_SETHOTKEY = 0x32;
//应⽤程序发送此消息来判断热键与某个窗⼝是否有关联
const int WM_GETHOTKEY = 0x33;
//此消息发送给最⼩化窗⼝,当此窗⼝将要被拖放⽽它的类中没有定义图标,应⽤程序能返回⼀个图标或光标的句柄,当⽤户拖放图标时系统显⽰这个图标或光标
const int WM_QUERYDRAGICON = 0x37;
//发送此消息来判定combobox或listbox新增加的项的相对位置
const int WM_COMPAREITEM = 0x39;
//显⽰内存已经很少了
const int WM_COMPACTING = 0x41;
//发送此消息给那个窗⼝的⼤⼩和位置将要被改变时,来调⽤setwindowpos函数或其它窗⼝管理函数
const int WM_WINDOWPOSCHANGING = 0x46;
//发送此消息给那个窗⼝的⼤⼩和位置已经被改变时,来调⽤setwindowpos函数或其它窗⼝管理函数
const int WM_WINDOWPOSCHANGED = 0x47;
//当系统将要进⼊暂停状态时发送此消息
const int WM_POWER = 0x48;
//当⼀个应⽤程序传递数据给另⼀个应⽤程序时发送此消息
const int WM_COPYDATA = 0x4A;
//当某个⽤户取消程序⽇志激活状态,提交此消息给程序
const int WM_CANCELJOURNA = 0x4B;
/
/当某个控件的某个事件已经发⽣或这个控件需要得到⼀些信息时,发送此消息给它的⽗窗⼝
const int WM_NOTIFY = 0x4E;
//当⽤户选择某种输⼊语⾔,或输⼊语⾔的热键改变
const int WM_INPUTLANGCHANGEREQUEST = 0x50;
//当平台现场已经被改变后发送此消息给受影响的最顶级窗⼝
const int WM_INPUTLANGCHANGE = 0x51;
//当程序已经初始化windows帮助例程时发送此消息给应⽤程序
const int WM_TCARD = 0x52;
//此消息显⽰⽤户按下了F1,如果某个菜单是激活的,就发送此消息个此窗⼝关联的菜单,否则就发送给有焦点的窗⼝,如果//当前都没有焦点,就把此消息发送给//当前激活的窗⼝const int WM_HELP = 0x53;
//当⽤户已经登⼊或退出后发送此消息给所有的窗⼝,//当⽤户登⼊或退出时系统更新⽤户的具体设置信
息,在⽤户更新设置时系统马上发送此消息
const int WM_USERCHANGED = 0x54;
//公⽤控件,⾃定义控件和他们的⽗窗⼝通过此消息来判断控件是使⽤ANSI还是UNICODE结构
const int WM_NOTIFYFORMAT = 0x55;
//当⽤户某个窗⼝中点击了⼀下右键就发送此消息给这个窗⼝
//const int WM_CONTEXTMENU = ??;
//当调⽤SETWINDOWLONG函数将要改变⼀个或多个窗⼝的风格时发送此消息给那个窗⼝
const int WM_STYLECHANGING = 0x7C;
//当调⽤SETWINDOWLONG函数⼀个或多个窗⼝的风格后发送此消息给那个窗⼝
const int WM_STYLECHANGED = 0x7D;
//当显⽰器的分辨率改变后发送此消息给所有的窗⼝
const int WM_DISPLAYCHANGE = 0x7E;
//此消息发送给某个窗⼝来返回与某个窗⼝有关连的⼤图标或⼩图标的句柄
const int WM_GETICON = 0x7F;
//程序发送此消息让⼀个新的⼤图标或⼩图标与某个窗⼝关联
const int WM_SETICON = 0x80;
//当某个窗⼝第⼀次被创建时,此消息在WM_CREATE消息发送前发送
const int WM_NCCREATE = 0x81;
//此消息通知某个窗⼝,⾮客户区正在销毁
//当某个窗⼝的客户区域必须被核算时发送此消息
const int WM_NCCALCSIZE = 0x83;
//移动⿏标,按住或释放⿏标时发⽣
const int WM_NCHITTEST = 0x84;
//程序发送此消息给某个窗⼝当它(窗⼝)的框架必须被绘制时
const int WM_NCPAINT = 0x85;
//此消息发送给某个窗⼝仅当它的⾮客户区需要被改变来显⽰是激活还是⾮激活状态
const int WM_NCACTIVATE = 0x86;
//发送此消息给某个与对话框程序关联的控件,widdows控制⽅位键和TAB键使输⼊进⼊此控件通过应
const int WM_GETDLGCODE = 0x87;
//当光标在⼀个窗⼝的⾮客户区内移动时发送此消息给这个窗⼝⾮客户区为:窗体的标题栏及窗的边框体
const int WM_NCMOUSEMOVE = 0xA0;
//当光标在⼀个窗⼝的⾮客户区同时按下⿏标左键时提交此消息
const int WM_NCLBUTTONDOWN = 0xA1;
//当⽤户释放⿏标左键同时光标某个窗⼝在⾮客户区⼗发送此消息
const int WM_NCLBUTTONUP = 0xA2;
//当⽤户双击⿏标左键同时光标某个窗⼝在⾮客户区⼗发送此消息
const int WM_NCLBUTTONDBLCLK = 0xA3;
//当⽤户按下⿏标右键同时光标⼜在窗⼝的⾮客户区时发送此消息
const int WM_NCRBUTTONDOWN = 0xA4;
//当⽤户释放⿏标右键同时光标⼜在窗⼝的⾮客户区时发送此消息
const int WM_NCRBUTTONUP = 0xA5;
//当⽤户双击⿏标右键同时光标某个窗⼝在⾮客户区⼗发送此消息
const int WM_NCRBUTTONDBLCLK = 0xA6;
//当⽤户按下⿏标中键同时光标⼜在窗⼝的⾮客户区时发送此消息
const int WM_NCMBUTTONDOWN = 0xA7;
//当⽤户释放⿏标中键同时光标⼜在窗⼝的⾮客户区时发送此消息
const int WM_NCMBUTTONUP = 0xA8;
//当⽤户双击⿏标中键同时光标⼜在窗⼝的⾮客户区时发送此消息
const int WM_NCMBUTTONDBLCLK = 0xA9;
//WM_KEYDOWN 按下⼀个键
const int WM_KEYDOWN = 0x0100;
//释放⼀个键
const int WM_KEYUP = 0x0101;
//按下某键,并已发出WM_KEYDOWN, WM_KEYUP消息
const int WM_CHAR = 0x102;
/
/当⽤translatemessage函数翻译WM_KEYUP消息时发送此消息给拥有焦点的窗⼝
const int WM_DEADCHAR = 0x103;
//当⽤户按住ALT键同时按下其它键时提交此消息给拥有焦点的窗⼝
const int WM_SYSKEYDOWN = 0x104;
//当⽤户释放⼀个键同时ALT 键还按着时提交此消息给拥有焦点的窗⼝
const int WM_SYSKEYUP = 0x105;
//当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后提交此消息给拥有焦点的窗⼝
const int WM_SYSCHAR = 0x106;
//当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后发送此消息给拥有焦点的窗⼝
const int WM_SYSDEADCHAR = 0x107;
//在⼀个对话框程序被显⽰前发送此消息给它,通常⽤此消息初始化控件和执⾏其它任务
const int WM_INITDIALOG = 0x110;
//当⽤户选择⼀条菜单命令项或当某个控件发送⼀条消息给它的⽗窗⼝,⼀个快捷键被翻译
const int WM_COMMAND = 0x111;
//当⽤户选择窗⼝菜单的⼀条命令或//当⽤户选择最⼤化或最⼩化时那个窗⼝会收到此消息
const int WM_SYSCOMMAND = 0x112;
//发⽣了定时器事件
const int WM_TIMER = 0x113;
//当⼀个窗⼝标准⽔平滚动条产⽣⼀个滚动事件时发送此消息给那个窗⼝,也发送给拥有它的控件
const int WM_HSCROLL = 0x114;
//当⼀个窗⼝标准垂直滚动条产⽣⼀个滚动事件时发送此消息给那个窗⼝也,发送给拥有它的控件
const int WM_VSCROLL = 0x115;
/
/当⼀个菜单将要被激活时发送此消息,它发⽣在⽤户菜单条中的某项或按下某个菜单键,它允许程序在显⽰前更改菜单
const int WM_INITMENU = 0x116;
//当⼀个下拉菜单或⼦菜单将要被激活时发送此消息,它允许程序在它显⽰前更改菜单,⽽不要改变全部
const int WM_INITMENUPOPUP = 0x117;
//当⽤户选择⼀条菜单项时发送此消息给菜单的所有者(⼀般是窗⼝)
const int WM_MENUSELECT = 0x11F;
//当菜单已被激活⽤户按下了某个键(不同于加速键),发送此消息给菜单的所有者
const int WM_MENUCHAR = 0x120;
//当⼀个模态对话框或菜单进⼊空载状态时发送此消息给它的所有者,⼀个模态对话框或菜单进⼊空载状态就是在处理完⼀条或⼏条先前的消息后没有消息它的列队中等待const int WM_ENTERIDLE = 0x121;
//在windows绘制消息框前发送此消息给消息框的所有者窗⼝,通过响应这条消息,所有者窗⼝可以通过使⽤给定的相关显⽰设备的句柄来设置消息框的⽂本和背景颜⾊const int WM_CTLCOLORMSGBOX = 0x132;
//当⼀个编辑型控件将要被绘制时发送此消息给它的⽗窗⼝通过响应这条消息,所有者窗⼝可以通过使⽤给定的相关显⽰设备的句柄来设置编辑框的⽂本和背景颜⾊const int WM_CTLCOLOREDIT = 0x133;
//当⼀个列表框控件将要被绘制前发送此消息给它的⽗窗⼝通过响应这条消息,所有者窗⼝可以通过使⽤给定的相关显⽰设备的句柄来设置列表框的⽂本和背景颜⾊const int WM_CTLCOLORLISTBOX = 0x134;
//当⼀个按钮控件将要被绘制时发送此消息给它的⽗窗⼝通过响应这条消息,所有者窗⼝可以通过使⽤给定的相关显⽰设备的句柄来设置按纽的⽂本和背景颜⾊
const int WM_CTLCOLORBTN = 0x135;
//当⼀个对话框控件将要被绘制前发送此消息给它的⽗窗⼝通过响应这条消息,所有者窗⼝可以通过使⽤给定的相关显⽰设备的句柄来设置对话框的⽂本背景颜⾊
const int WM_CTLCOLORDLG = 0x136;
//当⼀个滚动条控件将要被绘制时发送此消息给它的⽗窗⼝通过响应这条消息,所有者窗⼝可以通过使⽤给定的相关显⽰设备的句柄来设置滚动条的背景颜⾊
const int WM_CTLCOLORSCROLLBAR = 0x137;
//当⼀个静态控件将要被绘制时发送此消息给它的⽗窗⼝通过响应这条消息,所有者窗⼝可以通过使⽤给定的相关显⽰设备的句柄来设置静态控件的⽂本和背景颜⾊const int WM_CTLCOLORSTATIC = 0x138;
//当⿏标轮⼦转动时发送此消息个当前有焦点的控件
const int WM_MOUSEWHEEL = 0x20A;
//双击⿏标中键
const int WM_MBUTTONDBLCLK = 0x209;
//释放⿏标中键
const int WM_MBUTTONUP = 0x208;
/
/移动⿏标时发⽣,同WM_MOUSEFIRST
const int WM_MOUSEMOVE = 0x200;
//按下⿏标左键
const int WM_LBUTTONDOWN = 0x201;
//释放⿏标左键
const int WM_LBUTTONUP = 0x202;
//双击⿏标左键
const int WM_LBUTTONDBLCLK = 0x203;
//按下⿏标右键
//释放⿏标右键
const int WM_RBUTTONUP = 0x205;
/
/双击⿏标右键
const int WM_RBUTTONDBLCLK = 0x206;
//按下⿏标中键
const int WM_MBUTTONDOWN = 0x207;
const int WM_USER = 0x0400;
const int MK_LBUTTON = 0x0001;
const int MK_RBUTTON = 0x0002;
const int MK_SHIFT = 0x0004;
const int MK_CONTROL = 0x0008;
const int MK_MBUTTON = 0x0010;
const int MK_XBUTTON1 = 0x0020;
const int MK_XBUTTON2 = 0x0040;
消息统⼀采⽤4位16进制的数。
系统消息使⽤的是0x0100(WM_KEYDOWN);0x0000--0x0400是系统⾃定义的消息,其中0x0000为WM_NULL,0x0400为WM_USER。0x0400以后的数值我们可以作为⾃定义的消息值。
⾃定义消息,需要下⾯⼏个步骤:
1、定义消息
public const int USER = 0x0400;
在C#中就可以做对应的声明:
public const int WM_TEST = USER+101;
2、发送消息
消息发送是通过windows提供的API函数SendMessage来实现的,它的原型定义:
[DllImport("User32.dll",EntryPoint="SendMessage")]
private static extern int SendMessage(
IntPtr hWnd, // handle to destination window
uint Msg, // message
uint wParam, // first message parameter
uint lParam // second message parameter
);
3、消息接收
消息发出之后,在Form中如何接收呢?我们可以重载DefWinproc函数来接收消息。
protected override void DefWndProc ( ref System.Windows.Forms.Message m )
{
switch(m.Msg)
{
case Message.WM_TEST: //处理消息
break;
default:
base.DefWndProc(ref m);//调⽤基类函数处理⾮⾃定义消息。
break;
}
}
⽰例应⽤
1、定义消息
我们在⼯程中添加⼀个Message类⽤来定义消息。然后添加了三个成员变量,其中USER为⾃定义消息
的初始值,相当与MFC中的WM_USER。WM_TEST为⾃定义的⽤来响应应⽤程序的消息,WM_MSG为⾃定义的⽤来响应DLL传递过来的消息。如何在DLL定义消息请参考⽂章:。
public class Message
{
public const int USER = 0x0400;
public const int WM_TEST = USER+101;
public const int WM_MSG = USER+102;
进程间通信实验总结}
2、声明引⽤函数
在使⽤消息的地⽅,申明引⽤的函数,我们这⾥在MsgForm.cs⽂件中申明:
[DllImport("User32.dll",EntryPoint="SendMessage")]
private static extern int SendMessage(
IntPtr hWnd, // handle to destination window
uint Msg, // message
uint wParam, // first message parameter
uint lParam // second message parameter
);
//申明DLL中启动消息函数
[DllImport("MessageDLL.dll",EntryPoint="StartSendMessage")]
private extern static void StartSendMessage(IntPtr hWnd);
3、处理系统消息
protected override void OnPaint ( System.Windows.Forms.PaintEventArgs e )
{
/
//定义字体:⿊体,⼤⼩:28
Font font = new Font("⿊体",28);
///创建蓝⾊画笔
SolidBrush bluepen = new SolidBrush(Color.Blue);
///创建⿊⾊画笔
SolidBrush blackpen = new SolidBrush(Color.FromArgb(0xa0,0xa0,0xb0));
///写字符串
e.Graphics.DrawString("VC知识库",font,blackpen,65,25);
///偏移4个象素⽤不同的颜⾊再写⼀次,达到⽴体效果
e.Graphics.DrawString("VC知识库",font,bluepen,61,21);
}
4、触发⾃定义消息
//测试应⽤程序消息
private void TestAppbutton_Click(object sender, System.EventArgs e)
{
SendMessage(this.Handle,Message.WM_TEST,100,200);
}
//测试DLL消息
private void TestDLLbutton_Click(object sender, System.EventArgs e)
{
StartSendMessage(this.Handle);
}
5、响应和处理⾃定义消息
protected override void DefWndProc ( ref System.Windows.Forms.Message m )
{
string message;
switch(m.Msg)
{
case Message.WM_TEST://处理消息
message = string.Format("收到从应⽤程序发出的消息!参数为:{0},{1}",m.WParam,m.LParam); MessageBox.Show(message);///显⽰⼀个消息框
break;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论