マウスのホイールの回転と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を呼ぶ間にマウスが動かされた場合に)