C# Альтернативный класс / библиотека для использования PostMessage (user32.dll) для отправки нажатий клавиш?
У меня есть приложение, которое должно отправлять нажатия клавиш другому процессу. У меня был ограниченный успех с использованием функции PostMessage, определенной в user32.dll. Я могу отправлять обычные нажатия клавиш, но не могу отправлять нажатия клавиш с модификаторами (например, 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 и попробовал так много комбинаций вызовов методов, что, честно говоря, готов вызвать его.:П
Поэтому в отчаянии я использовал инструмент Visual Studio Spy++, чтобы посмотреть, что произойдет, когда я нажму ALT+F1 в целевом приложении. Вот результат захвата сообщения:
Spy ++ Log:
<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. Так что я думаю, что это будет работать, но это не так.
Здесь должно быть что-то еще. Единственное, о чем я могу думать, это 4-й параметр функции 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
);