simulating key press event using SendInput with C#
遵循该线程的建议:区分键盘的真实按键和虚拟按键
我正在尝试创建一个程序,该程序将使用SendInput()方法发送键盘的按键事件。
但是,问题是当我尝试模拟按键事件时-什么也没发生。到目前为止,这是我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | [DllImport("user32.dll")] static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize); [StructLayout(LayoutKind.Sequential)] struct KEYBDINPUT { public short wScan; public int dwFlags; public int time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Explicit)] struct INPUT { [FieldOffset(0)] public int type; [FieldOffset(8)] public KEYBDINPUT ki; //x64 - 8, x32 - 4 } const int KEYEVENTF_DOWN = 0; //key UP const int KEYEVENTF_EXTENDEDKEY = 0x0001; const int KEYEVENTF_KEYUP = 0x0002; //key UP const int KEYEVENTF_UNICODE = 0x0004; const int KEYEVENTF_SCANCODE = 0x0008; // scancode public void Send_Key(short Keycode) { INPUT[] InputData = new INPUT[1]; InputData[0].type = 1; InputData[0].ki.wScan = Keycode; InputData[0].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE; InputData[0].ki.time = 0; InputData[0].ki.dwExtraInfo = IntPtr.Zero; SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT))); } |
要解密扫描代码,我下载了此线程中建议的程序:
https://superuser.com/questions/293609/windows-7-tool-to-capture-keyboard-scan-codes
根据该程序-我键盘的" a"键代码为" 65"
我的程序应该在更改文本框文本时触发按键事件,因此,如果我们输入" q",则文本应更改为" q"加上send_key()的结果,即" qa":
2
3
4
{
Send_Key(0x0065); // nothing happens (0x65 also fails)
}
我在做什么错?将来,我将更改此代码,以便可以指定键保持时间(在DOWN和UP事件之间)。但就目前而言,出于测试目的,我仅模拟keyUP事件。
编辑:汉斯,根据您的建议,这里是编辑-不幸的是,它不起作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public void Send_Key(short Keycode) { INPUT[] InputData = new INPUT[1]; InputData[0].type = 1; InputData[0].ki.wScan = Keycode; InputData[0].ki.dwFlags = KEYEVENTF_DOWN; InputData[0].ki.time = 0; InputData[0].ki.dwExtraInfo = IntPtr.Zero; uint intReturn = SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT))); if (intReturn == 0) //!=1 { throw new Exception("Could not send keyDOWN:" + Keycode); } INPUT[] InputData2 = new INPUT[1]; InputData2[0].type = 1; InputData2[0].ki.wScan = Keycode; InputData2[0].mi.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE; InputData2[0].ki.time = 0; InputData2[0].ki.dwExtraInfo = IntPtr.Zero; uint intReturn2 = SendInput(1, InputData2, Marshal.SizeOf(typeof(INPUT))); if (intReturn2 == 0) //!=1 { throw new Exception("Could not send keyUP:" + Keycode); } } |
没有错误..也没有输出。
but for now, for testing purposes I'm simulating only keyUP event
我猜这没关系,但这不会使Windows做任何事情。要生成击键,必须首先发送KEYDOWN。"保持时间"没有任何有用的作用,因此只需将两个SendInput调用放在同一方法中即可。
您应该添加错误检查,winapi调用不会生成任何异常。如果函数返回0,则引发Win32Exception。并使用SetLastError = true修复[DllImport]声明。
通过设置ki.wVk字段并省略KEYEVENTF_SCANCODE标志,可以避免使用在superuser.com上找到的程序。这样就可以指定虚拟密钥而不是扫描代码。 .NET Keys枚举类型为您提供所需的值。像Keys.A一样,为A键生成一个按键。