10

以下は、SendInput API を介してキーの押下をシミュレートするために使用している一部のコードの抜粋です。アプリケーションを x86 CPU 用にコンパイルするように設定した場合、これは正しく機能しますが、x64 CPU コンパイルでは機能しません。

x64がダブルサイズのポインターを使用しているという事実と関係があると思いますが、これ[FieldOffset(4)]をこれに変更しようとしまし[FieldOffset(8)]たが、うまくいきませんでした。

user32.dll の 32 ビット バージョンをインポートしているという事実と何か関係があるのでしょうか?

    #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]));
    }
4

3 に答える 3

12

SLaks が特定したエラーに加えて、残りの問題は、のサイズINPUTが正しくないことです。これはSendInput、 type のパラメーターを受け取ったために失敗したことを意味しますINPUT[]StructLayout(LayoutKind.Explicit, Size = 28)x86 と x64 の両方を処理するコードが必要なため、 でサイズを指定することはできません。

KEYBRDINPUTこれはすべて、構造体のみを に含めたという事実に起因しますINPUT。構造体が問題の原因MOUSEINPUTよりも大きいです。KEYBRDINPUT

最善の解決策は、共用体部分を含め、INPUT 構造体を正しく定義することです。これを次のように行います ( pinvoke.netから取得した宣言)。

[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;
}
于 2011-07-26T16:23:42.893 に答える
5

dwExtraInfoポインタです。
したがって、32 ビット コードでは 4 バイト幅、64 ビット コードでは 8 バイト幅である必要があります。

C# でこれを行うには、IntPtr(not uint、常に 4 バイト) を使用します。

于 2011-07-26T13:27:02.073 に答える