Как отправить комбинации клавиш Ctrl/Shift / Alt + в окно приложения? (через метод SendMessage)

Я могу успешно отправить любое ключевое сообщение в приложение, но я не знаю, как отправлять комбинации клавиш (например, Ctrl+F12, Shift+F1, Ctrl+R, etc..)

попробовал сделать это так:

SendMessage(handle, WM_KEYDOWN, Keys.Control, 0);
SendMessage(handle, WM_KEYDOWN, Keys.F12, 0);
SendMessage(handle, WM_KEYUP, Keys.F12, 0);
SendMessage(handle, WM_KEYUP, Keys.Control, 0);

но это, похоже, не работает (приложение действует только как F12 нажата, а не Ctrl+F12).

любой идеи, как это сделать?

5 ответов


вы, вероятно, найдете, что с помощью SendInput (документация здесь) работает намного лучше. Вам нужно будет P / вызвать его из C#,пример. Вы можете предоставить массивы данных с ключами вниз и вверх и правильно установить другие параметры сообщения, например, влево или вправо Ctrl/Shift/Alt.

вы также можете использовать SendKeys класса (документации). Этот позволяет указать ключи по имени, например,{^F12} на Ctrl+F12.

редактировать: ОП теперь говорит, что ему нужно отправить входные данные в свернутые приложения без их активации. Это невозможно сделать надежно в в любом случае, в том числе даже со специализированным оборудованием. Я работал в области автоматизации. Это просто невозможно. OP должен использовать FindWindow/SetForegroundWindow для переключения целевого приложения, а затем он может переключиться обратно на его заявление.


Я уже пробовал метод с GetKeyboardState и SetKeyboardState (перед прикреплением потока окна и заканчивался отсоединением от потока окна). Я не работаю для комбинаций клавиш, таких как Ctrl+что-то или комбинации с использованием Alt или Shift. Клавиши Control, Alt и Shift не отображаются как нажатые. Похоже, максимум, который вы можете получить, когда окно свернуто, - это нажатие отдельных клавиш с помощью PostMessage с сообщениями WM_KEYDOWN. Еще я заметил, что если ты Сообщение WM_KEYDOWN и WM_KEYUP (для той же клавиши) клавиша будет нажата дважды. Поэтому используйте WM_KEYDOWN только один раз. Это не 100% точный метод, но когда окно свернуто, есть некоторые ограничения.

такая же ситуация происходит, когда экран заблокирован.


ОП теперь говорит, что ему нужно отправить входные данные в свернутые приложения не активируя их. Это невозможно сделать надежно в любом способ, в том числе даже со специализированным оборудованием. Я работал в автоматизация. Это просто невозможно.

отправка ввода в свернутые приложения, на самом деле, возможно, не уверен о вводе мыши, но ввод клавиатуры работает просто отлично. Принимая идею в предыдущем ответе вот что я смог добиться (код в Delphi, но это довольно просто, поэтому вы можете перевести его на нужный вам язык):

procedure SendKeys(const Win : HWND; const Key,sKey: Cardinal);
var
  thrID : Cardinal;
  KB : TKeyBoardState;
begin
  if sKey <> 0 then
  begin
    thrID := GetWindowThreadProcessId(win,nil);
    GetKeyboardState(KB);
    AttachThreadInput(GetCurrentThreadID, thrID, True);
    KB[sKey] := KB[sKey] or ;
    SetKeyboardState(KB);
  end;
  SendMessage(Win,WM_KEYDOWN,Key,0);
  SendMessage(Win,WM_KEYUP,Key,0);
  if sKey <> 0 then
  begin
    KB[sKey] := 0;
    SetKeyBoardState(KB);
    AttachThreadInput(GetCurrentThreadId, thrID, False);
  end;
end;

[Win] должен быть элементом управления для получения ввода, а не его родительской формы и т. д. [Ключ] ключ к быть нажата; [sKey] - это альтернативная клавиша, которую нужно нажимать при нажатии [Key], например CTRL/SHIFT (ALT передается через само сообщение, см. ссылку MSDN WM_KEYDOWN).

отправка единственного нажатия клавиши довольно проста, вы просто делаете sendmessage, и это сделано, но если вы нужно что-то вроде CTRL+SPACE вот где все усложняется. Каждый поток имеет свое собственное KeyboardState, изменение KeyboardState в вашем собственном приложении не повлияет на другое, если вы не присоединитесь к их входам потока с помощью функции AttachThreadInput. Когда приложение обрабатывает сообщение WM_KEYDOWN, оно также проверяет текущие состояния сдвига (CTRL / SHIFT), вызывая функцию GetKeyboardState (клавиша ALT может быть отправлена через дополнительный параметр сообщения WM_KEYDOWN), и именно тогда ввод вложенного потока входит играть.


может быть, вы ищете что-то вроде этого:

procedure GoCursorUp(Obj: TControl);
var   KeyState : TKeyboardState;
begin
  GetKeyboardState(KeyState);
  KeyState[VK_CONTROL] := KeyState[VK_CONTROL] or ;
  SetKeyboardState(KeyState);// control down
  Obj.Perform(WM_KEYDOWN,VK_HOME,0); //ex. with HOME key
  KeyState[VK_CONTROL] := ;
  SetKeyboardState(KeyState);// control up
end;

...

GoCursorUp (Self);

или что-то вроде этого:

  //for example: SHIFT + TAB
  keybd_event(VK_SHIFT, 0, 0, 0);
  keybd_event(VK_TAB, 0, 0, 0);
  keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);

Если вы хотите имитировать нажатия клавиш для минимизации окон, вы можете сделать что-то вроде этого:

uint windowThreadId = GetWindowThreadProcessId(hwnd, IntPtr.Zero);
uint myThreadId = GetCurrentThreadId();
AttachThreadInput(myThreadId, windowThreadId, true);

следующий шаг-использовать GetKeyboardState функция для извлечения массива всех состояний ключей потока окна. Измените состояние клавиш SHIFT, CTRL или ALT на нажатие с помощью их виртуальных кодов клавиш. Затем вызовите SetKeyboardState для применения этих состояний. Нажмите клавишу F12:

SendMessage(hwnd, WM_KEYDOWN, Keys.F12, 0);
SendMessage(hwnd, WM_KEYUP, Keys.F12, 0);

изменить обратно состояния клавиш SHIFT, CTRL или ALT как выпущенный. Снова звонок SetKeyboardState. Наконец, отсоедините от окна поток:

AttachThreadInput(myThreadId, windowThreadId, false);