我有一个应用程序需要将击键发送到另一个进程。使用user32.dll中定义的PostMessage函数,我的成功有限。我可以发送正常的击键,但不能发送带有修饰符的击键(例如 ALT、CTRL)。
让我告诉你我现在有什么......
常数:
public const ushort WM_KEYDOWN = 0x0100;
public const ushort WM_KEYUP = 0x0101;
public const ushort WM_SYSKEYDOWN = 0x0104;
public const ushort WM_SYSKEYUP = 0x0105;
public const ushort WM_SYSCHAR = 0x0106;
public const ushort VK_MENU = 0x12; // ALT key
DLL 导入:
[DllImport("user32.dll")]
public static extern int PostMessage(IntPtr hWnd, int Msg, uint wParam, int lParam);
发送单个密钥的方法:
public static void PostKey(ushort key, IntPtr hWnd)
{
SetActiveWindow(hWnd);
PostMessage(hWnd, WM_KEYDOWN, key, 0);
PostMessage(hWnd, WM_KEYUP, key, 0);
}
与 ALT 一起发送单个键的方法(不起作用):
public static void PostKeyWithAlt(ushort key, IntPtr hWnd)
{
SetActiveWindow(hWnd);
PostMessage(hWnd, WM_SYSKEYDOWN, VK_MENU, 0);
PostMessage(hWnd, WM_SYSKEYDOWN, key, 0);
PostMessage(hWnd, WM_SYSKEYUP, key, 0);
PostMessage(hWnd, WM_KEYUP, VK_MENU, 0);
}
PostKey完美运行。我能够连接到另一个进程,获取主窗口句柄,并发送我想要的任意键击。
当我尝试使用PostKeyWithAlt时出现问题。这似乎不起作用。(密钥被发送,但不是 ALT,所以它与PostKey基本相同。)我已经用 Google 搜索并尝试了很多方法调用的组合,坦率地说,我已经准备好退出了。:P
因此,无奈之下,我使用 Visual Studio Spy++ 工具来观察当我在目标应用程序中按 ALT+F1 时会发生什么。这是消息捕获的结果:
间谍++日志:
<00001> 00080228 P WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:0 fAltDown:1 fRepeat:0 fUp:0
<00002> 00080228 P WM_SYSKEYDOWN nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:0 fUp:0
<00003> 00080228 P WM_SYSKEYUP nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:1 fUp:1
<00004> 00080228 P WM_KEYUP nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:0 fAltDown:0 fRepeat:1 fUp:1
如您所见,该序列与我的PostKeyWithAlt函数的序列完全相同。所以我认为它会起作用,但事实并非如此。
这里一定有其他事情发生。我唯一能想到的是PostMessage函数的第四个参数。根据 Microsoft 文档,第 4 个参数定义为LPARAM lParam (请参阅下面的PostMessage的完整函数定义)。
也许我需要将lParam设置为 0 以外的值?如果是这样,我需要设置什么值?我可以使用 Spy++ 日志来解决这个问题吗?如果是这样,我无法解释这些日志消息中 _nVirtKey:VK_MENU_ 之后的任何内容:
<00001>.... cRepeat:1 ScanCode:38 fExtended:0 fAltDown:1 fRepeat:0 fUp:0
<00002>.... cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:0 fUp:0
<00003>.... cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:1 fUp:1
<00004>.... cRepeat:1 ScanCode:38 fExtended:0 fAltDown:0 fRepeat:1 fUp:1
如果我可以将上面的日志消息转换为正确的lParam参数,它可能会起作用。
任何有关如何执行此操作的帮助/建议将不胜感激。
或者,是否有另一种更优雅的方式将击键发送到进程?也许是一个 C# 库?我知道SendKeys类,但该类不会将击键发送到其他应用程序。
谢谢!
PostMessage 函数定义:
BOOL WINAPI PostMessage(
_In_opt_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);