使用WinAPI将击键发送到另一个应用程序 [英] Sending Keystroke to another application using WinAPI

查看:99
本文介绍了使用WinAPI将击键发送到另一个应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须通过向其发送击键来控制另一个应用程序,例如 CTRL S CTRL SHIFT C CTRL F

I have to control another application by sending keystrokes to it like CTRLS or CTRLSHIFTC or CTRLF.

我尝试了很多东西,但是我无法正常工作。因此,我试图在一个更简单的情况下解决问题。

I've tried a lot of things, but I can't get it working. So I'm trying to get this right on a simpler case.

此操作成功将发送到记事本:

This successfully sends Hey to the notepad:

procedure TForm1.Button1Click(Sender: TObject);
  var notepad, edit: HWND;
begin
  notepad := FindWindow('notepad', nil);
  edit := FindWindowEx(notepad, FindWindow('Edit', nil), nil, nil);

  SendMessage(edit, WM_CHAR, dword('H'), 0);
  SendMessage(edit, WM_CHAR, dword('e'), 0);
  SendMessage(edit, WM_CHAR, dword('y'), 0);
end;

这成功将 F5 密钥发送到记事本,并且也可以工作使用 F3 弹出查找对话框。

And this successfully sends the F5 key to the notepad, and also works with F3 poping up the Find dialog.

notepad := FindWindow('notepad', nil);
PostMessage(notepad, WM_KEYDOWN, VK_F5, 0);
PostMessage(notepad, WM_KEYUP, VK_F5, 0);

但是我不知道为什么使用 SendMessage 在上面的示例中不起作用。

But I don't know why using SendMessage doesn't work on the exemple above.

我能想到的最好的事情是这样的,什么都不做。

The best thing I could came up was something like this, which does nothing.

notepad := FindWindow('notepad', nil);
PostMessage(notepad, WM_KEYDOWN, VK_CONTROL, 0);
PostMessage(notepad, WM_KEYDOWN, VkKeyScan('F'), 0);
PostMessage(notepad, WM_KEYUP, VkKeyScan('F'), 0);
PostMessage(notepad, WM_KEYUP, VK_CONTROL, 0);

我在这里的某个地方找到了一个可以模仿VBScript发送关键功能的库,但是代码,由于没有Handle参数,它似乎只是广播当前应用程序或所有应用程序的密钥。

I've found somewhere here a library which kinda emulate the VBScript send key functions, but just looking the code, it seems to just broadcast keys to the current application or all applications, since there's no Handle parameter.

推荐答案

警告:此方法取决于实现细节,如果需要保证程序的正确性,则不应使用此方法。(另一方面,您已经在那条路上了。对于例如IIRC,在Windows 95中甚至没有转到对话框。)

Warning: This method depends on implementation details, and should not be used if you need to guarantee the correctness of your program. (On the other hand, you are already on that path. For instance, IIRC, in Windows 95 there isn't even a Go to dialog.)

我打开了 notepad.exe 在我最喜欢的资源编辑器中,并研究了菜单栏。我注意到保存菜单项的ID为 3 。因此,以下代码在记事本中执行 Save 菜单命令:

I opened notepad.exe in my favourite Resource Editor, and investigated the menu bar. I noticed that the ID of the Save menu item is 3. Hence, the following code executes the Save menu command in notepad:

var
  notepad: HWND;
begin
  notepad := FindWindow('notepad', nil);

  SendMessage(notepad, WM_COMMAND, 3, 0);

类似地,查找 21 在我的 notepad.exe 版本中。 转到 24

Similarly, Find is 21 in my version of notepad.exe. Go to is 24.

更新,根据评论::如果您需要发送 Ctrl + Key ,则可以使用 SendInput

Update, according to comment: If you need to send Ctrl+Key, you can use SendInput:

var
  notepad: HWND;
  inputArray: array[0..3] of TInput;
begin
  notepad := FindWindow('notepad', nil);

  // TODO: Either exit if notepad isn't focused, or set focus to notepad

  FillChar(inputArray, length(inputArray) * sizeof(TInput), 0);

  inputArray[0].Itype := INPUT_KEYBOARD;
  inputArray[0].ki.wVk := VK_LCONTROL;
  inputArray[1].Itype := INPUT_KEYBOARD;
  inputArray[1].ki.wVk := VkKeyScan('S');
  inputArray[2].Itype := INPUT_KEYBOARD;
  inputArray[2].ki.wVk := VkKeyScan('S');
  inputArray[2].ki.dwFlags := KEYEVENTF_KEYUP;
  inputArray[3].Itype := INPUT_KEYBOARD;
  inputArray[3].ki.wVk := VK_LCONTROL;
  inputArray[3].ki.dwFlags := KEYEVENTF_KEYUP;

  SendInput(length(inputArray), inputArray[0], sizeof(TInput));

这篇关于使用WinAPI将击键发送到另一个应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆