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を起点にカスタマイズする
