2011-07-26 54 views
10

下面是我用來模擬通過SendInput API進行按鍵操作的一些代碼的摘錄。如果我將我的應用程序設置爲x86 CPU編譯,但不適用於x64 CPU編譯,此工作正常。SendInput和64bits

我猜測它有一些事實,即x64使用雙倍大小的指針,但我試圖將此[FieldOffset(4)]更改爲此[FieldOffset(8)],但它不起作用。

難道這與它導入32位版本的user32.dll有關嗎?

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

不知何故,一些代碼缺少所以在這個行應該讀作[StructLayout(LayoutKind.Explicit,大小= 28)]' – Cheetah

回答

11

進一步說SLaks識別的錯誤,你剩下的問題是,INPUT的大小不正確。這意味着SendInput因接收到類型爲INPUT[]的參數而失敗。由於您需要可同時處理x86和x64的代碼,因此無法使用StructLayout(LayoutKind.Explicit, Size = 28)指定大小。

這一切都源於這樣一個事實,即您只包含KEYBRDINPUT結構體INPUTMOUSEINPUT結構大於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; 
} 
+0

當我開始這個項目時,我不得不使用SendInput,但我不記得原因。但是 - 這有效!非常感謝你! – Cheetah

5

dwExtraInfo是一個指針。
因此,它需要在32位代碼中爲4個字節寬,在64位代碼中爲8個字節。

要做到這一點在C#中,使用IntPtr(不uint,這始終是4個字節)

+0

我試圖改變這一點,但它並沒有再次與工作的x64(x86的是改變的罰款)。謝謝。 – Cheetah

+1

@Ben:你的尺寸是錯的。大小因位數而異,所以您無法指定它。 – SLaks

+0

是的,移除'LayoutKind.Explicit,Size = 28'和'FieldOffset'屬性。 –