ダイアログのエディットボックスやスタティックテキストの背景色を変えたいとき、WPF や HTML なら CSS で一行ですが、MFC では WM_CTLCOLOR メッセージをハンドルする必要があります。OnCtlColor を使うと、背景色と文字色をコントロールごとに切り替えられます。
検証環境:Visual Studio 2026 / MFC / x64
目次
OnCtlColor の仕組み
コントロールが描画される直前に、親ウィンドウ(ダイアログ)に WM_CTLCOLOR メッセージが送られます。このハンドラでテキスト色・背景色・背景ブラシを指定できます。
次の実行結果では、入力エラーのエディット、対応状況のスタティック、確認メモのリストボックスに OnCtlColor を適用しています。確認が必要な情報だけを自然に目立たせられることが見て取れます。

HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
// 特定のコントロールの色を変更
if (pWnd->GetDlgCtrlID() == IDC_EDIT_WARNING)
{
pDC->SetTextColor(RGB(255, 0, 0)); // 文字色:赤
pDC->SetBkColor(RGB(255, 255, 200)); // 文字背景色:薄黄
return m_brYellow; // コントロール背景のブラシ
}
return hbr;
}
ブラシの準備と破棄
返すブラシはコントロールが描画されるたびに使われるため、OnCtlColor の中でローカルに作成してはいけません。メンバ変数として保持し、ダイアログの破棄時に解放します。
class CMyDlg : public CDialogEx
{
CBrush m_brYellow; // メンバ変数として保持
CBrush m_brRed;
};
BOOL CMyDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
m_brYellow.CreateSolidBrush(RGB(255, 255, 200));
m_brRed.CreateSolidBrush(RGB(255, 200, 200));
return TRUE;
}
// CBrush はデストラクタで自動解放される
nCtlColor で種類を判定する
nCtlColor パラメータで、どのタイプのコントロールかを判定できます。
| 定数 | 対象 |
|---|---|
| CTLCOLOR_EDIT | エディットボックス |
| CTLCOLOR_STATIC | スタティックテキスト、グループボックス、読み取り専用/無効のエディット |
| CTLCOLOR_BTN | ボタン(効果は限定的) |
| CTLCOLOR_DLG | ダイアログ自体の背景 |
| CTLCOLOR_LISTBOX | リストボックス |
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
// すべてのスタティックテキストの色を変更
if (nCtlColor == CTLCOLOR_STATIC)
{
pDC->SetTextColor(RGB(0, 0, 128));
return hbr;
}
return hbr;
}
動的に色を切り替える
条件に応じて色を変えたい場合(エラー時に赤くするなど)、フラグ変数と Invalidate を組み合わせます。
// エラー発生時
m_bError = TRUE;
GetDlgItem(IDC_EDIT_VALUE)->Invalidate(); // 再描画を要求
// OnCtlColor 内
if (pWnd->GetDlgCtrlID() == IDC_EDIT_VALUE && m_bError)
{
pDC->SetTextColor(RGB(255, 0, 0));
pDC->SetBkColor(RGB(255, 220, 220));
return m_brRed;
}
まとめ
OnCtlColorでコントロールの文字色・背景色・背景ブラシを変更できます- 返すブラシはメンバ変数として保持し、毎回作成しないでください
nCtlColorでコントロール種類を、GetDlgCtrlID()で個別コントロールを判定します- 動的に色を変えるには、フラグを設定して
Invalidateで再描画を要求します
