为什么有些应用程序有时不接受某些sendkey [英] Why do some applications not accept some sendkeys at some times

查看:302
本文介绍了为什么有些应用程序有时不接受某些sendkey的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我之前遇到的一个问题,但是我总是放弃解决问题并解决问题.今天(希望如此).

This is an issue I've ran into before, but I've always given up solving the problem and worked out a work around. Not today (hopefully).

我正在尝试为经典的《毁灭战士II》制作机器人.我希望我的机器人可以访问通过转义键访问的主菜单.我自然尝试过:

I'm trying to make a bot for the classic Doom II. I want my bot to have access to the main menu which is accessed via the escape key. Naturally I tried:

sendkeys.send("{ESC}")

没有运气.但是随后发生了一些奇怪的事情.当我已经在菜单上时,我不小心运行了代码...并且它关闭了菜单(如果在菜单上按Escape键,这是正常的).显然,《毁灭战士2》监听了Sendkeys.

No luck. But then something weird happened. I accidently ran the code when I was already on the menu... and it closed the menu (which is normal if you press escape on the menu). So clearly Doom II listens to Sendkeys.

此后,我尝试了sendinput,postmessage和Simulationinput.没有一个起作用(它们都具有与sendkeys所述相同的行为).

I've since tried sendinput, postmessage, and simulateinput. None have worked (they all have the same behaviour as described with sendkeys).

如果有人可以骑白马并给我代码解决这个问题,那就太好了,但是除此之外,任何人都可以向我简单地解释这种行为吗?

It would be great if someone could ride in on a white horse and give me code to get around this issue, but outside of that can any one simply explain this behaviour to me?

推荐答案

Zandronum似乎不接受游戏运行(未暂停)时要发送给它的虚拟键.我不确定,但似乎虚拟键实际上可能是窗口消息,就像安德鲁·莫顿(Andrew Morton)所说的那样(或者它们至少是类似的东西……).解决方法是发送 硬件扫描代码 ,而不是 虚拟键码 .

It seems that Zandronum does not accept virtual keys to be sent to it when the game is running (not paused). I'm not sure but it seems that virtual keys might actually be window messages, like Andrew Morton said (or they're at least something similar...). The workaround to this was to send a hardware scan code instead of a virtual key code.

一个硬件扫描代码似乎是实际键盘在按下某个键时发送的代码,而虚拟键代码是系统从键盘上解释出来的键.扫描代码(参考).

A hardware scan code appears to be the code sent by the actual keyboard when pressing a key, while a virtual key code is the key which the system interprets from the scan code (reference).

因此,我设法使用一些WinAPI函数将击键发送到Zandronum(全屏和窗口式):

So I managed to send keystrokes to Zandronum (both fullscreen and windowed) using a few WinAPI functions:

  • SendInput() which is used to send the actual keyboard input.
  • MapVirtualKeyEx() which is used to convert key codes to scan codes, or vice versa.
  • GetKeyboardLayout() which is used to get the user's current keyboard layout (I, for example, have a Swedish keyboard).

通过使用我构建的以下帮助器类(或更正确的方法:包装器),您现在可以以简单的方式发送击键(无论是否为硬件),并且击键的种类比SendKeys.Send()所包含的种类更多.您可以在

By using the below helper class (or more correctly: wrapper) that I built you may now send keystrokes (hardware or not) in a simple manner, with a larger variety of keys than what SendKeys.Send() includes. You may use any key in the System.Windows.Forms.Keys enumeration.

这已通过Zandronum进行了测试,并且可以完全正常工作:

This was tested with Zandronum and works completely:

InputHelper.Keyboard.PressKey(Keys.Escape, True) 'True = Send key as hardware scan code.

编辑(2019-09-20)

InputHelper长期以来一直移到其自己的库中.答案已更新以反映此更改.

InputHelper has since long been moved to its own library. The answer has been updated to reflect this change.

从GitHub下载InputHelper:
https://github.com/Visual-Vincent/InputHelper/releases

Download InputHelper from GitHub:
https://github.com/Visual-Vincent/InputHelper/releases

只是为了好玩,我还设法在MSDN上找到了扫描代码列表: https://msdn.microsoft.com/en-us/library/aa299374(v = vs.60).aspx

Just for fun, I also managed to find a list of scan codes on the MSDN: https://msdn.microsoft.com/en-us/library/aa299374(v=vs.60).aspx

由于我本人是《毁灭战士》的粉丝,并且熟悉它的工作原理,也许您应该(按您的旧问题)还确保已在菜单中选择New Game,然后再按Enter键?

Since I'm a Doom fan myself and familiar with how it works, perhaps you should (per your old question) also make sure that you have selected New Game in the menu before you make it press enter?

Zandronum知道菜单项的名称,因此您只需要给它第一个字母,它就会跳到以它开头的项:

Zandronum is aware of the names of the menu items, so you just have to give it the first letter and it will jump to the item starting with it:

InputHelper.Keyboard.PressKey(Keys.Escape, True) 'Open the menu.
System.Threading.Thread.Sleep(100)      'Small delay to let the menu open.
InputHelper.Keyboard.PressKey(Keys.N, True)      'Jump to the "New Game" menu item.
InputHelper.Keyboard.PressKey(Keys.Enter, True)  'Go into the "New Game" menu.
InputHelper.Keyboard.PressKey(Keys.Enter, True)  'Start a new game.

我已经在全屏模式下在游戏中测试了上述代码.就像魅力一样.

I've tested the above code in-game, running in fullscreen mode. Works like a charm.

这篇关于为什么有些应用程序有时不接受某些sendkey的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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