Skip to content

Instantly share code, notes, and snippets.

@ajtruckle
Created January 31, 2025 12:59
Show Gist options
  • Save ajtruckle/a37f26292dc72824d7f48b31d3c7a3e7 to your computer and use it in GitHub Desktop.
Save ajtruckle/a37f26292dc72824d7f48b31d3c7a3e7 to your computer and use it in GitHub Desktop.
Support MFC Group Box Control in Dark Mode
#include "pch.h"
#include "MyStatic.h"
BEGIN_MESSAGE_MAP(CMyStatic, CStatic)
ON_WM_PAINT()
END_MESSAGE_MAP()
void CMyStatic::OnPaint() {
CPaintDC dc(this); // Device context for painting
// Get the text to display
CString text;
GetWindowText(text);
// Get the client area
CRect rect;
GetClientRect(&rect);
// Use the same font as the parent window (dialog)
CFont* pOldFont = dc.SelectObject(GetParent()->GetFont());
// Calculate the text height
CSize textSize = dc.GetTextExtent(text);
int textHeight = textSize.cy;
// Adjust the frame position so the top border intersects the middle of the text
rect.top += textHeight / 2;
// Draw the group box border
// dc.DrawEdge(&rect, EDGE_ETCHED, BF_RECT);
// Draw a 1-pixel-thick frame
CPen pen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW)); // Use a 1-pixel pen
CPen* pOldPen = dc.SelectObject(&pen);
// Draw the top border
dc.MoveTo(rect.left, rect.top);
dc.LineTo(rect.left + 8, rect.top); // Leave space for the text
dc.MoveTo(rect.left + 8 + textSize.cx, rect.top); // Resume after the text
dc.LineTo(rect.right, rect.top);
// Draw the bottom border
dc.MoveTo(rect.left, rect.bottom - 1);
dc.LineTo(rect.right, rect.bottom - 1);
// Draw the left border
dc.MoveTo(rect.left, rect.top);
dc.LineTo(rect.left, rect.bottom - 1);
// Draw the right border
dc.MoveTo(rect.right - 1, rect.top);
dc.LineTo(rect.right - 1, rect.bottom - 1);
// Restore the old pen
dc.SelectObject(pOldPen);
// Set the text color and background mode
dc.SetTextColor(m_textColor);
dc.SetBkMode(OPAQUE); // Use OPAQUE mode to draw the text with a background
// Get the system background color for dialogs (typically COLOR_3DFACE or COLOR_BTNFACE)
// COLORREF bgColor = GetSysColor(COLOR_3DFACE);
COLORREF bgColor = RGB(32, 32, 32);
// Set the background color for the text
dc.SetBkColor(bgColor);
// Calculate the text position
rect.left += 8; // Indent the text slightly
rect.top -= textHeight / 2; // Move the text back up to its original position
// Draw the text with a background to mask out the border
dc.DrawText(text, &rect, DT_LEFT | DT_TOP | DT_SINGLELINE);
// Restore the old font
dc.SelectObject(pOldFont);
}
#pragma once
#include <afxwin.h> // Include MFC headers
class CMyStatic : public CStatic
{
public:
CMyStatic() : m_textColor(RGB(255, 255, 255)) {} // Default to white text
void SetTextColor(COLORREF color) {
m_textColor = color;
if (m_hWnd != nullptr) {
Invalidate(); // Force the control to redraw
}
}
protected:
COLORREF m_textColor;
DECLARE_MESSAGE_MAP()
afx_msg void OnPaint(); // Handle WM_PAINT
};
// TestDarkMode.h : main header file for the PROJECT_NAME application
//
#pragma once
#ifndef __AFXWIN_H__
#error "include 'pch.h' before including this file for PCH"
#endif
#include "resource.h" // main symbols
#include <windows.h>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
// CTestDarkModeApp:
// See TestDarkMode.cpp for the implementation of this class
//
class CTestDarkModeApp : public CWinApp
{
public:
CTestDarkModeApp();
// Overrides
public:
virtual BOOL InitInstance();
// Implementation
DECLARE_MESSAGE_MAP()
public:
static BOOL AllowDarkModeForWindow(HWND hWnd, BOOL allow)
{
if (!hWnd)
return FALSE;
// Use DwmSetWindowAttribute to enable or disable dark mode
return SUCCEEDED(DwmSetWindowAttribute(hWnd, 20, &allow, sizeof(allow)));
}
};
extern CTestDarkModeApp theApp;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment