読者です 読者をやめる 読者になる 読者になる

酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

C#を使ってマウスの動きをプログラミングする

「マウスの右ボタンを押したままの状態で放置しておいて、1時間ごとに押し直すような事って出来ん?」って聞かれたので、「出来るんじゃね?」と適当に答えておきました。

それから1ヶ月……なんとなく思い出して本当に出来るのかどうか調べてみました。

P/Invokeで実現するためにまず定義をします。

using System.Runtime.InteropServices;

class Win32
{
    [DllImport("user32.dll")]
    public static extern uint SendInput(
                uint nInputs,    // INPUT 構造体の数(イベント数)
                INPUT[] pInputs, // INPUT 構造体
                int cbSize       // INPUT 構造体のサイズ
    );

    public const int MOUSEEVENTF_MOVED      = 0x0001;
    public const int MOUSEEVENTF_LEFTDOWN   = 0x0002;
    public const int MOUSEEVENTF_LEFTUP     = 0x0004;
    public const int MOUSEEVENTF_RIGHTDOWN  = 0x0008;
    public const int MOUSEEVENTF_RIGHTUP    = 0x0010;
    public const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
    public const int MOUSEEVENTF_MIDDLEUP   = 0x0040;
    public const int MOUSEEVENTF_WHEEL      = 0x0080;
    public const int MOUSEEVENTF_XDOWN      = 0x0100;
    public const int MOUSEEVENTF_XUP        = 0x0200;
    public const int MOUSEEVENTF_ABSOLUTE   = 0x8000;

    public const int SCREEN_LENGTH          = 0x10000;
}

[StructLayout(LayoutKind.Sequential)]
struct INPUT
{ 
    public int        type; // 0 = INPUT_MOUSE(デフォルト), 1 = INPUT_KEYBOARD 
    public MOUSEINPUT mi;
}

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

同僚の要望の動作をそのままトレースしても良かったんだけど、ここにはシンプルな例を書いておきます。

    INPUT[] input = new INPUT[3] ;  // 計3イベントを格納

    // マウスを移動
    input[0].mi.dx = Win32.SCREEN_LENGTH / 10;
    input[0].mi.dy = Win32.SCREEN_LENGTH / 10;
    input[0].mi.dwFlags = Win32.MOUSEEVENTF_MOVED | Win32.MOUSEEVENTF_ABSOLUTE;

    // 左ボタンを押下
    input[1].mi.dwFlags = Win32.MOUSEEVENTF_LEFTDOWN;

    // 左ボタンを開放
    input[2].mi.dwFlags = Win32.MOUSEEVENTF_LEFTUP;

    // マウスイベント送出
    Win32.SendInput(3, input, Marshal.SizeOf(input[0])); 

この手法を応用すれば、キーボード入力のデータを保持しておいておけば、ゲームのリプレイデータとして使えそうだなぁ。

今回調べた中で一番の発見は、マウスの移動させる単位のことを「ミッキー」と呼ぶこと。