Skip to content

Commit 2d8e803

Browse files
kcinickgxclaude
andcommitted
Add a dark theme for the Options dialog
Makes the Options property sheet (the "O" dialog) follow the dark look of the rest of the player instead of always rendering in the light system style. It covers the whole dialog: the navigation tree, the property pages, group boxes, edits/combos, list controls, spin buttons, sliders, tab headers, checkboxes and the scrollbars (flat, drawn through the bundled CoolSB, matching the playlist). The sheet also re-themes live when the setting is toggled while it is open. Everything is gated on the existing "Use the 'dark' theme" setting (bUseDarkTheme) and reuses the existing ThemeRGB() palette, so when the flag is off every control falls back to its original light appearance and there is no behavioural change. A new helper (controls/DarkTheme.*) centralises the theming so most of the ~26 pages are covered from CPPageBase / CPPageSheet. Small, flag-gated tweaks are made to the bundled coolsb (expose one global as extern so the header can be included from more than one TU) and to the TreePropSheet page frame (dark caption/background colours). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent e1cb640 commit 2d8e803

32 files changed

Lines changed: 6465 additions & 4054 deletions

src/ExtLib/ui/TreePropSheet/PropPageFrameDefault.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ BEGIN_MESSAGE_MAP(CPropPageFrameDefault, CWnd)
175175
//}}AFX_MSG_MAP
176176
END_MESSAGE_MAP()
177177

178+
// <MPC-BE Custom Code>
179+
bool CPropPageFrameDefault::s_bDarkMode = false;
180+
COLORREF CPropPageFrameDefault::s_clrFace = RGB(37, 42, 47);
181+
COLORREF CPropPageFrameDefault::s_clrText = RGB(179, 184, 189);
182+
// </MPC-BE Custom Code>
183+
178184

179185
CPropPageFrameDefault::CPropPageFrameDefault()
180186
{
@@ -299,9 +305,22 @@ CRect CPropPageFrameDefault::CalcCaptionArea()
299305
void CPropPageFrameDefault::DrawCaption(CDC *pDc, CRect rect, LPCTSTR lpszCaption, HICON hIcon)
300306
{
301307
// <MPC-BE Custom Code>
302-
COLORREF clrLeft = GetSysColor(COLOR_ACTIVECAPTION);
308+
auto Lighten = [](COLORREF c, int d) -> COLORREF {
309+
int r = GetRValue(c) + d; if (r > 255) { r = 255; }
310+
int g = GetGValue(c) + d; if (g > 255) { g = 255; }
311+
int b = GetBValue(c) + d; if (b > 255) { b = 255; }
312+
return RGB(r, g, b);
313+
};
314+
315+
COLORREF clrLeft;
316+
COLORREF clrRight;
317+
if (s_bDarkMode) {
318+
clrLeft = clrRight = Lighten(s_clrFace, 14); // subtle header band above the page
319+
} else {
320+
clrLeft = GetSysColor(COLOR_ACTIVECAPTION);
321+
clrRight = pDc->GetPixel(rect.right-1, rect.top);
322+
}
303323
// </MPC-BE Custom Code>
304-
COLORREF clrRight = pDc->GetPixel(rect.right-1, rect.top);
305324
FillGradientRectH(pDc, rect, clrLeft, clrRight);
306325

307326
// draw icon
@@ -317,7 +336,7 @@ void CPropPageFrameDefault::DrawCaption(CDC *pDc, CRect rect, LPCTSTR lpszCaptio
317336
// draw text
318337
rect.left += 2;
319338

320-
COLORREF clrPrev = pDc->SetTextColor(GetSysColor(COLOR_CAPTIONTEXT));
339+
COLORREF clrPrev = pDc->SetTextColor(s_bDarkMode ? s_clrText : GetSysColor(COLOR_CAPTIONTEXT));
321340
int nBkStyle = pDc->SetBkMode(TRANSPARENT);
322341
CFont *pFont = (CFont*)pDc->SelectStockObject(SYSTEM_FONT);
323342

@@ -405,6 +424,15 @@ void CPropPageFrameDefault::OnPaint()
405424

406425
BOOL CPropPageFrameDefault::OnEraseBkgnd(CDC* pDC)
407426
{
427+
// <MPC-BE Custom Code>
428+
if (s_bDarkMode) {
429+
CRect rect;
430+
GetClientRect(rect);
431+
pDC->FillSolidRect(rect, s_clrFace);
432+
return TRUE;
433+
}
434+
// </MPC-BE Custom Code>
435+
408436
if (g_ThemeLib.IsAvailable() && g_ThemeLib.IsThemeActive())
409437
{
410438
HTHEME hTheme = g_ThemeLib.OpenThemeData(m_hWnd, L"Tab");

src/ExtLib/ui/TreePropSheet/PropPageFrameDefault.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ class /*AFX_EXT_CLASS*/ CPropPageFrameDefault : public CWnd,
4646
CPropPageFrameDefault();
4747
virtual ~CPropPageFrameDefault();
4848

49+
// <MPC-BE Custom Code>
50+
// Dark theme palette, set by the host (CPPageSheet) before the frame paints.
51+
// When s_bDarkMode is false the classic (system-colored) appearance is used.
52+
public:
53+
static bool s_bDarkMode;
54+
static COLORREF s_clrFace;
55+
static COLORREF s_clrText;
56+
// </MPC-BE Custom Code>
57+
4958
// operations
5059
public:
5160

src/ExtLib/ui/coolsb/coolsblib.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737

3838
static TCHAR szPropStr[] = _T("CoolSBSubclassPtr");
3939

40+
// Single definition of the theme-colour callback (declared extern in coolscroll.h so the
41+
// header can be included from more than one translation unit without a duplicate symbol).
42+
ptr_themeRGB fThemeRGB = NULL;
43+
4044
LRESULT CALLBACK CoolSBWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
4145

4246
SCROLLWND *GetScrollWndFromHwnd(HWND hwnd)

src/ExtLib/ui/coolsb/coolscroll.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ int WINAPI CoolSB_SetScrollPos (HWND hwnd, int nBar, int nPos, BOOL fRedraw);
143143
int WINAPI CoolSB_SetScrollRange (HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw);
144144
BOOL WINAPI CoolSB_ShowScrollBar (HWND hwnd, int wBar, BOOL fShow);
145145

146-
ptr_themeRGB fThemeRGB;
146+
extern ptr_themeRGB fThemeRGB;
147147

148148
//
149149
// Scrollbar dimension functions

src/apps/mplayerc/PPageAccelTbl.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "stdafx.h"
2323
#include "PPageAccelTbl.h"
24+
#include "controls/DarkTheme.h"
2425

2526
//#define MASK_NUMBER 0xFFF
2627
#define DUP_KEY (1<<12)
@@ -839,11 +840,20 @@ void CPPageAccelTbl::OnCustomdrawList( NMHDR* pNMHDR, LRESULT* pResult )
839840
auto itemData = (ITEMDATA*)m_list.GetItemData(pLVCD->nmcd.dwItemSpec);
840841
auto dup = itemData->flag;
841842

842-
if (pLVCD->iSubItem == COL_CMD && dup
843+
const bool isDup = (pLVCD->iSubItem == COL_CMD && dup
843844
|| pLVCD->iSubItem == COL_KEY && (dup & DUP_KEY)
844845
|| pLVCD->iSubItem == COL_APPCMD && (dup & DUP_APPCMD)
845-
|| pLVCD->iSubItem == COL_RMCMD && (dup & DUP_RMCMD)) {
846+
|| pLVCD->iSubItem == COL_RMCMD && (dup & DUP_RMCMD));
847+
848+
if (isDup) {
846849
pLVCD->clrTextBk = RGB(255, 130, 120);
850+
if (DarkTheme::IsActive()) {
851+
pLVCD->clrText = RGB(0, 0, 0); // keep the text readable on the highlight
852+
}
853+
}
854+
else if (DarkTheme::IsActive()) {
855+
pLVCD->clrTextBk = DarkTheme::FaceColor();
856+
pLVCD->clrText = DarkTheme::TextColor();
847857
}
848858
else {
849859
pLVCD->clrTextBk = GetSysColor(COLOR_WINDOW);

src/apps/mplayerc/PPageBase.cpp

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "stdafx.h"
2323
#include "MainFrm.h"
2424
#include "PPageBase.h"
25+
#include "controls/DarkTheme.h"
2526

2627
// CPPageBase dialog
2728

@@ -79,6 +80,9 @@ BOOL CPPageBase::PreTranslateMessage(MSG* pMsg)
7980

8081
BEGIN_MESSAGE_MAP(CPPageBase, CCmdUIPropertyPage)
8182
ON_WM_DESTROY()
83+
ON_WM_CTLCOLOR()
84+
ON_WM_ERASEBKGND()
85+
ON_WM_DRAWITEM()
8286
END_MESSAGE_MAP()
8387

8488
// CPPageBase message handlers
@@ -87,7 +91,84 @@ BOOL CPPageBase::OnSetActive()
8791
{
8892
AfxGetAppSettings().nLastUsedPage = (UINT)(ULONG_PTR)m_pPSP->pszTemplate;
8993

90-
return __super::OnSetActive();
94+
BOOL bRet = __super::OnSetActive();
95+
96+
// Re-apply the dark visual style on every activation. It is idempotent (controls
97+
// already themed are skipped), and doing it each time avoids a race on the page
98+
// shown first, whose controls may not have been ready the very first time.
99+
DarkTheme::ApplyThemeToChildren(GetSafeHwnd());
100+
101+
return bRet;
102+
}
103+
104+
HBRUSH CPPageBase::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
105+
{
106+
HBRUSH hbr = __super::OnCtlColor(pDC, pWnd, nCtlColor);
107+
108+
if (HBRUSH hbrDark = DarkTheme::OnCtlColor(pDC, nCtlColor)) {
109+
return hbrDark;
110+
}
111+
112+
return hbr;
113+
}
114+
115+
BOOL CPPageBase::OnEraseBkgnd(CDC* pDC)
116+
{
117+
if (DarkTheme::IsActive()) {
118+
CRect rc;
119+
GetClientRect(rc);
120+
pDC->FillSolidRect(rc, DarkTheme::FaceColor());
121+
return TRUE;
122+
}
123+
124+
return __super::OnEraseBkgnd(pDC);
125+
}
126+
127+
// The horizontal separator lines in the option pages are owner-drawn statics
128+
// (SS_OWNERDRAW) so Windows does not paint its light 3D etched line. We draw them
129+
// here: a flat line in the shared border colour when the dark theme is active, or
130+
// the classic etched edge otherwise.
131+
void CPPageBase::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
132+
{
133+
if (lpDrawItemStruct && lpDrawItemStruct->CtlType == ODT_STATIC) {
134+
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
135+
CRect rc(lpDrawItemStruct->rcItem);
136+
if (DarkTheme::IsActive()) {
137+
pDC->FillSolidRect(rc, DarkTheme::FaceColor());
138+
pDC->FillSolidRect(rc.left, rc.top + rc.Height() / 2, rc.Width(), 1, DarkTheme::CtrlBorderColor());
139+
} else {
140+
pDC->FillSolidRect(rc, GetSysColor(COLOR_3DFACE));
141+
::DrawEdge(lpDrawItemStruct->hDC, &rc, EDGE_ETCHED, BF_TOP);
142+
}
143+
return;
144+
}
145+
146+
__super::OnDrawItem(nIDCtl, lpDrawItemStruct);
147+
}
148+
149+
BOOL CPPageBase::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
150+
{
151+
// For NM_CUSTOMDRAW, let any page-specific handler run first (e.g. colour-picker
152+
// buttons that paint themselves with the selected colour, or list controls). Only
153+
// when the page does not handle it do we apply the generic dark theming for the
154+
// controls native dark mode leaves light: trackbar (slider) channels, checkbox/
155+
// radio-button captions and push buttons. (Group boxes are handled by subclassing,
156+
// since they emit no NM_CUSTOMDRAW.)
157+
NMHDR* pNMHDR = reinterpret_cast<NMHDR*>(lParam);
158+
if (pNMHDR && pNMHDR->code == NM_CUSTOMDRAW) {
159+
if (__super::OnNotify(wParam, lParam, pResult)) {
160+
return TRUE;
161+
}
162+
if (DarkTheme::TrackbarCustomDraw(pNMHDR, pResult)) {
163+
return TRUE;
164+
}
165+
if (DarkTheme::ButtonCustomDraw(pNMHDR, pResult)) {
166+
return TRUE;
167+
}
168+
return FALSE;
169+
}
170+
171+
return __super::OnNotify(wParam, lParam, pResult);
91172
}
92173

93174
void CPPageBase::OnDestroy()

src/apps/mplayerc/PPageBase.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ class CPPageBase : public CCmdUIPropertyPage
3434
CToolTipCtrl m_wndToolTip;
3535
void CreateToolTip();
3636

37+
// dark theme: apply the dark visual style to child controls once, on first activation
38+
bool m_bDarkThemeApplied = false;
39+
3740
public:
3841
CPPageBase(UINT nIDTemplate, UINT nIDCaption = 0);
3942
virtual ~CPPageBase();
@@ -43,11 +46,15 @@ class CPPageBase : public CCmdUIPropertyPage
4346
virtual BOOL PreTranslateMessage(MSG* pMsg);
4447
virtual BOOL OnSetActive();
4548
virtual BOOL OnApply();
49+
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
4650

4751
int ScaleY(int y);
4852

4953
DECLARE_MESSAGE_MAP()
5054

5155
public:
5256
afx_msg void OnDestroy();
57+
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
58+
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
59+
afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
5360
};

src/apps/mplayerc/PPageExternalFilters.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "PPageBase.h"
2525
#include "controls/FloatEdit.h"
26+
#include "controls/DarkCheckListBox.h"
2627

2728
bool IsSupportedExternalVideoRenderer(CLSID clsid);
2829

@@ -46,7 +47,7 @@ class CPPageExternalFilters : public CPPageBase
4647

4748
enum { IDD = IDD_PPAGEEXTERNALFILTERS };
4849

49-
CCheckListBox m_filters;
50+
CDarkCheckListBox m_filters;
5051
int m_iLoadType = FilterOverride::PREFERRED;
5152
CHexEdit m_dwMerit;
5253
CTreeCtrl m_tree;

0 commit comments

Comments
 (0)