1

xp 32 ビットで sendInput() を使用し、Web サービスを使用して、現在フォーカスのあるウィンドウの F5 を押しました。現在、Vista win64 では、この結果を取得できません。一部の記事では、4 ビットまたは 8 ビットを使用した場合の uint の問題が指摘されていますが、これは差分コンパイルと FieldOffset(4) または (8) を使用したビスタでの問題を修正していません。他の人は、この SendInput() メソッドを使用すると、Vista の画面とウィンドウの間でやり取りがなくなると話しています。誰かがwin32およびwin64マシンでF5を押す解決策を指摘できますか. ありがとう。

uint intReturn = 0;
NativeWIN32.INPUT structInput;
structInput = new NativeWIN32.INPUT();
structInput.type = (uint)1;
structInput.ki.wScan = 0;
structInput.ki.time = 0;
structInput.ki.dwFlags = 0;
structInput.ki.dwExtraInfo = IntPtr.Zero; 

// Key down the actual key-code 
structInput.ki.wVk = (ushort)NativeWIN32.VK.F5;
//vk; 
intReturn = NativeWIN32.SendInput((uint)1, ref structInput, Marshal.SizeOf(structInput));
// Key up the actual key-code 
structInput.ki.dwFlags = NativeWIN32.KEYEVENTF_KEYUP;
structInput.ki.wVk = (ushort)NativeWIN32.VK.F5;
//vk; 
intReturn = NativeWIN32.SendInput((uint)1, ref structInput, Marshal.SizeOf(structInput));



public class NativeWIN32
{ 
    public const ushort KEYEVENTF_KEYUP = 0x0002; 
    public enum VK : ushort 
    {  
        F5                   = 0x74,  
    } 

    public struct KEYBDINPUT 
    {  
        public ushort wVk;  
        public ushort wScan;  
        public uint dwFlags;  
        public long time;  
        public uint dwExtraInfo; 
    }; 
    [StructLayout(LayoutKind.Explicit,Size=28)]  
    public struct INPUT 
    {  
        [FieldOffset(0)] 
        public uint type;
        #if x86 
    //32bit 
    [FieldOffset(4)] 
        #else
        //64bit 
        [FieldOffset(8)]
        #endif
        public KEYBDINPUT ki; 
    };

    [DllImport("user32.dll")] 
    public static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);

}

4

2 に答える 2

4

XPの32/64でこの問題が発生しました。これが、私が思いついた解決策です。私はpInvokeの専門家ではないので、もっと洗練された解決策があるかもしれません。

根本的な原因は、2つのアーキテクチャ間でワードサイズが異なることであると思われます。これにより、外部呼び出しで使用されたデータ構造から複雑なデータの一部が解析される場所が破棄されます。64ビットと32ビットの2つの別個の構造体セットと外部呼び出しを宣言する必要がありました。

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/64WindowsXPおよび32/64Windows7で動作します。

于 2012-04-30T18:23:56.943 に答える
-1

プロジェクトを32ビットでコンパイルすると、これが修正されます。参照してください:http ://social.msdn.microsoft.com/Forums/en-SG/Vsexpressvb/thread/69e5529e-372b-4d70-bb94-556507a2358e

于 2011-08-18T06:57:51.723 に答える