C#替代类/库使用PostMessage(user32.dll)发送击键?

时间:2012-08-21 05:46:40

标签: c# process send keystrokes

我有一个需要将键击发送到另一个进程的应用程序。我使用 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 函数的第4个参数。根据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
);

0 个答案:

没有答案
相关问题