SetTextColor

SetTextColorは、TextOutなどでテキストを描画するときの文字色を設定する。

SetTextColor function | Microsoft Docs

WindowProcのWM_PAINTで、

TextOutの前に、SetTextColorで、16進数で色を指定した。
第1引数はhDCで、本来、第2引数にはCOLORREFで色を指定するが、実態はただの16進数、ただし、XBGR(ABGRって書いたけど正確にはXBGR)の順なので注意。
最後がffなので赤になるはず。

テキストが赤になった
テキストが赤になった

このようにテキストが赤になった。

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

EN_UPDATE

エディットコントロールの入力内容が変更された直後に、EN_UPDATEが、WM_COMMANDの通知コードとして送られる。

EN_UPDATE notification code - Windows applications | Microsoft Docs

Win32プロジェクト
Win32プロジェクト

Win32プロジェクトで、

空のプロジェクト
空のプロジェクト

空のプロジェクトで、

EN_UPDATE.cpp
EN_UPDATE.cpp

EN_UPDATE.cppを追加。
内容はEM_SETMODIFYベース。

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

Menuリソースを追加。
これもEM_SETMODIFYベース。

で、実はプロジェクト名に"UPDATE"が入っているので、

管理者権限
管理者権限

Windows7ではこのままデバッガ起動できないので、DispatchMessageのプロジェクトから、

app.manifest
app.manifest

app.manifestを持ってくる。

追加のマニフェストファイル
追加のマニフェストファイル

[追加のマニフェストファイル]に追加。

ソースコードの変更点は、

HIWORD(wParam)がEN_UPDATEなら、ウィンドウタイトルを"Modified!"にする。

メニューの"Reset Modify"が選択されたら、元に戻す。

起動時
起動時

起動時、こうなっているが、

"A"と入力
"A"と入力

"A"と入力すると、"Modified!"になってる。

"Reset Modify"
"Reset Modify"

メニューの"Reset Modify"で、

元に戻る。
元に戻る。

元に戻る。

"B"を追加
"B"を追加

"B"を追加すると、"Modified!"になるが、

"Reset Modify"
"Reset Modify"

メニューの"Reset Modify"で、

元に戻る
元に戻る

元に戻る。

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

BN_CLICKED

コントロールの場合、WM_COMMANDが発生した時、リソースIDとは別にどういう操作が行われたかを示す通知コードを返す。
ボタンが押された時には、押されたボタンのリソースIDとともに、BN_CLICKEDという通知コードが返ってくる。

BN_CLICKED notification code - Windows applications | Microsoft Docs

通知コードは、HIWORD(wParam)で取得できるが、メニューは常に0、アクセラレータは常に1になり、コントロールの場合はあらかじめ定められた通知コードになる。

Win32プロジェクト
Win32プロジェクト

Win32プロジェクトで、

空のプロジェクト
空のプロジェクト

空のプロジェクト。

BN_CLICKED.cpp
BN_CLICKED.cpp

BN_CLICKED.cppを追加。
中身は以前WM_CLOSEのトピックで使ったWM_CLOSE.cppをベースにしている。

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

Menuリソースを追加。
これも中身(BN_CLICKED.rcやresource.h)をWM_CLOSEのトピックで使ったものに差し替える。

ソースコードの違いとしては、

メニューアイテムの場合、HIWORD(wParam)は0なので、HIWORD(wParam)の値をOutputDebugStringでデバッグ出力。

ボタンの場合、HIWORD(wParam)はBN_CLICKEDだが、BN_CLICKEDは0なので、前に"BN_CLICKED: "と付けて、HIWORD(wParam)の値をOutputDebugStringでデバッグ出力。

デバッグ開始
デバッグ開始

[デバッグ開始]で、

起動時
起動時

最初はこうだが、

メニューアイテムを選択
メニューアイテムを選択

メニューアイテムを選択すると、

確認
確認

これが出て、OKを押すと終了する。
この時、デバッグ出力は、

メニューアイテムデバッグ出力
メニューアイテムデバッグ出力

こうなっている。
HIWORD(wParam)は0。

デバッグ開始
デバッグ開始

もう一度、デバッグ開始。

ボタンを押す
ボタンを押す

今度はボタンを押すと、

確認
確認

これが出るので、OKで終了する。

この時のデバッグ出力は、

ボタンデバッグ出力
ボタンデバッグ出力

こうなる。
"BN_CLICKED: "の後に、HIWORD(wParam)が出ているが0である。

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

EM_SETMODIFY

EM_GETMODIFYで変更されたかどうかが取得できるわけだが、テキストファイルを保存した直後はそのテキストファイルとエディットコントロールの入力内容は同じなので、変更されていないという状態に戻さないといけない。
EM_SETMODIFYで変更状態のフラグを設定できる。

EM_SETMODIFY message - Windows applications | Microsoft Docs

resource.hで、

リソースIDのID_ITEM_RESET_MODIFYを追加。

EM_SETMODIFY.rcで、

メニューアイテムに”Reset Modify”を追加し、ID_ITEM_RESET_MODIFYを割り当てる。

EM_SETMODIFY.cppでは、

”Reset Modify”が選択されたら、SendMessageの第3引数にFALSEを指定して、EM_SETMODIFYを送る。
これで、変更された状態でもフラグを降ろして、変更されていない状態になる。

起動時
起動時

起動時、この状態で、

Check Modify
Check Modify

"Check Modify"を選択しても、変更されていないので、当然何も起こらない。

"ABCDE"と入力
"ABCDE"と入力

"ABCDE"と入力してから、

Check Modify
Check Modify

"Check Modify"を選択すると、

Modify!
Modify!

変更された状態なので"Modify!"が表示される。

Reset Modify
Reset Modify

ここで、"Reset Modify"を選択してから、

Check Modify
Check Modify

"Check Modify"を選択すると、

何も起こらない
何も起こらない

何も起こらない。
変更状態のフラグが降ろされているからである。
このままウィンドウを閉じても、"Modify!"は表示されない。

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

EM_GETMODIFY

テキストエディタや、なんらかの入力項目を持つアプリで、入力内容に変更があったら、アプリ終了時に内容の保存を促すダイアログが表示されることがあるだろう。
入力内容に変更があったのかどうかを取得するには、EM_GETMODIFYメッセージを使う。

EM_GETMODIFY message - Windows applications | Microsoft Docs

resource.hでは、

今回は、ボタンじゃなくてエディットコントロールなので、ID_EDIT1。

EM_GETMODIFY.rcでは、

リソースIDはID_ITEM_CHECK_MODIFYで、"Check Modify"という表示名のアイテムを用意。

EM_GETMODIFY.cppでは、

WM_CREATEで、リソースIDがID_EDIT1のエディットコントロール作成。

"Check Modify"のアイテムが選択されたら、GetDlgItemでhEditを取得。
SendMessageでhEditにEM_GETMODIFYを送ると、戻り値としてエディットコントロールの内容に変更があったかどうかが返ってくる。
変更されたら"Modify!"と表示する。

WM_CLOSEの時も、同じ処理をする。

実行時は、

実行時
実行時

この状態。

Check Modify
Check Modify

"Check Modify"を選択しても何も起きない。

閉じるボタン
閉じるボタン

閉じるボタンを押しても、何も起きず、ウィンドウは閉じてしまう。

内容変更
内容変更

"ABCDE"を入力して、内容を変更してから、

Check Modify
Check Modify

"Check Modify"すると、

Modify!
Modify!

"Modify!"と表示される。

閉じるボタン
閉じるボタン

閉じるボタンでも、

"Modify!"
"Modify!"

"Modify!"と表示される。

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

WM_CLOSE

WM_CLOSEは、ウィンドウが閉じられる時(DestroyWindowが呼ばれる前)に発生するウィンドウメッセージ。

WM_CLOSE message - Windows applications | Microsoft Docs

WM_CLOSEの時に、DefWindowProcの既定の処理に通さないことで、DestroyWindowによるウィンドウの破棄をキャンセルすることができる。

閉じるボタンを押すと、WM_CLOSEが発生する。
この時、"Close?"というOKCancelなメッセージボックスを表示して、戻り値がIDOKでない場合は、0を返してしまう。
こうすれば、キャンセルボタンが押された時はDefWindowProcを通らないので、その後の既定の処理によりDestroyWindowによるウィンドウ破棄が発生しない。
つまり閉じられない。

右上の閉じるボタン
右上の閉じるボタン

右上の閉じるボタンを押すと、

確認ダイアログ
確認ダイアログ

"Close?"という確認ダイアログが表示される。

"キャンセル"を押すと、

閉じない
閉じない

閉じない。

"OK"を押すと、ウィンドウが閉じて破棄され、プログラムが終了する。

これだけだと、メニューアイテムや、ボタンが押された時に、この確認ダイアログでキャンセルができないので、

メニューアイテムや、ボタンが押された時は、WM_DESTROYのトピックの時のようなDestroyWindowではなく、SendMessageでWM_CLOSEを送信するようにする。
そうすると、WM_CLOSEが発生し、確認ダイアログが表示される。

メニューアイテム
メニューアイテム

メニューアイテム選択でも、

確認ダイアログ
確認ダイアログ

確認ダイアログが出てくるし、

ボタン
ボタン

ボタン押しの時でも、

確認ダイアログ
確認ダイアログ

確認ダイアログが出てくる。
当然、キャンセルの仕組みは同じ。

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

WM_DESTROY

WM_DESTROYは、ウィンドウが破棄された時(DestroyWindowが呼ばれた後)に発生するウィンドウメッセージ。

WM_DESTROY message - Windows applications | Microsoft Docs

DestroyWindowの後に発生しているか確認する。

WM_DESTROYプロジェクト
WM_DESTROYプロジェクト

WM_DESTROYプロジェクトで、

新しい項目
新しい項目

新しい項目で、

WM_DESTROY.cpp
WM_DESTROY.cpp

WM_DESTROY.cppを追加。

リソース
リソース

リソースを追加。

Menu
Menu

Menuリソースを追加。
で、resource.hとWM_DESTROY.rcの中身は、DestroyWindowのトピックのものをそのまま使う。

WM_DESTROY.cppでは、

メニューアイテムが選択された時、ボタンが押された時、それぞれのDestroyWindowの前後にOutputDebugStringでログを出す。

WM_DESTROYが発生した時も、OutputDebugStringでログを出す。

デバッグ開始
デバッグ開始

デバッグ開始で、

メニューアイテム
メニューアイテム

メニューアイテムItem1-1を選択すると、ウィンドウは破棄されて終了する。

ログ
ログ

"ID_ITEM_1_1 before"の後に、DestroyWindowが呼ばれているはずで、その後に"WM_DESTROY"が出力されていて、"ID_ITEM_1_1 after"となっている。

ボタン
ボタン

ボタンButton1も、

ログ
ログ

同じような出力順。

閉じるボタン
閉じるボタン

さて、閉じるボタンはどうだろうか。

閉じた場合
閉じた場合

WM_DESTROYが出ているということは、その前にDestroyWindowによる破棄が行われている可能性がある。
しかし、DestroyWindowの呼び出しは、ここにはない別のメッセージの既定処理で行われている模様。

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