Win32APIでマウスのイベントをチェックしたり座標を取得したりする

Win32APIでマウスイベントの管理をしたい場合は、WindowProc(ウィンドウプロシージャ関数)内で行う。

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
}

左クリックやダブルクリック等のマウスイベントが発生した時には、第2引数のUINTには「どの種類のマウスイベントなのか」の情報が格納されて、第3引数にはマウスイベントの種類が入り、第4引数のLPARAMには「上位ビットにy座標の情報、下位ビットにx座標の情報」が格納される。

マウスイベントによって処理を分ける

マウスイベントによって処理を分けたい場合は、WM_PAINTとかWM_CREATEと同じようにマウスイベントを指定してあげればよい。

Point pt;
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CREATE:
return 0;
case WM_LBUTTONDOWN:
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);

上記の例では、WM_LBUTTONDOWNと指定してあげることで、左クリックが押された時に処理が実行される。

他にも、指定できるマウスイベントは多くあるので、公式ページを確認しよう。

参考:Mouse Input Notifications - Windows applications | Microsoft Docs

マウスの座標を取得する

マウス座標を獲得する方法はいくつかあり、多くの解説サイトで紹介されているのが、LOWORD(lParam)HIWORD(lParam)の2つの関数を使う事だ。

Point pt;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);

一行目のPOINT ptの部分はPOINT構造体を定義している。POINT構造体の中身はシンプルで、double型のx変数とy変数を格納しているだけの構造体だ。(なので、絶対に使わないといけない、と言うわけではない)

参考:Point(Double, Double) Constructor (System.Windows) | Microsoft Docs

先ほども解説したように、マウスイベント時にはWindowProc関数の第4引数LPAMRA引数に座標の情報が格納されており、LOWORD(lParam)とすることでx座標を取得し、HIWORD(lParam)とすることでy座標を取得する。

ちなみに、LOWORDはLow Wordの意味、HIWORDはHigh Wordの意味。

マウス座標を取得する時には、GET_X_LPARAMを使うべき

多くの解説サイトではマウス座標の取得にはLOWORDとHIWORDを使っているのが、公式ページには「LOWORDとHIWORDではなくて、GET_X_LPARAMとGET_Y_LPARAMを使うべき」と書かれている。

Do not use the LOWORD or HIWORD macros to extract the x- and y- coordinates of the cursor position because these macros return incorrect results on systems with multiple monitors. Systems with multiple monitors can have negative x- and y- coordinates, and LOWORD and HIWORD treat the coordinates as unsigned quantities. WM_MBUTTONDOWN message - Windows applications | Microsoft Docs

簡単に言うと、複数のモニターを使っているパソコンの場合は、LOWORDやHIWORDだと座標を上手く取得できないから使わないでね、と書かれている。

#include <windowsx.h>
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);

こちらの関数の方が何がしたいのか分かりやすくて良い。1つ注意なのが、windowsx.hをincludeするのを忘れないようにすること。

参考:GET_X_LPARAM macro (windowsx.h) | Microsoft Docs