我可以成功地将任何单个密钥消息发送到应用程序,但我不知道如何发送密钥组合(例如 Ctrl + F12 , Shift + F1 , Ctrl + R 等。)
尝试这样做:
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 )。
任何想法如何使这项工作?
答案 0 :(得分:5)
您可能会发现使用SendInput (documentation here)效果更好。您需要从C#,example here进行P / Invoke。您可以使用向下和向上键提供数据数组并正确设置其他消息参数,例如是左还是右 Ctrl / Shift / Alt 被压了。
您还可以使用SendKeys
班级(documentation here)。这允许您按名称指定键,例如,{kbd> Ctrl + F12 的{^F12}
。
编辑:OP现在说他需要将输入发送到最小化的应用程序而不激活它们。这不可能以任何方式可靠地执行,包括使用专门的硬件。我从事自动化工作。这是不可能的。 OP需要使用FindWindow
/ SetForegroundWindow
来切换目标应用,然后他可以切换回他的应用。
答案 1 :(得分:3)
OP现在说他需要向最小化的应用程序发送输入 没有激活它们。任何情况都不可能做到这一点 方式,甚至包括专门的硬件。我曾经参与过 自动化。这是不可能的。
事实上,向最小化应用程序发送输入是可能的,不确定鼠标输入,但键盘输入工作正常。 在前面的回答中提出我的想法是什么(代码在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 $80;
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消息时,它还通过调用GetKeyboardState函数来测试当前的移位状态(CTRL / SHIFT)(ALT键可以通过WM_KEYDOWN消息的附加参数发送),并且当附加的线程输入发挥作用时。
答案 2 :(得分:3)
我已经尝试了使用GetKeyboardState和SetKeyboardState的方法(先附加窗口线程,最后从窗口线程中分离)。我不能使用Ctrl + Something等键组合或使用Alt或Shift组合键。 Control,Alt和Shift键不被视为按下。看起来当窗口最小化时可以获得的最大值是使用带有WM_KEYDOWN消息的PostMessage按下单个键。我注意到的另一件事是,如果你发布WM_KEYDOWN和WM_KEYUP(对于相同的键),键将被按两次。所以一次只能使用WM_KEYDOWN。这不是100%准确的方法,但是当窗口最小化时,存在一些限制。
屏幕锁定时会发生同样的情况。
答案 3 :(得分:0)
也许你看起来像这样:
procedure GoCursorUp(Obj: TControl);
var KeyState : TKeyboardState;
begin
GetKeyboardState(KeyState);
KeyState[VK_CONTROL] := KeyState[VK_CONTROL] or $80;
SetKeyboardState(KeyState);// control down
Obj.Perform(WM_KEYDOWN,VK_HOME,0); //ex. with HOME key
KeyState[VK_CONTROL] := $0;
SetKeyboardState(KeyState);// control up
end;
...
GoCursorUp(自拍);
或类似的东西:
//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);
答案 4 :(得分: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);