SendMessage向窗口或控件发送文本、按键、鼠标事件等消息
SendMessage的定义如下,用于向窗口句柄发送系统定义的消息,以及额外的数据。
LRESULT SendMessage(
[in] HWND hWnd,
[in] UINT Msg,
[in] WPARAM wParam,
[in] LPARAM lParam
);
SendMessage向窗口发送消息事件
向窗口发送文字(输入文字)
WM_SETTEXT = 0x000C
表示发送文字消息,第4个参数表示文字内容。
/// <summary>
/// 发送文本到窗口句柄(或控件)
/// </summary>
/// <param name="hWnd"></param>
/// <param name="text"></param>
public static void SendText(IntPtr hWnd, string text)
{
SendMessage(hWnd, WM_SETTEXT, IntPtr.Zero, text);
}
const int WM_SETTEXT = 0x000C;
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
我们通过帮助类项Winform的TextBox控件发送文本测试:
var wndHandle = WndHelper.FindWindow(null, "Form测试窗体的标题栏");
if (wndHandle != IntPtr.Zero)
{
IntPtr txtHandle = WndHelper.FindWindowEx(wndHandle, IntPtr.Zero, null, "");
if (txtHandle != IntPtr.Zero)
{
WndHelper.SendText(txtHandle,"我是文字");
}
}
这个时候,如果有两个TextBox控件,则永远只会获取某一个(最后一个添加到窗体的TextBox),因此,只会向此控件发送消息文本。
这个时候,就需要通过遍历的方式获取到其他控件了。
向窗口发送键盘按键、发送回车键
/// <summary>
/// 发送回车键(Enter)到窗口(或控件)
/// </summary>
/// <param name="hWnd"></param>
public static void SendEnter(IntPtr hWnd)
{
SendMessage(hWnd, WM_CHAR, VK_ENTER, 0);
}
/// <summary>
/// 发送键盘按键到窗口(或控件)
/// </summary>
/// <param name="hWnd"></param>
/// <param name="keyValue">按键的数字值KeyValue</param>
public static void SendKey(IntPtr hWnd, uint keyValue)
{
SendMessage(hWnd, WM_CHAR, keyValue, 0);
}
const int WM_CHAR = 0x0102;
const uint VK_ENTER = 0x0D; // 13 Enter键
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, uint Msg, uint wParam, uint lParam);
结合第四个参数可以发送组合按键。
比如,发送字母A的按键:
WndHelper.SendKey(txtHandle, 65); // 发送字母A
发送回车
WndHelper.SendEnter(txtHandle);
关于键盘输入更多的内容参见 Using Keyboard Input
向窗口发送鼠标事件
前面的代码中已经有使用SendClick
发送鼠标事件的代码,下面对此进行下介绍。
- 发送Click点击事件
/// <summary>
/// 发送点击事件
/// </summary>
/// <param name="hwnd">控件句柄</param>
public static void SendClick(IntPtr hwnd)
{
SendMessage(hwnd, WM_CLICK, 0, 0);
}
/// <summary>
/// 发送点击事件
/// </summary>
/// <param name="hwnd">控件句柄</param>
/// <param name="x">鼠标位置x</param>
/// <param name="y">鼠标位置y</param>
public static void SendClick(IntPtr hwnd, int X, int Y)
{
int lparm = (Y << 16) + X;
SendMessage(hwnd, WM_CLICK, 0, lparm);
}
[DllImport("user32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
/// <summary>
/// 点击消息
/// </summary>
const uint WM_CLICK = 0xF5;
直接调用SendClick
方法即可。
- 发送鼠标按下、抬起事件,模拟点击
/// <summary>
/// 发送鼠标点击事件,包含MouseDown和MouseUp
/// </summary>
/// <param name="hwnd">控件句柄</param>
/// <param name="x">鼠标位置x</param>
/// <param name="y">鼠标位置y</param>
public static void SendMouseClick(IntPtr hwnd, int X, int Y)
{
int lparm = (Y << 16) + X;
int lngResult = SendMessage(hwnd, WM_LBUTTONDOWN, 0, lparm);
int lngResult2 = SendMessage(hwnd, WM_LBUTTONUP, 0, lparm);
}
/// <summary>
/// 鼠标按下
/// </summary>
const uint WM_LBUTTONDOWN = 0x0201;
/// <summary>
/// 鼠标抬起
/// </summary>
const uint WM_LBUTTONUP = 0x0202;
向窗口发送关闭指令
public static void CloseWindow(IntPtr hwnd)
{
SendMessage(hwnd, WM_CLOSE, 0, 0);
}
const int WM_CLOSE = 0x0010;
SendMessage实现在进程间传送数据
SendMessage
的另一个巧妙的作用是实现跨窗体,或跨进程间的数据传递,当然,在传递时需要在对应的窗口处理函数WndProc
中进行数据的获取。
对于Winform,即需要重写WndProc
函数接受数据传递。
对于同一进程内的不同窗体间的数据传递,理论上,SendMessage可以使用任何消息传递额外数据(应该是不会产生额外操作的消息);
但是对于跨进程间的数据传递,则需要使用WM_COPYDATA = 0x004A
消息类型实现,它用于传递只读数据。
更具体的介绍参见后续的文章。
SendMessage和PostMessage函数【更推荐PostMessage】
SendMessage
用于向Windows或窗口发送特定的消息,SendMessage
会调用窗口处理程序,并且直到窗口处理程序处理完消息才会返回。
所以,SendMessage
发送消息会阻塞当前线程的执行,直到消息处理完成,这一点需要特别注意。
PostMessage
和SendMessage
的作用一样,但是PostMessage
是将消息发送到创建窗口的线程关联的消息队列中,并立即返回,不会等到消息处理完成。
PostMessage
相当于异步发送消息,不会阻塞等待。
在多线程应用中推荐使用PostMessage
,可以在各自创建的窗口间进行安全的通信,非常有用。
另外的想要发送消息,并立即返回,可以参考SendMessageCallback 或 SendNotifyMessage。
而PostMessage 或 PostThreadMessage 函数则是发送到线程消息队列,并立即返回。
关于SendMessage和PostMessage的返回
SendMessage
的返回表示消息处理的结果、消息处理后的返回值,由于无法控制另一个窗体内的消息处理,实际获取的结果作用并不大。可以作为消息是否正确处理完成的参考。
PostMessage
返回表示是否发送成功,是一个bool值。但并不能决定何时执行、是否执行,只是成功发送到了消息队列中。
扩展 The difference between SendMessage and PostMessage
SendMessage发送的消息和系统定义的消息类型(消息列表)
参见官方文档Windows消息和消息队列