マウス、ペンそれにトラックボールなどのカーソル (マウスポインタ) を制御する方法について解説します。
BOOL GetCursorPos(
LPPOINT lpPoint // カーソルの位置
);
GetCursorPos 関数 | MSDN
現在のマウスポインタの位置を、スクリーン座標で取得できます。
BOOL SetCursorPos( int X, // 水平位置 int Y // 垂直位置 );SetCursorPos 関数 | MSDN
マウスポインタを、スクリーン座標の指定の位置へ移動できます。これは後述するSendInput()でも可能であり、それには次のようにします。
void Move(int x, int y) { const double ScaleX = 0xffff / GetSystemMetrics(SM_CXSCREEN); const double ScaleY = 0xffff / GetSystemMetrics(SM_CYSCREEN); INPUT input = {}; input.type = INPUT_MOUSE; input.mi.dx = (LONG)(x * ScaleX); input.mi.dy = (LONG)(y * ScaleY); input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; SendInput(1, &input, sizeof(INPUT)); }
クリックはSendInput()で行えます。
UINT WINAPI SendInput( _In_ UINT nInputs, // pInputsの要素数 _In_ LPINPUT pInputs, // マウスまたはキーボード入力の内容 _In_ int cbSize // INPUT構造体のバイト数 );SendInput function (Windows) | MSDN
入力方法を指定するpInputsは、次のINPUT構造体で定義します。
typedef struct tagINPUT { DWORD type; union { MOUSEINPUT mi; KEYBDINPUT ki; HARDWAREINPUT hi; }; } INPUT, *PINPUT;INPUT structure (Windows) | MSDN
入力方法をマウスとするにはtypeをINPUT_MOUSEとし、その入力内容はmiにMOUSEINPUT共用体で指定します。
typedef struct tagMOUSEINPUT { LONG dx; LONG dy; DWORD mouseData; DWORD dwFlags; DWORD time; ULONG_PTR dwExtraInfo; } MOUSEINPUT, *PMOUSEINPUT;MOUSEINPUT structure (Windows) | MSDN
これらを用いて、たとえば現在の位置から右へ100ピクセル移動した位置をクリックするならば、次のようにします。
INPUT input = {}; input.type = INPUT_MOUSE; input.mi.dx = 100; input.mi.dy = 0; input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP; SendInput(1, &input, sizeof(INPUT));
INPUT構造体の定義時に初期化すれば、これは次のように簡潔に記述できます。
INPUT input = { INPUT_MOUSE, 100, 0, 0, MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP }; SendInput(1, &input, sizeof(INPUT));
たとえば現在の位置でダブルクリックするならば、次のように同じ位置で2度クリックします。
INPUT input[] = { {}, {} }; input[0].type = input[1].type = INPUT_MOUSE; input[0].mi.dwFlags = input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP; SendInput(sizeof(input) / sizeof(input[0]), input, sizeof(INPUT));
HCURSOR WINAPI LoadCursor( _In_opt_ HINSTANCE hInstance, _In_ LPCTSTR lpCursorName );LoadCursor function (Windows) | MSDN
HCURSOR WINAPI SetCursor( _In_opt_ HCURSOR hCursor );SetCursor function (Windows) | MSDN
SetCursor(LoadCursor(NULL, IDC_HAND));
SetCursor()は、アプリケーション上での現在のカーソルを変更します。これをアプリケーション外にも適用させるには、SetSystemCursor()でシステムのカーソルを変更します。
BOOL WINAPI SetSystemCursor( _In_ HCURSOR hcur, _In_ DWORD id );SetSystemCursor function (Windows) | MSDN SetSystemCursor 関数 | MSDN
SetSystemCursor()に渡すhcurは、カーソル変更後に破棄されます。よって破棄されては困るリソースは、コピーを渡すようにします。
HCURSOR cursor = LoadCursor(NULL, IDC_CROSS); SetSystemCursor(CopyCursor(cursor), OCR_NORMAL);
なおシステムカーソルの変更はアプリケーション終了後も維持されるため、明示的に元に戻さねばなりません。
// カーソルを保存する HCURSOR normalCursor = CopyCursor(LoadCursor(NULL, IDC_ARROW)); // カーソルを変更する SetSystemCursor(CopyCursor(LoadCursor(NULL, IDC_HAND)), OCR_NORMAL); // 一時的に戻す SetSystemCursor(CopyCursor(normalCursor), OCR_NORMAL); // カーソルを変更する SetSystemCursor(CopyCursor(LoadCursor(NULL, IDC_CROSS)), OCR_NORMAL); // 元に戻す SetSystemCursor(normalCursor, OCR_NORMAL);