Windows 10 以降でダークモードが標準機能となり、ユーザーからの対応要望が増えています。しかし MFC にはダークモードを直接サポートする API がなく、実装には工夫が必要です。
この記事では、MFC アプリへのダークモード対応の課題と実装方法を解説します。
目次
なぜ MFC では難しいのか
- 標準コントロール(ボタン、エディット、リストボックス等)の背景色は Windows が描画する
- MFC のコモンコントロールは GDI ベースで、テーマ変更の仕組みが限定的
- タイトルバーや一部のコントロールは、Windows のバージョンや標準テーマ描画の影響を受ける
特に注意したいのは、「背景だけ黒くすれば終わり」ではない点です。Static、Edit、ListBox は OnCtlColor である程度合わせられますが、Button のように標準テーマ描画の影響が強い部品は、見た目を完全に揃えるにはオーナードローや別コントロール化が必要になります。

ダークモードの検出
bool IsWindowsDarkMode()
{
DWORD dwValue = 0;
DWORD dwSize = sizeof(dwValue);
LSTATUS status = RegGetValue(
HKEY_CURRENT_USER,
_T("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"),
_T("AppsUseLightTheme"),
RRF_RT_DWORD, nullptr, &dwValue, &dwSize);
return (status == ERROR_SUCCESS && dwValue == 0);
}
WM_SETTINGCHANGE メッセージを監視すると、ユーザーがテーマを変更したタイミングを検出できます。
void CMainFrame::OnSettingChange(UINT, LPCTSTR lpszSection)
{
if (lpszSection && CString(lpszSection) == _T("ImmersiveColorSet"))
{
ApplyDarkMode();
}
}
背景色のカスタマイズ
// Static / Edit / ListBox などの色を変更
HBRUSH CMyFrame::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if (m_bDarkMode)
{
pDC->SetTextColor(RGB(240, 240, 240));
pDC->SetBkColor(RGB(48, 48, 48));
if (nCtlColor == CTLCOLOR_STATIC ||
nCtlColor == CTLCOLOR_EDIT ||
nCtlColor == CTLCOLOR_LISTBOX)
{
return m_brControlDark;
}
}
return __super::OnCtlColor(pDC, pWnd, nCtlColor);
}
この方法で塗り替えやすい部品もありますが、ボタンやタブなどは標準テーマ描画の都合で一部だけ明るく残ることがあります。そこが MFC ダークモード対応の難所です。
タイトルバーのダーク化
タイトルバーは DwmSetWindowAttribute でダーク表示を指定できます。ただし、DWMWA_USE_IMMERSIVE_DARK_MODE の扱いは Windows のバージョンによって差があります。アプリ全体のダークモード対応とは分けて、補助的な見た目調整として扱うのが安全です。
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
void SetDarkTitleBar(HWND hWnd, BOOL bDark)
{
BOOL bValue = bDark;
DwmSetWindowAttribute(hWnd,
DWMWA_USE_IMMERSIVE_DARK_MODE,
&bValue,
sizeof(bValue));
}
現実的なアプローチ
- タイトルバーのダーク化は、対応環境で使える補助的な見た目調整として扱う
- メインエリアの背景色は
OnCtlColor/OnEraseBkgndで対応 - 標準コントロールの完全なダーク化はオーナードローが必要になる場合がある
- 完璧を目指すよりも、主要な背景色とテキスト色の対応から始めるのが現実的
まとめ
- MFC にはダークモードの直接サポートはないが、段階的に対応可能
- レジストリと
WM_SETTINGCHANGEでダークモードを検出する - タイトルバーのダーク化は、対応環境で使える補助的な調整として扱う
- コントロールの色変更は
OnCtlColorを起点にカスタマイズする
