C# 使用直接输入向游戏发送按键

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/409886/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:16:11  来源:igfitidea点击:

Send Key Strokes to Games using Direct Input

c#

提问by Ibrahim AKGUN

I can send any windows application key strokes with PostMessageapi. But I can't send key strokes to Game window by using PostMessage.

我可以使用PostMessageapi发送任何 Windows 应用程序按键。但我无法使用PostMessage.

Anyone know anything about using Direct Input functions for sending keys to games from C#.

任何人都知道使用直接输入函数从 C# 向游戏发送键。

采纳答案by Adrian

An alternate way would be to hook the DirectInput API directly - Microsoft Research has provided a library to do this already: http://research.microsoft.com/en-us/projects/detours/

另一种方法是直接挂钩 DirectInput API - Microsoft Research 已经提供了一个库来执行此操作:http: //research.microsoft.com/en-us/projects/detours/

Once you hook into the API, you can do whatever you want with it. However, it's worth noting that in recent versions of Windows, DirectInput for mouse & keyboard input is just a wrapper around the Win32 windows messages. DirectInput spawns a thread in the background and simply intercepts window messages before passing them along back to the application. It's one of the reasons why Microsoft no longer recommends the use of DirectInput - and it means that messaging APIs like PostMessage shouldwork just fine.

一旦你连接到 API,你就可以用它做任何你想做的事。但是,值得注意的是,在最新版本的 Windows 中,用于鼠标和键盘输入的 DirectInput 只是 Win32 Windows 消息的包装器。DirectInput 在后台生成一个线程并在将它们传递回应用程序之前简单地拦截窗口消息。这是 Microsoft 不再推荐使用 DirectInput 的原因之一——这意味着像 PostMessage 这样的消息传递 API应该可以正常工作。

回答by Nils Pipenbrinck

There is now way to do this via the DirectInput API.

现在可以通过 DirectInput API 做到这一点。

The only way to archive the same effect would be to write your own DirectInput COM object which just wraps the normal DirectInput object. Afterwards you can add code to simulate keystrokes. The trick is to replace the Win32 dinput.dll with your version. All games will then load your DLL on startup.

存档相同效果的唯一方法是编写您自己的 DirectInput COM 对象,该对象仅包装普通的 DirectInput 对象。之后,您可以添加代码来模拟击键。诀窍是用您的版本替换 Win32 dinput.dll。所有游戏都将在启动时加载您的 DLL。

I'm afraid that you can't do that from a managed language though. You have to do this with native code as it requirs quite a bit of low level hackery.

不过,恐怕您无法从托管语言中做到这一点。您必须使用本机代码执行此操作,因为它需要相当多的低级黑客。

回答by Radu Simionescu

You can use the unmanaged SendInput function for this. It posts the input on a level lower then DirectInput. It is very important to know what keycodes to send. These can vary between games. If Windows Virtual keycodes don't work for a game, you can try sending DIKEYBOARD constants (like DIKEYBOARD_A etc.) and if it still doesn't work keep trying. Half Life or Counter Strike, for instance, expect ASCII codes as keycodes (it took me a while to figure this out)

您可以为此使用非托管 SendInput 函数。它将输入发布在低于 DirectInput 的级别。知道要发送什么键码非常重要。这些可能因游戏而异。如果 Windows 虚拟键码对游戏不起作用,您可以尝试发送 DIKEYBOARD 常量(如 DIKEYBOARD_A 等),如果仍然不起作用,请继续尝试。例如,Half Life 或 Counter Strike 期望使用 ASCII 代码作为键码(我花了一段时间才弄清楚这一点)

回答by Jason

One alternative, instead of hooking into DirectX, is to use a keyboard driver (this is not SendInput()) to simulate key presses - and event mouse presses.

一种替代方法,而不是连接到 DirectX,是使用键盘驱动程序(这不是 SendInput())来模拟按键 - 和事件鼠标按下。

You can use Oblita's Interception keyboard driver(for Windows 2000 - Windows 7) and the C# library Interception(wraps the keyboard driver to be used in C#).

您可以使用Oblita 的 Interception 键盘驱动程序(适用于 Windows 2000 - Windows 7)和C# 库 Interception(包装要在 C# 中使用的键盘驱动程序)。

With it, you can do cool stuff like:

有了它,你可以做一些很酷的事情,比如:

input.MoveMouseTo(5, 5);
input.MoveMouseBy(25, 25);
input.SendLeftClick();

input.KeyDelay = 1; // See below for explanation; not necessary in non-game apps
input.SendKeys(Keys.Enter);  // Presses the ENTER key down and then up (this constitutes a key press)

// Or you can do the same thing above using these two lines of code
input.SendKeys(Keys.Enter, KeyState.Down);
Thread.Sleep(1); // For use in games, be sure to sleep the thread so the game can capture all events. A lagging game cannot process input quickly, and you so you may have to adjust this to as much as 40 millisecond delay. Outside of a game, a delay of even 0 milliseconds can work (instant key presses).
input.SendKeys(Keys.Enter, KeyState.Up);

input.SendText("hello, I am typing!");

/* All these following characters / numbers / symbols work */
input.SendText("abcdefghijklmnopqrstuvwxyz");
input.SendText("1234567890");
input.SendText("!@#$%^&*()");
input.SendText("[]\;',./");
input.SendText("{}|:\"<>?");

Because the mechanism behind these key presses is a keyboard driver, it's pretty much unrestricted.

因为这些按键背后的机制是键盘驱动程序,所以它几乎不受限制。

回答by Deniz

Worked for a friends Game (Nostale) without probems:

在没有问题的情况下为朋友游戏(Nostale)工作:

Also herea usefull list of Virtual Key Codes

这里还有一个有用的虚拟键代码列表

        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);

        private void button1_Click(object sender, EventArgs e)
        {
            const int WM_SYSKEYDOWN = 0x0104;
            const int VK_SPACE = 0x20;

            IntPtr WindowToFind = FindWindow(null, "WINDOW NAME");

            PostMessage(WindowToFind, WM_SYSKEYDOWN, VK_SPACE, 0);
        }