首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SendInput和64位

SendInput和64位
EN

Stack Overflow用户
提问于 2011-07-26 21:22:57
回答 3查看 4.2K关注 0票数 10

下面是我用来通过SendInput应用程序接口模拟按键的一些代码的摘录。如果我将我的应用程序设置为针对x86处理器进行编译,但不适用于x64 CPU编译,则可以正确执行此操作。

我猜这与x64使用双倍大小指针的事实有关,但我试图将此[FieldOffset(4)]更改为此[FieldOffset(8)],但它不起作用。

这是否与它正在导入32位版本的user32.dll有关?

代码语言:javascript
复制
    #region SendInput API

    [DllImport("user32.dll", EntryPoint = "SendInput", SetLastError = true)]
    static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

    [DllImport("user32.dll", EntryPoint = "GetMessageExtraInfo", SetLastError = true)]
    static extern IntPtr GetMessageExtraInfo();

    private enum KeyEvent
    {
        KeyUp = 0x0002,
        KeyDown = 0x0000,
        ExtendedKey = 0x0001
    }

    private struct KEYBDINPUT
    {
        public ushort wVk;
        public ushort wScan;
        public uint dwFlags;
        public long time;
        public uint dwExtraInfo;
    };

    [StructLayout(LayoutKind.Explicit, Size = 28)]
    private struct INPUT
    {
        [FieldOffset(0)]
        public uint type;
        [FieldOffset(4)]
        public KEYBDINPUT ki;
    };

    #endregion

    public void sendKey(KeyCode Key)
    {
        INPUT[] InputList = new INPUT[2];

        INPUT keyInput = new INPUT();
        keyInput.type = 1;

        keyInput.ki.wScan = 0;
        keyInput.ki.time = 0;
        keyInput.ki.dwFlags = (int)KeyEvent.KeyDown;
        keyInput.ki.dwExtraInfo = (uint)GetMessageExtraInfo();
        keyInput.ki.wVk = (ushort)Key;

        InputList[0] = keyInput;

        keyInput.ki.dwFlags = (int)KeyEvent.KeyUp;

        InputList[1] = keyInput;

        SendInput((uint)2, InputList, Marshal.SizeOf(InputList[0]));
    }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-07-27 00:23:43

除了SLaks发现的错误之外,剩下的问题是INPUT的大小不正确。这意味着SendInput会失败,因为它接收到了INPUT[]类型的参数。您不能使用StructLayout(LayoutKind.Explicit, Size = 28)指定大小,因为您需要同时处理x86和x64的代码。

这一切都源于在INPUT中只包含了KEYBRDINPUT结构这一事实。MOUSEINPUT结构比KEYBRDINPUT大,这是导致问题的原因。

最好的解决方案是正确定义输入结构,包括联合部分。这样做(声明取自pinvoke.net)。

代码语言:javascript
复制
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
    public int dx;
    public int dy;
    public uint mouseData;
    public uint dwFlags;
    public uint time;
    public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT 
{
     public ushort wVk;
     public ushort wScan;
     public uint dwFlags;
     public uint time;
     public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
     public int uMsg;
     public short wParamL;
     public short wParamH;
}

[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;
}
票数 12
EN

Stack Overflow用户

发布于 2011-07-26 21:27:02

dwExtraInfo是一个指针。

因此,它需要在32位代码中为4字节宽,在64位代码中为8字节。

要在C#中执行此操作,请使用IntPtr (而不是uint,它始终为4字节)

票数 5
EN

Stack Overflow用户

发布于 2021-12-16 23:47:41

对于64位平台,唯一需要更改的是INPUT第二个参数的FieldOffset(8) (而不是4)。不需要更改或指定rest结构的大小。这就足够了,而且是完整的(注意,我使用的是默认的InputUnion结构,而不是KEYBDINPUT,但没有区别):

代码语言:javascript
复制
 [StructLayout(LayoutKind.Explicit)]
    public struct INPUT
    {
    [FieldOffset(0)] public uint Type;
    [FieldOffset(8)] public InputUnion U;
    }

    [StructLayout(LayoutKind.Explicit )]
    public struct InputUnion
    {
        [FieldOffset(0)] public MOUSEINPUT mi;
        [FieldOffset(0)] public KEYBDINPUT ki;
        [FieldOffset(0)] public HARDWAREINPUT hi;
    }


    [StructLayout(LayoutKind.Sequential)]
    public struct MOUSEINPUT
    {
        public int dx;
        public int dy;
        public uint mouseData;
        public uint dwFlags;
        public uint time;
        public  IntPtr dwExtraInfo;
    }


    [StructLayout(LayoutKind.Sequential)]
    public struct KEYBDINPUT
{
    public UInt16 Vk;
    public UInt16 Scan;
    public UInt32 Flags;
    public UInt32 Time;
    public IntPtr ExtraInfo;
}

    [StructLayout(LayoutKind.Sequential)]
    public struct HARDWAREINPUT
    {
        public uint uMsg;
        public ushort wParamL;
        public ushort wParamH;
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6830651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档