我在 XP 上使用 32/64 时遇到了这个问题,这是我想出的解决方案。我不是 pInvoke 专家,因此可能有更优雅的解决方案。
根本原因似乎是两种架构之间的字长不同。这会导致从外部调用中使用的数据结构中解析出一些复杂的数据。我必须为 64 位和 32 位声明两组独立的结构和外部调用。
internal static class SendInputExternalCalls
{
// This SendInput call uses the 32bit input structure.
[DllImport("user32.dll", SetLastError = true, EntryPoint = "SendInput")]
public static extern UInt32 SendInput(
UInt32 numInputs,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 1)]
SEND_INPUT_FOR_32_BIT[] sendInputsFor,
Int32 cbSize);
// This SendInput call uses the 64bit input structure.
[DllImport("user32.dll", SetLastError = true, EntryPoint = "SendInput")]
public static extern UInt32 SendInput(
UInt32 numInputs,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 1)]
SEND_INPUT_FOR_64_BIT[] sendInputsFor,
Int32 cbSize);
}
// This is the basic structure for 32 bit input. SendInput allows for other input
// types, but I was only concerned with keyboard input, so I harcoded my strucs that way.
[StructLayout(LayoutKind.Explicit, Pack = 1)]
internal struct SEND_INPUT_FOR_32_BIT
{
[FieldOffset(0)]
public uint InputType;
[FieldOffset(4)]
public KEYBOARD_INPUT_FOR_32_BIT KeyboardInputStruct;
}
// Here is the structure for keyboard input. The key code, scan code, and flags
// are what's important. The other variables are place holders so that the structure
// maintains the correct size when compared to the other possible input structure types.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct KEYBOARD_INPUT_FOR_32_BIT
{
public ushort VirtualKeyCode;
public ushort ScanCode;
public uint Flags;
public uint Time;
public uint ExtraInfo;
public uint Padding1;
public uint Padding2;
}
// Here's the corresponding 64 bit structure. Notice that the field offset are larger.
[StructLayout(LayoutKind.Explicit, Pack = 1)]
internal struct SEND_INPUT_FOR_64_BIT
{
[FieldOffset(0)]
public uint InputType;
[FieldOffset(8)]
public KEYBOARD_INPUT_FOR_64_BIT KeyboardInputStruct;
}
// Here's the keyboard 64 bit structure. Notice that the field offset are again larger.
[StructLayout(LayoutKind.Explicit, Pack = 1)]
internal struct KEYBOARD_INPUT_FOR_64_BIT
{
[FieldOffset(0)]
public ushort VirtualKeyCode;
[FieldOffset(2)]
public ushort ScanCode;
[FieldOffset(4)]
public uint Flags;
[FieldOffset(12)]
public uint Time;
[FieldOffset(20)]
public uint Padding1;
[FieldOffset(28)]
public uint Padding2;
}
这是稍微有点笨拙的部分。使用哪种结构取决于应用程序运行的架构。您可以针对 32 位或 64 位目标进行编译,但仍然可以在 64 位 Windows 上运行 32 位编译的应用程序。如果您希望 32 位编译的应用程序在 64 位计算机上使用 SendInput,则必须弄清楚在运行时要使用哪个结构。我通过在调用发送输入的公共方法时检查字长来做到这一点。
public static void SendInput( ushort charUnicode )
{
// In 32 bit the IntPtr should be 4; it's 8 in 64 bit.
if (Marshal.SizeOf(new IntPtr()) == 8)
{
SendInput64(charUnicode);
}
else
{
SendInput32(charUnicode);
}
}
我没有在 Vista 中尝试过此操作,但它可以在 32/64 位 Windows XP 和 32/64 位 Windows 7 中运行。