背景
これまで C# を使って 32bit で作成していた Windows アプリケーションを 64bit に変更したら、キー入力が反映されなくなった。ログを追ってみると、どうも SendInput で送出しているキー入力が無視されているようだ。
調査に当たっては以下の記事が参考になったので、備忘として残しておく。
改修ポイント
32bit の時は、上の記事と同じように、SendInput に渡す構造体を次のように定義していた。
[StructLayout(LayoutKind.Explicit)]
private struct INPUT
{
[FieldOffset(0)] public int type;
[FieldOffset(4)] public MOUSEINPUT mi;
[FieldOffset(4)] public KEYBDINPUT ki;
[FieldOffset(4)] public HARDWAREINPUT hi;
};
これだと、先頭の type
と次の mi
やki
との間が 4 バイトしか差がないことになるが、64bit アプリケーションでは、ここにパディングが入って 8バイトのオフセットが必要だった。
下の記事では、32bit/64bit 両方に対応するため、次のような定義になっている。
[StructLayout(LayoutKind.Sequential)]
struct Input
{
public int Type;
public InputUnion ui;
}
[StructLayout(LayoutKind.Explicit)]
struct InputUnion
{
[FieldOffset(0)]
public MouseInput Mouse;
[FieldOffset(0)]
public KeyboardInput Keyboard;
[FieldOffset(0)]
public HardwareInput Hardware;
}
もう一点、次の修正も必要だった。
[StructLayout(LayoutKind.Sequential)]
private struct KEYBDINPUT
{
public short wVk;
public short wScan;
public int dwFlags;
public int time;
// public int dwExtraInfo;
public IntPtr ExtraInfo; // IntPtr に変更
};
int
から IntPtr
に変更することで、バイト幅は 4バイトから 8バイトに増えるわけだが、その明確な理由は見つけられなかった。理由をご存じの方はご教示いただけると幸いです。