Skip to content

Commit 8de6b92

Browse files
authored
Themed titlebar on Srindows 10+ (#675)
* Themed titlebar on Srindows * Added credit * Removed old code
1 parent 8da4508 commit 8de6b92

File tree

7 files changed

+174
-10
lines changed

7 files changed

+174
-10
lines changed

aui.core/src/AUI/Platform/Entry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ AUI_EXPORT int aui_entry(const AStringVector& args)
7373
int main(int argc, char** argv) { \
7474
return aui_main(argc, argv, aui_entry);\
7575
} \
76-
int __stdcall WinMain( \
76+
int WINAPI WinMain( \
7777
HINSTANCE hInstance, \
7878
HINSTANCE hPrevInstance, \
7979
LPSTR lpCmdLine, \

aui.views/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ if (OPENGL_FOUND OR ANDROID OR IOS)
1212
if(AUIB_DISABLE)
1313
find_package(freetype REQUIRED CONFIG)
1414
else()
15-
auib_import(Freetype https://github.com/freetype/freetype/archive/refs/tags/VER-2-13-3.zip ARCHIVE
15+
auib_import(Freetype https://github.com/freetype/freetype/archive/refs/tags/VER-2-14-1.zip ARCHIVE
1616
CONFIG_ONLY
1717
CMAKE_ARGS -DFT_DISABLE_BZIP2=ON -DFT_DISABLE_PNG=ON -DFT_DISABLE_HARFBUZZ=ON -DFT_DISABLE_BROTLI=ON
1818
)

aui.views/src/AUI/Platform/win32/AWindowsImpl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include <AUI/Util/AViewProfiler.h>
5050
#include <AUI/Platform/AMessageBox.h>
5151
#include <AUI/Platform/win32/AComBase.h>
52+
#include <AUI/Platform/win32/Theme.h>
5253

5354
LRESULT AWindow::winProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
5455
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
@@ -248,6 +249,13 @@ LRESULT AWindow::winProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
248249
return 0;
249250
}
250251

252+
case WM_SETTINGCHANGE: {
253+
if (wParam == 0 && lParam != 0 && wcscmp(reinterpret_cast<wchar_t*>(lParam), L"ImmersiveColorSet") == 0) {
254+
aui::UpdateDarkModeForHWND(hwnd);
255+
}
256+
return 0;
257+
}
258+
251259
case WM_GETMINMAXINFO: {
252260
MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(lParam);
253261

aui.views/src/AUI/Platform/win32/CommonRenderingContext.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
// Created by Alex2772 on 12/9/2021.
1414
//
1515

16-
#include <AUI/Platform/CommonRenderingContext.h>
1716
#include <AUI/Util/ARandom.h>
1817
#include <AUI/Logging/ALogger.h>
19-
#include "AUI/Platform/ARenderingContextOptions.h"
18+
#include <AUI/Platform/win32/Theme.h>
19+
#include <AUI/Platform/CommonRenderingContext.h>
20+
#include <AUI/Platform/ARenderingContextOptions.h>
2021

2122
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
2223
auto window = reinterpret_cast<AWindow*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
@@ -74,6 +75,8 @@ void CommonRenderingContext::init(const Init& init) {
7475
GetSystemMetrics(SM_CYSCREEN) / 2 - init.height / 2, init.width, init.height,
7576
init.parent != nullptr ? init.parent->mHandle : nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
7677

78+
aui::UpdateDarkModeForHWND(window.mHandle);
79+
7780
mWindowDC = GetDC(window.mHandle);
7881

7982
SetWindowLongPtr(window.mHandle, GWLP_USERDATA, reinterpret_cast<long long int>(&window));

aui.views/src/AUI/Platform/win32/OpenGLRenderingContextImpl.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,18 @@
1414
//
1515

1616
#include <AUI/GL/gl.h>
17+
#include <AUI/GL/GLDebug.h>
18+
#include <glad/glad_wgl.h>
1719
#include <AUI/Platform/OpenGLRenderingContext.h>
1820
#include <AUI/Util/ARandom.h>
1921
#include <AUI/Logging/ALogger.h>
2022
#include <AUI/Platform/AMessageBox.h>
21-
#include <AUI/GL/GLDebug.h>
22-
#include <glad/glad_wgl.h>
23-
2423
#include <AUI/GL/OpenGLRenderer.h>
2524
#include <AUI/GL/State.h>
26-
#include "AUI/Util/kAUI.h"
27-
25+
#include <AUI/Util/kAUI.h>
2826
#include <tuple>
2927
#include <string_view>
3028

31-
3229
HGLRC OpenGLRenderingContext::ourHrc = nullptr;
3330

3431
static constexpr auto LOG_TAG = "OpenGL";
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* AUI Framework - Declarative UI toolkit for modern C++20
3+
* Copyright (C) 2020-2025 Alex2772 and Contributors
4+
*
5+
* SPDX-License-Identifier: MPL-2.0
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
10+
*/
11+
12+
//
13+
// Created by Nelonn on 12/17/2025.
14+
//
15+
16+
// Credit: SDL3
17+
18+
#include "Theme.h"
19+
20+
#include <dwmapi.h>
21+
22+
typedef enum {
23+
UXTHEME_APPMODE_DEFAULT,
24+
UXTHEME_APPMODE_ALLOW_DARK,
25+
UXTHEME_APPMODE_FORCE_DARK,
26+
UXTHEME_APPMODE_FORCE_LIGHT,
27+
UXTHEME_APPMODE_MAX
28+
} UxthemePreferredAppMode;
29+
30+
typedef enum {
31+
WCA_UNDEFINED = 0,
32+
WCA_USEDARKMODECOLORS = 26,
33+
WCA_LAST = 27
34+
} WINDOWCOMPOSITIONATTRIB;
35+
36+
typedef struct {
37+
WINDOWCOMPOSITIONATTRIB Attrib;
38+
PVOID pvData;
39+
SIZE_T cbData;
40+
} WINDOWCOMPOSITIONATTRIBDATA;
41+
42+
typedef struct {
43+
ULONG dwOSVersionInfoSize;
44+
ULONG dwMajorVersion;
45+
ULONG dwMinorVersion;
46+
ULONG dwBuildNumber;
47+
ULONG dwPlatformId;
48+
WCHAR szCSDVersion[128];
49+
} NT_OSVERSIONINFOW;
50+
51+
typedef bool (WINAPI *ShouldAppsUseDarkMode_t)(void);
52+
typedef void (WINAPI *AllowDarkModeForWindow_t)(HWND, bool);
53+
typedef void (WINAPI *AllowDarkModeForApp_t)(bool);
54+
typedef void (WINAPI *RefreshImmersiveColorPolicyState_t)(void);
55+
typedef UxthemePreferredAppMode (WINAPI *SetPreferredAppMode_t)(UxthemePreferredAppMode);
56+
typedef BOOL (WINAPI *SetWindowCompositionAttribute_t)(HWND, const WINDOWCOMPOSITIONATTRIBDATA *);
57+
typedef void (NTAPI *RtlGetVersion_t)(NT_OSVERSIONINFOW *);
58+
59+
namespace aui {
60+
61+
bool IsWindowsBuildVersionAtLeast(DWORD dwBuildNumber) {
62+
static DWORD BuildNumber = 0;
63+
if (BuildNumber != 0) {
64+
return (BuildNumber >= dwBuildNumber);
65+
}
66+
67+
HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll"));
68+
if (!ntdll) {
69+
return false;
70+
}
71+
// There is no function to get Windows build number, so let's get it here via RtlGetVersion
72+
RtlGetVersion_t RtlGetVersionFunc = (RtlGetVersion_t)GetProcAddress(ntdll, "RtlGetVersion");
73+
NT_OSVERSIONINFOW os_info;
74+
os_info.dwOSVersionInfoSize = sizeof(NT_OSVERSIONINFOW);
75+
os_info.dwBuildNumber = 0;
76+
if (RtlGetVersionFunc) {
77+
RtlGetVersionFunc(&os_info);
78+
}
79+
FreeLibrary(ntdll);
80+
81+
BuildNumber = (os_info.dwBuildNumber & ~0xF0000000);
82+
return (BuildNumber >= dwBuildNumber);
83+
}
84+
85+
void UpdateDarkModeForHWND(HWND hwnd) {
86+
if (!IsWindowsBuildVersionAtLeast(17763)) return;
87+
88+
HMODULE uxtheme = LoadLibrary(TEXT("uxtheme.dll"));
89+
if (!uxtheme) return;
90+
91+
RefreshImmersiveColorPolicyState_t RefreshImmersiveColorPolicyStateFunc = (RefreshImmersiveColorPolicyState_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(104));
92+
ShouldAppsUseDarkMode_t ShouldAppsUseDarkModeFunc = (ShouldAppsUseDarkMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(132));
93+
AllowDarkModeForWindow_t AllowDarkModeForWindowFunc = (AllowDarkModeForWindow_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(133));
94+
if (!IsWindowsBuildVersionAtLeast(18362)) {
95+
AllowDarkModeForApp_t AllowDarkModeForAppFunc = (AllowDarkModeForApp_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135));
96+
if (AllowDarkModeForAppFunc) {
97+
AllowDarkModeForAppFunc(true);
98+
}
99+
} else {
100+
SetPreferredAppMode_t SetPreferredAppModeFunc = (SetPreferredAppMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135));
101+
if (SetPreferredAppModeFunc) {
102+
SetPreferredAppModeFunc(UXTHEME_APPMODE_ALLOW_DARK);
103+
}
104+
}
105+
if (RefreshImmersiveColorPolicyStateFunc) {
106+
RefreshImmersiveColorPolicyStateFunc();
107+
}
108+
if (AllowDarkModeForWindowFunc) {
109+
AllowDarkModeForWindowFunc(hwnd, true);
110+
}
111+
BOOL value;
112+
if (ShouldAppsUseDarkModeFunc) {
113+
value = ShouldAppsUseDarkModeFunc() ? TRUE : FALSE;
114+
} else {
115+
value = TRUE;
116+
}
117+
FreeLibrary(uxtheme);
118+
if (!IsWindowsBuildVersionAtLeast(18362)) {
119+
SetProp(hwnd, TEXT("UseImmersiveDarkModeColors"), reinterpret_cast<HANDLE>(static_cast<INT_PTR>(value)));
120+
} else {
121+
HMODULE user32 = GetModuleHandle(TEXT("user32.dll"));
122+
if (user32) {
123+
SetWindowCompositionAttribute_t SetWindowCompositionAttributeFunc = (SetWindowCompositionAttribute_t)GetProcAddress(user32, "SetWindowCompositionAttribute");
124+
if (SetWindowCompositionAttributeFunc) {
125+
WINDOWCOMPOSITIONATTRIBDATA data = { WCA_USEDARKMODECOLORS, &value, sizeof(value) };
126+
SetWindowCompositionAttributeFunc(hwnd, &data);
127+
}
128+
}
129+
}
130+
}
131+
132+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* AUI Framework - Declarative UI toolkit for modern C++20
3+
* Copyright (C) 2020-2025 Alex2772 and Contributors
4+
*
5+
* SPDX-License-Identifier: MPL-2.0
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
10+
*/
11+
12+
//
13+
// Created by Nelonn on 12/17/2025.
14+
//
15+
16+
#pragma once
17+
18+
#include <windows.h>
19+
20+
namespace aui {
21+
22+
void UpdateDarkModeForHWND(HWND hwnd);
23+
24+
}

0 commit comments

Comments
 (0)