С# Альтернативный класс/библиотека для использования 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.) Я погуглил и перепробовал так много комбинаций вызовов методов, что, честно говоря, готов назвать это выходом. :П

Итак, в отчаянии я воспользовался инструментом 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 этот четвертый параметр определяется как 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, это могло бы сработать.

Любая помощь/предложения о том, как это сделать, будет принята с благодарностью.

В качестве альтернативы, есть ли другой более элегантный способ отправки нажатий клавиш процессу? Возможно, библиотека С#? Я знаю о классе SendKeys, но этот класс не отправляет нажатия клавиш другим приложениям.

Спасибо!

Определение функции PostMessage:

BOOL WINAPI PostMessage(
  _In_opt_  HWND hWnd,
  _In_      UINT Msg,
  _In_      WPARAM wParam,
  _In_      LPARAM lParam
);

person Jan Tacci    schedule 21.08.2012    source источник
comment
Не надейтесь, но, возможно, API Monitor будет полезен...   -  person user541686    schedule 21.08.2012
comment
Никогда не пробовал API Monitor. Изучу прямо сейчас. Спасибо!   -  person Jan Tacci    schedule 21.08.2012
comment
также взгляните сюда: stackoverflow.com/questions/11384669 /   -  person JleruOHeP    schedule 21.08.2012