【MFC】OnCtlColor: コントロールの背景色を変える

【MFC】OnCtlColor: コントロールの背景色を変える

ダイアログのエディットボックスやスタティックテキストの背景色を変えたいとき、WPF や HTML なら CSS で一行ですが、MFC では WM_CTLCOLOR メッセージをハンドルする必要があります。
OnCtlColor を使うと、背景色と文字色をコントロールごとに切り替えられます。

検証環境:Visual Studio 2026 / MFC / x64


目次

OnCtlColor の仕組み

コントロールが描画される直前に、親ウィンドウ(ダイアログ)に WM_CTLCOLOR メッセージが送られます。このハンドラでテキスト色・背景色・背景ブラシを指定できます。

次の実行結果では、入力エラーのエディット、対応状況のスタティック、確認メモのリストボックスに OnCtlColor を適用しています。確認が必要な情報だけを自然に目立たせられることが見て取れます。

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 で再描画を要求します
目次