GetCursor

GetCursorで、現在のカーソルのカーソルハンドルを取得できる。

GetCursor function (winuser.h) - Win32 apps | Microsoft Docs

カーソルが変わったかを確認してみる。
GetCursor.cppで、

WM_LBUTTONDOWN時のハンドルをチェック。
(いちいちMessageBoxとかめんどいのでデバッガで。)

最初は既定のアローカーソル
最初は既定のアローカーソル

最初は既定のアローカーソル。

クロスカーソルをロード
クロスカーソルをロード

クロスカーソルをロード。

クロスカーソルをセット
クロスカーソルをセット

クロスカーソルをセット。

戻り値は既定のアローカーソルハンドル
戻り値は既定のアローカーソルハンドル

戻り値は既定のアローカーソルハンドル。

直後にGetCursorすると、クロスカーソルのハンドルが返ってくる。
直後にGetCursorすると、クロスカーソルのハンドルが返ってくる。

直後にGetCursorすると、クロスカーソルのハンドルが返ってくる。
差し替えられたことがわかる。

アローカーソルが
アローカーソルが

アローカーソルが、

クロスカーソルに替わったということ
クロスカーソルに替わったということ

クロスカーソルに替わったということ。

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

SetCursor

SetCursorは、現在のカーソルを、指定されたカーソルハンドルのカーソルにする。

SetCursor function (winuser.h) - Win32 apps | Microsoft Docs

SetCursor.cppで、

// ヘッダファイルのインクルード
// 既定のヘッダファイル
#include <windows.h>	// 標準WindowsAPI
#include <tchar.h>		// TCHAR型

// 関数のプロトタイプ宣言
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);	// ウィンドウメッセージに対して独自の処理をするように定義したコールバック関数WindowProc.

// _tWinMain関数の定義
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd){

	// 変数・配列の宣言と初期化.
	HWND hWnd;							// CreateWindowで作成したウィンドウのウィンドウハンドルを格納するHWND型変数hWnd.
	MSG msg;							// ウィンドウメッセージ情報を格納するMSG構造体型変数msg.
	WNDCLASS wc;						// ウィンドウクラス情報をもつWNDCLASS構造体型変数wc.

	// ウィンドウクラスの設定
	wc.lpszClassName = _T("SetCursor");						// ウィンドウクラス名は"SetCursor".
	wc.style = CS_HREDRAW | CS_VREDRAW;						// スタイルはCS_HREDRAW | CS_VREDRAW.
	wc.lpfnWndProc = WindowProc;							// ウィンドウプロシージャは独自の処理を定義したWindowProc.
	wc.hInstance = hInstance;								// インスタンスハンドルは_tWinMainの引数.
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);				// アイコンはアプリケーション既定のもの.
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);				// カーソルは矢印.
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	// 背景は白ブラシ.
	wc.lpszMenuName = NULL;									// なし
	wc.cbClsExtra = 0;										// 0でいい.
	wc.cbWndExtra = 0;										// 0でいい.

	// ウィンドウクラスの登録
	if (!RegisterClass(&wc)) {	// RegisterClassでウィンドウクラスを登録し, 0が返ったらエラー.

		// エラー処理
		MessageBox(NULL, _T("RegisterClass Failure!"), _T("SetCursor"), MB_OK | MB_ICONHAND);	// MessageBoxで"RegisterClass Failure!"とエラーメッセージを表示.
		return -1;	// 異常終了(1)

	}

	// ウィンドウの作成
	hWnd = CreateWindow(_T("SetCursor"), _T("SetCursor"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);	// CreateWindowで, 上で登録した"SetCursor"ウィンドウクラスのウィンドウを作成.
	if (hWnd == NULL) {	// ウィンドウの作成に失敗したとき.

		// エラー処理
		MessageBox(NULL, _T("CreateWindow Failure!"), _T("SetCursor"), MB_OK | MB_ICONHAND);	// MessageBoxで"CreateWindow Failure!"とエラーメッセージを表示.
		return -2;	// 異常終了(2)

	}

	// ウィンドウの表示
	ShowWindow(hWnd, SW_SHOW);	// ShowWindowでSW_SHOWを指定してウィンドウの表示.

	// メッセージループ
	while (GetMessage(&msg, NULL, 0, 0) > 0) {	// GetMessageでメッセージを取得, 戻り値が0より大きい間はループし続ける.

		// ウィンドウメッセージ処理
		TranslateMessage(&msg);	// TranslateMessageで仮想キーメッセージを文字メッセージへ変換.
		DispatchMessage(&msg);	// DispatchMessageで受け取ったメッセージをウィンドウプロシージャ(この場合は独自に定義したWindowProc)に送出.

	}

	// プログラムの終了
	return (int)msg.wParam;	// 終了コード(msg.wParam)を戻り値として返す.

}

// WindowProc関数の定義
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {	// ウィンドウメッセージに対して独自の処理をするように定義したウィンドウプロシージャ.

	// スタティック変数の初期化.
	static HCURSOR hOldCursor = NULL;	// hOldCursorをNULLで初期化.

	// ウィンドウメッセージに対する処理.
	switch (uMsg) {	// switch-casa文でuMsgの値ごとに処理を振り分ける.

		// ウィンドウの作成が開始された時.
		case WM_CREATE:		// ウィンドウの作成が開始された時.(uMsgがWM_CREATEの時.)

			// WM_CREATEブロック
			{

				// 変数の宣言と初期化.
				HCURSOR hCursor;	// カーソルハンドルhCursor.

				// ウェイトカーソルのロード.
				hCursor = (HCURSOR)LoadImage(NULL, IDC_WAIT, IMAGE_CURSOR, 0, 0, LR_SHARED);	// LoadImageでIMAGE_CURSORをロードし, ハンドルをhCursorに格納.

				// ウェイトカーソルをセット.
				hOldCursor = SetCursor(hCursor);	// SetCursorにhCursorをセットし, 以前のカーソルはhOldCursorに格納.

				// ウィンドウ作成成功
				return 0;	// return文で0を返して, ウィンドウ作成成功とする.

			}

			// 既定の処理へ向かう.
			break;	// breakで抜けて, 既定の処理(DefWindowProc)へ向かう.

		// ウィンドウが破棄された時.
		case WM_DESTROY:	// ウィンドウが破棄された時.(uMsgがWM_DESTROYの時.)

			// WM_DESTROYブロック
			{

				// 以前のカーソルに戻す.
				SetCursor(hOldCursor);	// SetCursorにhOldCursorをセット.

				// 終了メッセージの送信.
				PostQuitMessage(0);	// PostQuitMessageで終了コードを0としてWM_QUITメッセージを送信.(するとメッセージループのGetMessageの戻り値が0になるので, メッセージループから抜ける.)

			}

			// 既定の処理へ向かう.
			break;	// breakで抜けて, 既定の処理(DefWindowProc)へ向かう.

		// 上記以外の時.
		default:	// 上記以外の値の時の既定処理.

			// 既定の処理へ向かう.
			break;	// breakで抜けて, 既定の処理(DefWindowProc)へ向かう.

	}

	// あとは既定の処理に任せる.
	return DefWindowProc(hwnd, uMsg, wParam, lParam);	// 戻り値も含めDefWindowProcに既定の処理を任せる.

}

WM_CREATEで、ウェイトカーソル(砂時計というか作業待ちのカーソルね。)をロードしてセット。

ただ、これは一瞬で元に戻ってしまうので、わからない。
ただ、これは一瞬で元に戻ってしまうので、わからない。

ただ、これは一瞬で元に戻ってしまうので、わからない。
そこで、

左クリックで、ウェイトカーソルをセットして、5秒待つようにする。

最初はこうだけどクリックすると
最初はこうだけどクリックすると

最初はこうだけどクリックすると、

作業待ち状態になる
作業待ち状態になる

作業待ち状態になる。

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

SetClassLong

SetWindowLongでウィンドウにさまざまな値をセットしてきたが、SetClassLongでウィンドウクラスに値をセットすることもできる。

SetClassLongA function (winuser.h) - Win32 apps | Microsoft Docs
ウィンドウの設定

SetClassLong.cppで、普通にウィンドウ表示のプログラムを書く。

// ヘッダファイルのインクルード
// 既定のヘッダファイル
#include <windows.h>	// 標準WindowsAPI
#include <tchar.h>		// TCHAR型

// 関数のプロトタイプ宣言
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);	// ウィンドウメッセージに対して独自の処理をするように定義したコールバック関数WindowProc.

// _tWinMain関数の定義
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd){

	// 変数・配列の宣言と初期化.
	HWND hWnd;							// CreateWindowで作成したウィンドウのウィンドウハンドルを格納するHWND型変数hWnd.
	MSG msg;							// ウィンドウメッセージ情報を格納するMSG構造体型変数msg.
	WNDCLASS wc;						// ウィンドウクラス情報をもつWNDCLASS構造体型変数wc.

	// ウィンドウクラスの設定
	wc.lpszClassName = _T("SetClassLong");					// ウィンドウクラス名は"SetClassLong".
	wc.style = CS_HREDRAW | CS_VREDRAW;						// スタイルはCS_HREDRAW | CS_VREDRAW.
	wc.lpfnWndProc = WindowProc;							// ウィンドウプロシージャは独自の処理を定義したWindowProc.
	wc.hInstance = hInstance;								// インスタンスハンドルは_tWinMainの引数.
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);				// アイコンはアプリケーション既定のもの.
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);				// カーソルは矢印.
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	// 背景は白ブラシ.
	wc.lpszMenuName = NULL;									// なし
	wc.cbClsExtra = 0;										// 0でいい.
	wc.cbWndExtra = 0;										// 0でいい.

	// ウィンドウクラスの登録
	if (!RegisterClass(&wc)) {	// RegisterClassでウィンドウクラスを登録し, 0が返ったらエラー.

		// エラー処理
		MessageBox(NULL, _T("RegisterClass Failure!"), _T("SetClassLong"), MB_OK | MB_ICONHAND);	// MessageBoxで"RegisterClass Failure!"とエラーメッセージを表示.
		return -1;	// 異常終了(1)

	}

	// ウィンドウの作成
	hWnd = CreateWindow(_T("SetClassLong"), _T("SetClassLong"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);	// CreateWindowで, 上で登録した"SetClassLong"ウィンドウクラスのウィンドウを作成.
	if (hWnd == NULL) {	// ウィンドウの作成に失敗したとき.

		// エラー処理
		MessageBox(NULL, _T("CreateWindow Failure!"), _T("SetClassLong"), MB_OK | MB_ICONHAND);	// MessageBoxで"CreateWindow Failure!"とエラーメッセージを表示.
		return -2;	// 異常終了(2)

	}

	// ウィンドウの表示
	ShowWindow(hWnd, SW_SHOW);	// ShowWindowでSW_SHOWを指定してウィンドウの表示.

	// メッセージループ
	while (GetMessage(&msg, NULL, 0, 0) > 0) {	// GetMessageでメッセージを取得, 戻り値が0より大きい間はループし続ける.

		// ウィンドウメッセージ処理
		TranslateMessage(&msg);	// TranslateMessageで仮想キーメッセージを文字メッセージへ変換.
		DispatchMessage(&msg);	// DispatchMessageで受け取ったメッセージをウィンドウプロシージャ(この場合は独自に定義したWindowProc)に送出.

	}

	// プログラムの終了
	return (int)msg.wParam;	// 終了コード(msg.wParam)を戻り値として返す.

}

// WindowProc関数の定義
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {	// ウィンドウメッセージに対して独自の処理をするように定義したウィンドウプロシージャ.

	// ウィンドウメッセージに対する処理.
	switch (uMsg) {	// switch-casa文でuMsgの値ごとに処理を振り分ける.

		// ウィンドウの作成が開始された時.
		case WM_CREATE:		// ウィンドウの作成が開始された時.(uMsgがWM_CREATEの時.)

			// WM_CREATEブロック
			{

				// ウィンドウ作成成功
				return 0;	// return文で0を返して, ウィンドウ作成成功とする.

			}

			// 既定の処理へ向かう.
			break;	// breakで抜けて, 既定の処理(DefWindowProc)へ向かう.

		// ウィンドウが破棄された時.
		case WM_DESTROY:	// ウィンドウが破棄された時.(uMsgがWM_DESTROYの時.)

			// WM_DESTROYブロック
			{

				// 終了メッセージの送信.
				PostQuitMessage(0);	// PostQuitMessageで終了コードを0としてWM_QUITメッセージを送信.(するとメッセージループのGetMessageの戻り値が0になるので, メッセージループから抜ける.)

			}

			// 既定の処理へ向かう.
			break;	// breakで抜けて, 既定の処理(DefWindowProc)へ向かう.

		// 上記以外の時.
		default:	// 上記以外の値の時の既定処理.

			// 既定の処理へ向かう.
			break;	// breakで抜けて, 既定の処理(DefWindowProc)へ向かう.

	}

	// あとは既定の処理に任せる.
	return DefWindowProc(hwnd, uMsg, wParam, lParam);	// 戻り値も含めDefWindowProcに既定の処理を任せる.

}

これだと、ウィンドウクラスの設定で背景は白ブラシにしているので、

背景は白になる
背景は白になる

背景は白になる。
これを、

WM_CREATEで黒ブラシを取得し、SetClassLongのGCL_HBRBACKGROUNDでセットする。

そうすると起動時の背景が黒ブラシになる
そうすると起動時の背景が黒ブラシになる

そうすると起動時の背景が黒ブラシになる。

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

RemoveProp

RemovePropで、削除できる。

RemovePropA function (winuser.h) - Win32 apps | Microsoft Docs
データの関連付け

ウィンドウ破棄時に、削除はしておいたほうがいいらしいので。
RemoveProp.cppのWM_DESTROYで、

RemovePropした後、そのキーでGetPropして、NULLなら削除されているということ。

この時点ではテキストを取得出来て描画出来てる
この時点ではテキストを取得出来て描画出来てる

この時点ではテキストを取得出来て描画出来てる。
閉じると、

1つ目は削除されてる
1つ目は削除されてる

1つ目は削除されてる。

2つ目も削除されてる
2つ目も削除されてる

2つ目も削除されてる。

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

SetProp

SetPropは、キーと値のペアで登録するので、複数登録することもできる。

SetPropA function (winuser.h) - Win32 apps | Microsoft Docs
データの関連付け

SetProp.cppのWinMainで、

キーが"UserData1"で値が"ABCDE"、キーが"UserData2"で値が"FGHIJ"、という2つのペアをSetPropで登録。
WM_PAINTでは、

それぞれのキーで文字列を取り出し。

どちらも取り出して描画できた。
どちらも取り出して描画できた。

どちらも取り出して描画できた。

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

GetProp

ウィンドウにデータをセットする方法は、SetPropとGetPropを使う方法もある。

GetPropA function (winuser.h) - Win32 apps | Microsoft Docs
データの関連付け

GetProp.cppのWinMainで、

SetPropで"UserData1"をキーとしてtszUserData1を登録。
WM_PAINTで、

"UserData1"をキーにして、GetPropで文字列を取得し、TextOutで描画。

前回と変わらずテキストを取得して描画できる。
前回と変わらずテキストを取得して描画できる。

前回と変わらずテキストを取得して描画できる。

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

GWL_USERDATA

ウィンドウに、何らかのデータをセットということは、GWL_USERDATAでも出来る。

GetWindowLongA function (winuser.h) - Win32 apps | Microsoft Docs

GWL_USERDATA.cppのWinMainで、

SetWindowLongのGWL_USERDATAで、文字列"ABCDE"をセットしたtszUserDataを、hWndにセット。
WindowProcのWM_PAINTで、

GetWindowLongのGWL_USERDATAから文字列を取得して、TextOutで描画。

こんな感じでウィンドウにセットされた文字列を描画
こんな感じでウィンドウにセットされた文字列を描画

こんな感じでウィンドウにセットされた文字列を描画。

Sample/winapi/GetWindowLong/GWL_USERDATA/src/GWL_USERDATA at master · bg1bgst333/Sample · GitHub