Jas*_*son 16 c# directinput sendinput
我正在尝试为自定义游戏控制器应用程序模拟键盘命令.因为我需要在DirectInput环境中模拟命令,所以大多数常用方法都不起作用.我知道使用一个钩子可以100%工作,但我试图找到一个更容易的实现.
我已经做了很多搜索,发现通过使用带有扫描码的SendInput API而不是虚拟键应该可以工作,但它似乎表现得像键是"坚持".我已经发送了KEYDOWN和KEYUP事件,但是当我尝试在DirectInput环境中发送消息时,游戏就像按下键一样.
例如,如果我模拟"W"按键并将该键映射到第一人称射击游戏中以"向前移动"动作,那么一旦我在游戏中,下面的功能将导致角色向前移动.但是,只需发出一次命令,它就会无限地向前移动角色.
这是我正在调用的SendInput函数的代码片段(在C#中):
[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());
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定这种方法是否是一个失败的原因,或者是否有一些愚蠢的东西我不知道.如果我不需要使用钩子,我讨厌使代码复杂化,但这对我来说也是一个新的领域.
任何人都可以给予任何帮助非常感谢.
谢谢!
Jas*_*son 22
我找到了解决自己问题的方法.所以,我想我会在这里发帖,以帮助将来可能遇到类似问题的人.
keyup命令无法正常工作,因为当只发送扫描代码时,密钥必须与扫描代码标志进行"或"运算(有效地启用两个标志),以告诉SendInput()API这是一个KEYUP和一个SCANCODE命令.
例如,以下代码将正确发出扫描代码键:
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)))
Run Code Online (Sandbox Code Playgroud)
感谢Hans的回应.我做了一些调查并发送两条消息,就像最初的例子确实模拟了一个"按键",但速度非常快.它对于移动命令不会很好,但是当动作键被"轻敲"而不是按下时,它将是理想的.
此外,发送扫描代码时会忽略虚拟键字段.MSDN对此主题有以下说法:
"设置KEYEVENTF_SCANCODE标志以根据扫描代码定义键盘输入.这对于模拟物理击键非常有用,无论当前使用哪个键盘.键的虚拟键值可能会根据当前键盘布局或什么而改变按下了其他键,但扫描码总是一样的."
http://msdn.microsoft.com/en-us/library/ms646271%28v=VS.85%29.aspx