SCROLLINFO

SCROLLINFOは、スクロール情報を持つ構造体。

SCROLLINFO (winuser.h) - Win32 apps | Microsoft Learn

SCROLLINFO.cppで、

RECTの計算も、WM_HSCROLLの項では間違っていたので修正したし、コードが複雑になっていたので、ちょっと整理した。

起動時
起動時

起動時。

左クリック。画像も変えた。
左クリック。画像も変えた。

左クリック。画像も変えた。

下にスクロール
下にスクロール

下にスクロール。

右にスクロール
右にスクロール

右にスクロール。

スクロールを両方とも元の位置に戻すとこうなる。
スクロールを両方とも元の位置に戻すとこうなる。

スクロールを両方とも元の位置に戻すとこうなる。
まだ、再描画がないので、隠れたところは白く消えてしまう。

Sample/winapi/SCROLLINFO/SCROLLINFO/src/SCROLLINFO at master · bg1bgst333/Sample · GitHub

RECT

RECTは、矩形の左端、右端、上端、下端、を表す構造体。

RECT (windef.h) - Win32 apps | Microsoft Learn

GetWindowRectでウィンドウのRECTが取得できるので、そこから幅と高さを計算する。

で、勘違いしてたんだけど、幅widthはrc.right - rc.left, 高さheightはrc.bottom-rc.topが正解だった・・・。
(以前の項で、right - left + 1とか、bottom - top + 1とか、なぜか+1してたけど、これはいらなかった・・・。)

結果はこうなる
結果はこうなる

結果はこうなる。

Sample/winapi/RECT/RECT/src/RECT at master · bg1bgst333/Sample · GitHub

POINT

POINTは、位置(x, y)を指定するときに使う構造体。

POINT (windef.h) - Win32 apps | Microsoft Learn

GetCursorPosの項で、ウィンドウメッセージが来てない時に、マウスカーソルの座標を描画するようなプログラムを作ったが、WindowFromPointをさらに使えば、リアルタイムにその位置のウィンドウハンドルを描画できる。
POINT.cppで、

前回のプログラムに、その位置のウィンドウハンドルも描画する処理を追加した。

ボタンのハンドル
ボタンのハンドル

ボタンのハンドル。

ボタン以外のウィンドウのクライアント領域のハンドル
ボタン以外のウィンドウのクライアント領域のハンドル

ボタン以外のウィンドウのクライアント領域のハンドル。

この位置だとウィンドウハンドルが出る
この位置だとウィンドウハンドルが出る

この位置だとウィンドウハンドルが出る。

ボタンの上だとボタンハンドルが出る
ボタンの上だとボタンハンドルが出る

ボタンの上だとボタンハンドルが出る。

ウィンドウの外のこの位置だとまた別のハンドル
ウィンドウの外のこの位置だとまた別のハンドル

ウィンドウの外のこの位置だとまた別のハンドル。

さらにウィンドウの下のこの位置だとまた別のハンドル
さらにウィンドウの下のこの位置だとまた別のハンドル

さらにウィンドウの下のこの位置だとまた別のハンドル。

Sample/winapi/POINT/POINT/src/POINT at master · bg1bgst333/Sample · GitHub

WindowFromPoint

WindowFromPointで、指定されたPOINT構造体の指す位置にあるウィンドウのハンドルを取得できる。

WindowFromPoint 関数 (winuser.h) - Win32 apps | Microsoft Learn

WindowFromPoint.cppにて、

メインとなるウィンドウ表示前に、ウィンドウハンドルを表示。

WM_CREATEで、子ウィンドウとなるボタンのハンドルも表示。

WM_LBUTTONDOWNでは、クリックした位置のスクリーン座標をWindowFromPointに渡して、ウィンドウハンドル取得。

ボタンの場合は、WM_LBUTTONDOWNに来ないので、WM_COMMANDで、ボタンのID(WM_APP + 1)のところに来た時に、GetCursorPosで取得した座標をWindowFromPointに渡して、ウィンドウハンドル取得。

ボタンはこれ
ボタンはこれ

ボタンはこれ。

ウィンドウはこれ
ウィンドウはこれ

ウィンドウはこれ。

ボタンを押した場合はこうなる
ボタンを押した場合はこうなる

ボタンを押した場合はこうなる。

クライアント領域のボタン以外のところを押したらこうなる。
クライアント領域のボタン以外のところを押したらこうなる。

クライアント領域のボタン以外のところを押したらこうなる。

Sample/winapi/WindowFromPoint/WindowFromPoint/src/WindowFromPoint at master · bg1bgst333/Sample · GitHub

ClientToScreen

ClientToScreenで、指定されたクライアント座標をスクリーン座表に変換する。

ClientToScreen 関数 (winuser.h) - Win32 apps | Microsoft Learn

座標はPOINT構造体を使って渡す。
WM_LBUTTONDOWNで得られるクリックされた座標はクライアント座標。
これをスクリーン座標に変換する。
ClientToScreen.cppで、

クライアント座標と変換後のスクリーン座標を描画。

左上隅をクリックした場合だとこうなる。
左上隅をクリックした場合だとこうなる。

左上隅をクリックした場合だとこうなる。

右下だとこうなる。
右下だとこうなる。

右下だとこうなる。

Sample/winapi/ClientToScreen/ClientToScreen/src/ClientToScreen at master · bg1bgst333/Sample · GitHub

UpdateWindow

UpdateWindowで画面を更新する。

UpdateWindow 関数 (winuser.h) - Win32 apps | Microsoft Learn

InvalidateRectで無効領域が作られればWM_PAINTが送られて更新されるが、これはタスクが無いアイドル状態だからであり、処理が忙しい時はなかなか更新されない。
UpdateWindowで強制更新する必要がある。

"Update"が含まれてるので今回はapp.manifestを用意
"Update"が含まれてるので今回はapp.manifestを用意

"Update"が含まれてるので今回はapp.manifestを用意。
UpdateWindow.cppで、

		// マウスの左ボタンが押された時.
		case WM_LBUTTONDOWN:	// マウスの左ボタンが押された時.(uMsgがWM_LBUTTONDOWNの時.)

			// WM_LBUTTONDOWNブロック
			{

				// iをインクリメントしまくる.
				for (int j = 0; j < 1000000; j++){	// jが1000000を超えるまで続ける.
					InvalidateRect(hwnd, NULL, TRUE);	// InvalidateRectで画面全体を無効領域とする.
					i++;	// iをインクリメント.
				}

			}

			// 抜ける.
			break;	// breakで抜ける.

左クリックしたら、iをインクリメントする度に、InvalidateRectで無効領域をつくる。

WM_PAINTでiを描画。

起動時はこうだが、左クリックしても画面は更新されない。
起動時はこうだが、左クリックしても画面は更新されない。

起動時はこうだが、左クリックしても画面は更新されない。

数秒したら、全部インクリメントし終わって、この画面になる。
数秒したら、全部インクリメントし終わって、この画面になる。

数秒したら、全部インクリメントし終わって、この画面になる。
InvalidateRectを呼んでも更新はされない。

InvalidateRectの後にUpdateWindowを呼ぶ。

起動時
起動時

起動時。
左クリックすると、

今度は画面が更新されて、1ずつカウントされる。途中過程がわかる。
今度は画面が更新されて、1ずつカウントされる。途中過程がわかる。

今度は画面が更新されて、1ずつカウントされる。途中過程がわかる。

最後はこう
最後はこう

最後はこう。
更新してから足してるから、最後の値は反映されないのか。

Sample/winapi/UpdateWindow/UpdateWindow/src/UpdateWindow at master · bg1bgst333/Sample · GitHub

WM_HSCROLL

WM_HSCROLLをやってなかったので、ここのイベント時の処理も書いて、水平方向にもスクロールしてみる。

WM_HSCROLL メッセージ (Winuser.h) - Win32 apps | Microsoft Learn

WM_HSCROLL.cppで、

左クリック時の初期化で、水平方向分の設定も追加。

WM_HSCROLLに来た時の処理も追加。

起動時
起動時

起動時。

左クリックで表示
左クリックで表示

左クリックで表示。

右に1ピクセルずつスクロール
右に1ピクセルずつスクロール

右に1ピクセルずつスクロール。

1ページスクロールで一気に。
1ページスクロールで一気に。

1ページスクロールで一気に。

つまみを1番左に戻す。
つまみを1番左に戻す。

つまみを1番左に戻す。
スクロールするたびに見えてなかった部分は白く出てしまう。

Sample/winapi/WM_HSCROLL/WM_HSCROLL/src/WM_HSCROLL at master · bg1bgst333/Sample · GitHub