User32-SendInput模拟数字键盘发送到文本框-32位和64位兼容问题

来源:互联网 发布:鬼吹灯 知乎 编辑:程序博客网 时间:2024/06/05 17:18

原来的Input结构体为如下,导致只能在32位下运行,

using System;using System.Runtime.InteropServices;using System.Drawing;namespace CAXA.MES.ScreenKeyboard {    [StructLayout(LayoutKind.Sequential)]    internal struct MOUSEINPUT {        public int dx;        public int dy;        public int mouseData;        public int dwFlags;        public int time;        public IntPtr dwExtraInfo;    }    [StructLayout(LayoutKind.Sequential)]    internal struct KEYBDINPUT {        public short wVk;        public short wScan;        public int dwFlags;        public int time;        public IntPtr dwExtraInfo;    }    [StructLayout(LayoutKind.Explicit)]    internal struct Input {        [FieldOffset(0)]        public int type;        [FieldOffset(4)]        public MOUSEINPUT mi;        [FieldOffset(4)]        public KEYBDINPUT ki;        [FieldOffset(4)]        public HARDWAREINPUT hi;    }    [StructLayout(LayoutKind.Sequential)]    internal struct HARDWAREINPUT {        public int uMsg;        public short wParamL;        public short wParamH;    }    internal class INPUT {        public const int MOUSE = 0;        public const int KEYBOARD = 1;        public const int HARDWARE = 2;    }    internal static class NativeMethods {        [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = false)]        internal static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);        [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = false)]        internal static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);        [DllImport("User32.dll", EntryPoint = "SendInput", CharSet = CharSet.Auto)]        internal static extern UInt32 SendInput(UInt32 nInputs, Input[] pInputs, Int32 cbSize);        [DllImport("Kernel32.dll", EntryPoint = "GetTickCount", CharSet = CharSet.Auto)]        internal static extern int GetTickCount();        [DllImport("Kernel32.dll")]        public static extern IntPtr GetModuleHandle(string name);         [DllImport("User32.dll", EntryPoint = "GetKeyState", CharSet = CharSet.Auto)]        internal static extern short GetKeyState(int nVirtKey);        [DllImport("User32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]        internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);    }}

调用,

 private void SendKeyDown(short key)        {            Input[] input = new Input[1];            input[0].type = INPUT.KEYBOARD;            input[0].mkhi.ki.wVk = key;            input[0].mkhi.ki.time = NativeMethods.GetTickCount();                             if (SendInput((uint)input.Length, input, Marshal.SizeOf(input[0])) < input.Length)            {                throw new Win32Exception(Marshal.GetLastWin32Error());            }        }

测试的时候发现只能运行在32位下,在64位下运行,始终按键不能发送到文本框中。

经过很长时间的搜索,终于在Stackoverflow上找到了正确答案,虽然原因还是理解不透,

https://stackoverflow.com/questions/6830651/sendinput-and-64bits

这里写图片描述

问题出在Input结构体上,64位是8个字节的偏移,这个网友给出的答案,

[StructLayout(LayoutKind.Explicit)]    struct MouseKeybdHardwareInputUnion    {        [FieldOffset(0)]        public MOUSEINPUT mi;        [FieldOffset(0)]        public KEYBDINPUT ki;        [FieldOffset(0)]        public HARDWAREINPUT hi;    }    [StructLayout(LayoutKind.Sequential)]    struct Input    {        public uint type;        public MouseKeybdHardwareInputUnion mkhi;    }

改为上面这个就好了32位和64位都能发送。

原创粉丝点击