模拟键盘与DirectInput的应用程序API SendInput [英] Simulating Keyboard with SendInput API in DirectInput applications

查看:1396
本文介绍了模拟键盘与DirectInput的应用程序API SendInput的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图模拟一个自定义游戏控制器应用程序的键盘命令。因为我需要在DirectInput的环境中模拟命令大部分常用的方法不起作用。我知道,用钩子将工作100%,但我试图找到一个更容易实现。

I'm trying to simulate keyboard commands for a custom game controller application. Because I'll need to simulate commands in a DirectInput environment most of the usual methods don't work. I know that using a hook would work 100% but I'm trying to find an easier implementation.

我已经做了相当多的搜索后发现,通过使用扫描codeS的SendInput API而不是虚拟按键应该工作,但它似乎表现得像关键的是坚持。我送两个KEYDOWN和KeyUp事件,但是当我试图在DirectInput的环境中发送的消息,本场比赛作为如果该键被按下。

I've done quite a bit of searching and found that by using the SendInput API with Scancodes instead of virtual keys should work, but it seems to behave like the key's are "sticking". I've sent both the KEYDOWN and KEYUP events but when I attempt to send the message in a DirectInput environment, the game acts as if the key is being held down.

举例来说,如果我模拟一个W键preSS并在第一人称射击游戏映射到前进的动作是关键,有一次我在游戏中是,以下的功能会造成字符前进。然而,仅仅通过一次发出命令,它会无限期地向前移动的字符。

For instance, if I simulate a "W" keypress and have that key mapped in a First Person Shooter to the "move forward" action, once I'm in game, the function below will cause the character to move forward. However, just by issuing the command once, it will move the character forward indefinitely.

下面是一个code段(在C#)为SendInput功能我打电话:

Here is a code snippet (in C#) for the SendInput function I'm calling:

[DllImport("user32.dll")]
static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize);

public static void Test_KeyDown()
{
    INPUT[] InputData = new INPUT[2];
    Key ScanCode = Microsoft.DirectX.DirectInput.Key.W;

    InputData[0].type = 1; //INPUT_KEYBOARD
    InputData[0].wScan = (ushort)ScanCode;
    InputData[0].dwFlags = (uint)SendInputFlags.KEYEVENTF_SCANCODE;

    InputData[1].type = 1; //INPUT_KEYBOARD
    InputData[1].wScan = (ushort)ScanCode;
    InputData[1].dwFlags = (uint)(SendInputFlags.KEYEVENTF_KEYUP | SendInputFlags.KEYEVENTF_UNICODE);

    // send keydown
    if (SendInput(2, InputData, Marshal.SizeOf(InputData[1])) == 0)
    {
        System.Diagnostics.Debug.WriteLine("SendInput failed with code: " +
        Marshal.GetLastWin32Error().ToString());
    }
}

我不知道,如果这方法是一个失败的事业,或者如果有只是一些无聊的我失踪。我讨厌过度,如果我没有使用钩子复杂我code,而这也是新的领域对我来说。

I'm not sure if this method is a lost cause, or if there is just something silly I'm missing. I hate to over complicate my code if I don't have to by using hooks, but this is also new territory for me.

任何帮助任何人都可以给很多AP preciated。

Any help anyone can give is much appreciated.

谢谢!

推荐答案

我已经找到了解决方案,以我自己的问题。所以,我想我会张贴在这里帮人谁可能在将来出现类似的问题。

I've found the solution to my own problem. So, I thought I'd post here to help anyone who may have similar issues in the future.

在keyUp命令不能正常工作,因为当只发送扫描code时,KEYUP必须用扫描code标志(高效地提供对标志)告诉SendInput()API或运算的这是一个既KEYUP和扫描code命令。

The keyup command was not working properly because when only sending the scan code, the keyup must be OR'ed with the scan code flag (effectively enabling both flags) to tell the SendInput() API that this is a both a KEYUP and a SCANCODE command.

例如,下面的code将正常发出扫描code键式:

For instance, the following code will properly issue a scan code key-up:

INPUT[] InputData = new INPUT[1];

InputData[0].Type = (UInt32)InputType.KEYBOARD;
//InputData[0].Vk = (ushort)DirectInputKeyScanCode;  //Virtual key is ignored when sending scan code
InputData[0].Scan = (ushort)DirectInputKeyScanCode;
InputData[0].Flags = (uint)KeyboardFlag.KEYUP | (uint)KeyboardFlag.SCANCODE;
InputData[0].Time = 0;
InputData[0].ExtraInfo = IntPtr.Zero;

// Send Keyup flag "OR"ed with Scancode flag for keyup to work properly
SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)))

感谢汉斯响应。我做了一些调查和发送两个消息背靠背像原来的例子确实模仿键preSS,但它的速度非常快。它不会为某运动命令很好地工作,但是当操作键都被挖,而不是压得将是理想的。

Thanks to Hans for the response. I did some investigating and sending two messages back to back like the original example does indeed simulate a "keypress" but it's very fast. It would not work well for a movement command, but would be ideal when action keys are to be "tapped" and not held down.

此外,发送扫描code当虚拟键字段将被忽略。 MSDN有以下关于这个问题说:

Also, the virtual key field is ignored when sending a scan code. MSDN had the following to say on the subject:

设置KEYEVENTF_SCAN code标志在扫描$ C $的c来定义键盘输入。这是有用的,以模拟物理键击无论哪个键盘的当前正在使用。关键的虚拟键的值可以根据当前的键盘布局还是什么其他按键被pressed改变,但扫描code将永远是相同的。

"Set the KEYEVENTF_SCANCODE flag to define keyboard input in terms of the scan code. This is useful to simulate a physical keystroke regardless of which keyboard is currently being used. The virtual key value of a key may alter depending on the current keyboard layout or what other keys were pressed, but the scan code will always be the same."

<一个href=\"http://msdn.microsoft.com/en-us/library/ms646271%28v=VS.85%29.aspx\">http://msdn.microsoft.com/en-us/library/ms646271%28v=VS.85%29.aspx

这篇关于模拟键盘与DirectInput的应用程序API SendInput的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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