マウスのホイールの回転とWM_MOUSEWHEELウィンドウメッセージ
わりとメモのような位置づけです。
ソースはMSDN。正確でより詳しい情報を知りたい場合はそちらをお読みください。
概要
WM_MOUSEWHEELはマウスホイールが回されたときにフォーカスを持つウィンドウに送られる。
DefWindowProc関数(デフォルトウィンドウプロシジャ)は、それの親ウィンドウにメッセージを知らせる。
wParam
上位ワードはホイールが回転した距離(回転量)を示す。WHEEL_DELTA(120)の倍数の形で表される。
正の値は前(奥)、負の値は後ろ(手前)へ回された事を意味する。
(wParamの上位ワードをWHEEL_DELTAで割れば、何回「カクッ、カクッ」と回されたかがわかる・・・らしい。要検証。)
下位ワードはどのキーが押されてるかを示す。
MK_CONTROL | Ctrlキー |
MK_LBUTTON | 左のマウスボタンが押されてる |
MK_MBUTTON | 真ん中のマウスボタンが押されてる |
MK_RBUTTON | 右 |
MK_SHIFT | Shiftキー |
MK_XBUTTON1 | Windows 2000/XP: 最初のXボタンが押されてる (?) |
MK_XBUTTON2 | Windows 2000/XP: 次のXボタンが押されている (?) |
上位/下位ワードを分けるマクロもあります。
fwKeys = GET_KEYSTATE_WPARAM(wParam);
zDelta = GET_WHEEL_DELTA_WPARAM(wParam); // この値は負になることもある
fwKeysはintかDWORDかunsigned shortがいいのかな。
zDeltaは負になることもあるので、intがいいかな。
lParam
マウスカーソルの、スクリーンの左上からの相対座標。
下位ワードはX座標。上位ワードはY座標。便利なマクロもあります。
xPos = GET_X_LPARAM(lParam); yPos = GET_Y_LPARAM(lParam);
xPos, yPosはint型がいいのかな。
また、MAKEPOINTSマクロを使えばlParamをPOINTS構造体へ変換できます(後述)。
戻り値
アプリケーションがこのメッセージを処理したときにはゼロを返すべき。
ウィンドウ上のマウスの座標を求める方法(09/02/27)
万能なやり方
#include <assert.h> #include <windows.h> // 指定したウィンドウ上でのカーソルの座標を得る bool GetClientCursorPos( HWND hWnd, POINT *dest) { assert(hWnd); assert(dest); if(GetCursorPos( dest)) { if(ScreenToClient( hWnd, dest)) return true; } return false; }
これはWM_MOUSEWHEELメッセージが来た時以外でも使える万能なやり方です。
そのままコピペしないで、もうちょっといいエラーチェックを行ってください。
WM_MOUSEWHEELメッセージが来たとき
MAKEPOINTSマクロは
#define MAKEPOINTS(l) (*((POINTS FAR *)&(l)))
と定義されています。lParamがカーソル座標を表すので以下の通りにできます。
POINTS cursors; // 画面上のカーソル座標 cursors = MAKEPOINTS( lParam); // これは実際には構造体同士のコピー POINT cursor; // 特定のウィンドウ上のカーソル座標 cursor.x = cursors.x; cursor.y = cursors.y; ScreenToClient( hWnd, &cursor);
ちなみにPOINTS構造体とPOINT構造体は別物です。
POINTSはX,Y座標それぞれがSHORT型です。だからポインツではなくポイントエスとかポイントショートとか読んだほうがいいのでしょうか。英語の人は好き勝手に読むらしいですけど。
POINT型はそれぞれLONG型です。だから常にPOINTS型はPOINTに変換できると。多分。
この二つの構造体はWinDef.hに、MAKEPOINTSマクロはWinGDI.hで定義されています。
これら2つのやり方の違い
上のほうのやり方は「その瞬間のマウスカーソルの位置」を知りたいときに使い、
下のほうは「WM_MOUSEWHEELメッセージが渡された瞬間の位置」を知りたいときに使ってください。
実際、下のやり方と上のやり方を同時に使って値を比較すると、ずれる事が多々あります。
(メッセージが来た瞬間と、GetClientCursorPosを呼ぶ間にマウスが動かされた場合に)