0 c# keyboard unicode localization keyboard-events
我正在使用需要将击键发送到第三方应用程序的屏幕键盘。它们在 Windows XP 上运行。需要支持美国英语键盘上不可用的一小组字符(例如“\xc3\xa5”或\xc3\xb1)。在查看 SendInput 后,似乎最安全的事情是将字符的十六进制 unicode 值作为击键序列发送。我编写的代码发送“Alt”和“Add”按键按下事件,然后发送与 Alt 键 ORed 的四字符 unicode 序列的按键按下和向上事件,最后发送“Add”和“Alt”按键按下事件。在我的 C# 测试应用程序中。我正在使用 KeyPreview,果然,所有事件都会通过,但我得到的只是一声蜂鸣声,没有字符。我通过手动输入击键捕获了相同的信息,KeyPreview 信息相同,并且出现了字符。
\n\n可以这样使用SendInput吗?我没有使用钩子来检查数据,但我看到帖子表明 SendInput 事件附加了某种“注入”标志,也许这会导致序列失败?
\n\n此演示代码成功发送按键事件,但旨在生成 unicode 字符的一系列按键事件失败。
\n\n private const uint KEYEVENTF_KEYDOWN = 0x0000;\n private const uint KEYEVENTF_EXTENDEDKEY = 0x0001;\n private const uint KEYEVENTF_KEYUP = 0x0002;\n\n private const int INPUT_KEYBOARD = 1;\n\n [DllImport ("user32.dll", SetLastError = false)]\n static extern IntPtr GetMessageExtraInfo ();\n\n [DllImport ("user32.dll", SetLastError = true)]\n static extern uint SendInput (uint nInputs, [MarshalAs (UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, int cbSize);\n\n [StructLayout (LayoutKind.Sequential, Size = 24)]\n private struct KEYBDINPUT\n {\n public ushort wVk;\n public ushort wScan;\n public uint dwFlags;\n public uint time;\n public IntPtr dwExtraInfo;\n }\n\n [StructLayout (LayoutKind.Explicit)]\n private struct INPUT\n {\n [FieldOffset (0)]\n public int type;\n [FieldOffset (4)]\n public KEYBDINPUT ki;\n }\n\n private void PressKey (Keys k)\n {\n PressKeyDown (k);\n PressKeyUp (k);\n }\n\n private void PressKeyDown (Keys k)\n {\n INPUT input = new INPUT ();\n input.type = INPUT_KEYBOARD;\n input.ki.wVk = (byte)k;\n input.ki.wScan = 0;\n input.ki.time = 0;\n\n uint flags = KEYEVENTF_KEYDOWN;\n if ((33 <= (byte)k && (byte)k <= 46) || (91 <= (byte)k) && (byte)k <= 93)\n flags |= KEYEVENTF_EXTENDEDKEY;\n input.ki.dwFlags = flags;\n\n input.ki.dwExtraInfo = GetMessageExtraInfo ();\n\n Output ("Sending key down {0}. Flags:{1}", k, flags);\n\n INPUT[] inputs = new INPUT[] { input };\n uint result = SendInput ((uint)inputs.Length, inputs, Marshal.SizeOf (typeof (INPUT)));\n\n if ((uint)inputs.Length != result)\n MessageBox.Show ("PressKeyDown result = " + Marshal.GetLastWin32Error ());\n }\n\n private void PressKeyUp (Keys k)\n {\n INPUT input = new INPUT ();\n input.type = INPUT_KEYBOARD;\n input.ki.wVk = (byte)k;\n input.ki.wScan = 0;\n input.ki.time = 0;\n\n uint flags = KEYEVENTF_KEYUP;\n if ((33 <= (byte)k && (byte)k <= 46) || (91 <= (byte)k) && (byte)k <= 93)\n flags |= KEYEVENTF_EXTENDEDKEY;\n input.ki.dwFlags = flags;\n\n input.ki.dwExtraInfo = GetMessageExtraInfo ();\n\n Output ("Sending key up {0}", k);\n\n INPUT[] inputs = new INPUT[] { input };\n uint result = SendInput ((uint)inputs.Length, inputs, Marshal.SizeOf (typeof (INPUT)));\n\n if ((uint)inputs.Length != result)\n MessageBox.Show ("PressKeyUp result = " + Marshal.GetLastWin32Error ());\n }\n\n private void TestSend ()\n {\n System.Threading.Thread.CurrentThread.Join (1000);\n\n Keys k = Keys.Menu;\n PressKeyDown (k);\n\n System.Threading.Thread.Sleep (100);\n\n k = Keys.Add;\n k |= Keys.Alt;\n PressKeyDown (k);\n\n System.Threading.Thread.Sleep (100);\n\n k = Keys.NumPad0;\n k |= Keys.Alt;\n PressKey (k);\n\n System.Threading.Thread.Sleep (100);\n\n k = Keys.NumPad0;\n k |= Keys.Alt;\n PressKey (k);\n\n System.Threading.Thread.Sleep (100);\n\n k = Keys.E;\n k |= Keys.Alt;\n PressKey (k);\n\n System.Threading.Thread.Sleep (100);\n\n k = Keys.NumPad5;\n k |= Keys.Alt;\n PressKey (k);\n\n System.Threading.Thread.Sleep (100);\n\n PressKeyUp (Keys.Add);\n PressKeyUp (Keys.Menu);\n }\nRun Code Online (Sandbox Code Playgroud)\n
小智 5
using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Runtime.InteropServices;\n\nnamespace Simulate\n{\n public class Simulate\n {\n [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]\n static extern UInt32 SendInput(UInt32 numberOfInputs, INPUT[] input, Int32 sizeOfInputStructure);\n\n [StructLayout(LayoutKind.Sequential, Size = 24)]\n struct KEYBDINPUT\n {\n public UInt16 Vk;\n public UInt16 Scan;\n public UInt32 Flags;\n public UInt32 Time;\n public UInt32 ExtraInfo;\n }\n\n [StructLayout(LayoutKind.Explicit)]\n private struct INPUT\n {\n [FieldOffset(0)]\n public int Type;\n [FieldOffset(4)]\n public KEYBDINPUT ki;\n } \n\n public static void TextInput(string text)\n {\n char[] chars = text.ToCharArray();\n\n for (int i = 0; i < chars.Length; i++)\n {\n UInt16 unicode = chars[i];\n\n INPUT down = new INPUT();\n down.Type = 1; //INPUT_KEYBOARD\n down.ki.Vk = 0;\n down.ki.Scan = unicode;\n down.ki.Time = 0;\n down.ki.Flags = 0x0004; //KEYEVENTF_UNICODE\n down.ki.ExtraInfo = 0;\n\n INPUT up = new INPUT();\n up.Type = 1; //INPUT_KEYBOARD\n up.ki.Vk = 0;\n up.ki.Scan = unicode;\n up.ki.Time = 0;\n up.ki.Flags = 0x0004; //KEYEVENTF_UNICODE\n up.ki.ExtraInfo = 0;\n\n INPUT[] input = new INPUT[2];\n input[0] = down;\n input[1] = up;\n SendInput(1, input, Marshal.SizeOf(typeof(INPUT)));\n }\n }\n }\n}\n\n// Call the API :\nSimulate.TextInput("AbC\xc3\xa7DeFg\xc4\x9eh\xc4\xb0iJkLmNo\xc3\x96pQrS\xc5\x9fTu\xc3\x9cvXyZ - \xc3\xa4\xc3\x84\xc3\x9f_0123456789");\nRun Code Online (Sandbox Code Playgroud)\n