diff foosdk/sdk/libPPUI/DarkMode.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/libPPUI/DarkMode.h	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,112 @@
+#pragma once
+#include <functional>
+#include <list>
+
+namespace DarkMode {
+	// Is dark mode supported on this system or not?
+	bool IsSupportedSystem();
+	// Is system in dark mode or not?
+	bool QueryUserOption();
+	
+	// Darken menus etc app-wide
+	void SetAppDarkMode(bool bDark);
+	// Darken window title bar
+	void UpdateTitleBar(HWND wnd, bool bDark );
+	void ApplyDarkThemeCtrl(HWND ctrl, bool bDark, const wchar_t * ThemeID = L"Explorer");
+	void ApplyDarkThemeCtrl2(HWND ctrl, bool bDark, const wchar_t* ThemeID_light = L"Explorer", const wchar_t* ThemeID_dark = L"DarkMode_Explorer");
+	void AllowDarkModeForWindow(HWND wnd, bool bDark);
+
+	// One-shot version of darkening function for editboxes
+	void DarkenEditLite(HWND ctrl);
+	// One-shot version of darkening function for comboboxes
+	void DarkenComboLite(HWND ctrl);
+
+	// Returns if the dialog appears to be using dark mode (text brighter than background)
+	bool IsDialogDark(HWND dlg, UINT msgSend = WM_CTLCOLORDLG);
+	// Returns if the DC appears to be using dark mode (text brighter than background)
+	bool IsDCDark(HDC dc);
+	
+	// Returns if these colors (text, background) look like dark theme
+	bool IsThemeDark(COLORREF text, COLORREF background);
+
+	COLORREF GetSysColor(int, bool bDark = true);
+
+	LRESULT CustomDrawToolbar(NMHDR*);
+	// Custom draw handler that paints registered darkened controls.
+	// Can be used with NOTIFY_CODE_HANDLER() directly
+	LRESULT OnCustomDraw(int, NMHDR*, BOOL & bHandled);
+
+	// Handle WM_NCPAINT drawing dark frame
+	void NCPaintDarkFrame(HWND ctrl, HRGN rgn);
+
+	bool IsHighContrast();
+
+	// msgSetDarkMode
+	// return 1 if understood, 0 otherwise
+	// WPARAM = 0, DISABLE dark mode
+	// WPARAM = 1, ENABLE dark mode
+	// WPARAM = -1, query if supported
+	UINT msgSetDarkMode();
+
+	//! CHooks class: entrypoint class for all Dark Mode hacks. \n
+	//! Usage: Keep CHooks m_dark = detectDarkMode(); as a member of your window class, replacing detectDarkMode() with your own function returning dark mode on/off state. \n
+	//! When initializing your window (WM_CREATE, WM_INITDIALOG), call m_dark.AddDialogWithControls(m_hWnd); \n
+	//! AddDialogWithControls() walks all child windows of your window; call other individual methods to finetune handling of Dark Mode if that's not acceptable in your case.
+	class CHooks {
+	public:
+		CHooks(bool enabled = false) : m_dark(enabled) {}
+		CHooks(const CHooks&) = delete;
+		void operator=(const CHooks&) = delete;
+
+		void AddDialog(HWND);
+		void AddTabCtrl(HWND);
+		void AddComboBox(HWND);
+		void AddComboBoxEx(HWND);
+		void AddButton(HWND);
+		void AddEditBox(HWND);
+		void AddPopup(HWND);
+		void AddStatusBar(HWND);
+		void AddScrollBar(HWND);
+		void AddToolBar(HWND, bool bExplorerTheme = true);
+		void AddReBar(HWND);
+		void AddStatic(HWND);
+		void AddUpDown(HWND);
+		void AddListBox(HWND);
+		void AddListView(HWND);
+		void AddTreeView(HWND);
+		void AddPPListControl(HWND);
+
+
+		// SetWindowTheme with DarkMode_Explorer <=> Explorer
+		void AddGeneric(HWND, const wchar_t * name = L"explorer");
+		// SetWindowTheme(wnd, L"", L"") for dark, Explorer theme for normal
+		void AddClassic(HWND, const wchar_t* normalTheme = L"explorer");
+
+		void AddCtrlAuto(HWND);
+		void AddCtrlMsg(HWND);
+
+		void AddDialogWithControls(HWND);
+		void AddControls(HWND wndParent);
+
+		void SetDark(bool v = true);
+		bool IsDark() const { return m_dark; }
+		operator bool() const { return m_dark; }
+
+		~CHooks() { clear(); }
+		void clear();
+
+		void AddApp();
+	private:
+		template<typename obj_t> void addObj(obj_t* arg) { 
+			m_apply.push_back([arg, this] { arg->SetDark(m_dark); });
+			m_cleanup.push_back([arg] { delete arg; });
+		}
+		void addOp(std::function<void()> f) { f(); m_apply.push_back(f); }
+		bool m_dark = false;
+		std::list<std::function<void()> > m_apply;
+		std::list<std::function<void()> > m_cleanup;
+
+		void flushMoveToBack();
+		std::list<HWND> m_lstMoveToBack;
+	}; 
+}