用于创建 unicode 字符的 SendInput 序列失败

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    }\n
Run 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");\n
Run Code Online (Sandbox Code Playgroud)\n