Как отправить комбинации клавиш 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);