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

ScrollWindow

ScrollWindowでクライアント領域をスクロールする。

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

これまでは、WM_PAINT時のBitBltで描画する範囲をスクロールごとに変えていく方法を取っていた。
しかし、どうもScrollWindowを使えば、WM_PAINTが無くても見えている範囲のスクロールは勝手にやってくれるらしい。
ScrollWindow.cppで、

左クリックで、ビットマップを描画し、スクロールバーの初期設定。
上下のスクロールのみ対応。
WM_PAINTは無い。

クライアント領域は画像より小さい
クライアント領域は画像より小さい

クライアント領域は画像より小さい。
ここで左クリックすると、

bitmap1.bmpが描画される
bitmap1.bmpが描画される

bitmap1.bmpが描画される。
スクロールバーの長さも適切なものに。

スクロールバーの一番下のボタンで1行ずつスクロールする。
スクロールバーの一番下のボタンで1行ずつスクロールする。

スクロールバーの一番下のボタンで1行ずつスクロールする。
下の見えていなかった部分は、WM_PAINTが呼ばれるようにして、そこで描画しないといけないが、ここではあえてそれをしていないので白くなっている。

一番下のボタンとつまみの間をクリックすると、1ページ分のスクロール。
一番下のボタンとつまみの間をクリックすると、1ページ分のスクロール。

一番下のボタンとつまみの間をクリックすると、1ページ分のスクロール。
ここでは、一気に下までスクロールしている。その分、白い部分が大きく見えている。

今度はつまみを掴んで一気に上に戻す。
今度はつまみを掴んで一気に上に戻す。

今度はつまみを掴んで一気に上に戻す。
隠れていた部分は再描画されないので今度は上のほうが白くなる。
ScrollWindowでスクロールは出来たが、どっちみちWM_PAINTで見えてない部分の再描画は必要。

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

STM_SETIMAGE

ウィンドウメッセージSTM_SETIMAGEで、スタティックコントロールにビットマップをセットできる。

STM_SETIMAGE message (Winuser.h) - Win32 apps | Microsoft Learn

プロジェクト作成後、

リソースを追加
リソースを追加

リソースを追加。

Bitmapを新規作成
Bitmapを新規作成

Bitmapを新規作成。

最初はこうだけど、いったん閉じて
最初はこうだけど、いったん閉じて

最初はこうだけど、いったん保存して閉じて、
テキストエディタで、resource.hを、

こうして、STM_SETIMAGE.rcも、

こうして、

bitmap1.bmpをこれに置き換える。
bitmap1.bmpをこれに置き換える。

bitmap1.bmpをこれに置き換える。
ソリューション開いたら、

こうなってる
こうなってる

こうなってる。
あとは、STM_SETIMAGE.cppで、

LoadBitmapで取得したhBitmapを、SendMessageのSTM_SETIMAGEにてセット。

セットできた
セットできた

セットできた。

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

SetupDiGetClassDevs

SetupDiGetClassDevsは、指定されたGUIDのデバイスクラスのデバイス情報ハンドルを取得する。

SetupDiGetClassDevsW function (setupapi.h) - Win32 apps | Microsoft Docs

ボリュームデバイスクラスのデバイス情報ハンドルを取得する。
SetupDiGetClassDevs.cppで、

と書く。

setupapi.libをリンク
setupapi.libをリンク

setupapi.libをリンク。

exeのファイル名に&quot;setup&quot;が含まれてると管理者権限必要になるのでapp.manifest用意。
exeのファイル名に"setup"が含まれてると管理者権限必要になるのでapp.manifest用意。

exeのファイル名に"setup"が含まれてると管理者権限必要になるのでapp.manifest用意。
(DispatchMessageで使ったやつをコピペ。)

app.manifestをセット
app.manifestをセット

app.manifestをセット。

これでハンドル取得できた。
これでハンドル取得できた。

これでハンドル取得できた。

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