From 2a4704e5b5dd5ba34abad51b9e2ab91cdc5a6438 Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Fri, 10 Apr 2026 20:40:35 +0800 Subject: [PATCH 01/13] feat: add Windows title bar theme support based on app theme --- lib/app_widget.dart | 9 ++++ lib/pages/settings/theme_settings_page.dart | 17 ++++++++ lib/utils/utils.dart | 22 ++++++++++ windows/runner/flutter_window.cpp | 36 ++++++++++++++++ windows/runner/flutter_window.h | 3 ++ windows/runner/win32_window.cpp | 46 +++++++++++++++------ windows/runner/win32_window.h | 13 ++++-- 7 files changed, 131 insertions(+), 15 deletions(-) diff --git a/lib/app_widget.dart b/lib/app_widget.dart index 78ad8aeca..97a88d61a 100644 --- a/lib/app_widget.dart +++ b/lib/app_widget.dart @@ -215,6 +215,15 @@ class _AppWidgetState extends State if (defaultThemeMode == 'system') { themeProvider.setThemeMode(ThemeMode.system, notify: false); } + + // Set Windows title bar theme based on app theme + if (Platform.isWindows) { + final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; + final isDark = themeProvider.themeMode == ThemeMode.dark || + (themeProvider.themeMode == ThemeMode.system && brightness == Brightness.dark); + Utils.setWindowTitleBarDarkMode(isDark); + } + themeProvider.setFontFamily(useSystemFont, notify: false); var defaultDarkTheme = ThemeData( useMaterial3: true, diff --git a/lib/pages/settings/theme_settings_page.dart b/lib/pages/settings/theme_settings_page.dart index 90d9dd0bc..c840adcc3 100644 --- a/lib/pages/settings/theme_settings_page.dart +++ b/lib/pages/settings/theme_settings_page.dart @@ -122,6 +122,13 @@ class _ThemeSettingsPageState extends State { setState(() { defaultThemeMode = theme; }); + + // Update Windows title bar theme + if (Utils.isDesktop() && Platform.isWindows) { + final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; + final isDark = theme == 'dark' || (theme == 'system' && brightness == Brightness.dark); + Utils.setWindowTitleBarDarkMode(isDark); + } } void updateOledEnhance() { @@ -382,6 +389,16 @@ class _ThemeSettingsPageState extends State { showWindowButton = value ?? !showWindowButton; await setting.put( SettingBoxKey.showWindowButton, showWindowButton); + // Reset title bar theme to follow system when hiding system title bar + if (!showWindowButton && Platform.isWindows) { + Utils.resetWindowTitleBarTheme(); + } else if (showWindowButton && Platform.isWindows) { + // Update title bar theme based on current app theme when showing system title bar + final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; + final isDark = defaultThemeMode == 'dark' || + (defaultThemeMode == 'system' && brightness == Brightness.dark); + Utils.setWindowTitleBarDarkMode(isDark); + } setState(() {}); }, title: Text('使用系统标题栏', diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 1fdd4773b..8c93cab76 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -700,4 +700,26 @@ class Utils { action?.call(); }); } + + /// 设置 Windows 标题栏深色模式 + static Future setWindowTitleBarDarkMode(bool isDark) async { + if (!Platform.isWindows) return; + const MethodChannel themeChannel = MethodChannel("com.predidit.kazumi/theme"); + try { + await themeChannel.invokeMethod("setTitleBarDarkMode", {"isDark": isDark}); + } on PlatformException catch (e) { + KazumiLogger().e("Failed to set title bar dark mode: '${e.message}'."); + } + } + + /// 重置 Windows 标题栏跟随系统主题 + static Future resetWindowTitleBarTheme() async { + if (!Platform.isWindows) return; + const MethodChannel themeChannel = MethodChannel("com.predidit.kazumi/theme"); + try { + await themeChannel.invokeMethod("resetTitleBarTheme"); + } on PlatformException catch (e) { + KazumiLogger().e("Failed to reset title bar theme: '${e.message}'."); + } + } } \ No newline at end of file diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index f16880f9a..3815ef065 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -54,6 +54,9 @@ bool FlutterWindow::OnCreate() { // Register Shortcut MethodChannel RegisterShortcutChannel(); + // Register Theme MethodChannel + RegisterThemeChannel(); + return true; } @@ -176,3 +179,36 @@ void FlutterWindow::RegisterShortcutChannel() { } }); } + +// Theme MethodChannel setup for immersive title bar +void FlutterWindow::RegisterThemeChannel() { + auto channel = std::make_unique>( + flutter_controller_->engine()->messenger(), "com.predidit.kazumi/theme", + &flutter::StandardMethodCodec::GetInstance()); + + channel->SetMethodCallHandler([this](const auto& call, auto result) { + if (call.method_name() == "setTitleBarDarkMode") { + const auto* arguments = std::get_if(call.arguments()); + if (arguments) { + auto is_dark_it = arguments->find(flutter::EncodableValue("isDark")); + if (is_dark_it != arguments->end()) { + bool is_dark = std::get(is_dark_it->second); + Win32Window::SetDarkMode(is_dark ? TRUE : FALSE); + Win32Window::UpdateTheme(GetHandle()); + result->Success(); + } else { + result->Error("InvalidArguments", "Missing 'isDark' argument"); + } + } else { + result->Error("InvalidArguments", "Arguments are not a map"); + } + } else if (call.method_name() == "resetTitleBarTheme") { + // Reset to follow system theme + Win32Window::SetDarkMode(-1); + Win32Window::UpdateTheme(GetHandle()); + result->Success(); + } else { + result->NotImplemented(); + } + }); +} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h index f523a885e..3cd548ced 100644 --- a/windows/runner/flutter_window.h +++ b/windows/runner/flutter_window.h @@ -37,6 +37,9 @@ class FlutterWindow : public Win32Window { // Register Shortcut MethodChannel void RegisterShortcutChannel(); + + // Register Theme MethodChannel for immersive title bar + void RegisterThemeChannel(); }; #endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 8e098faba..824058561 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -55,6 +55,9 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { } // namespace +// Static member definition - must be outside anonymous namespace +BOOL Win32Window::manual_dark_mode_ = -1; + // Manages the Win32Window's window class registration. class WindowClassRegistrar { public: @@ -280,17 +283,36 @@ void Win32Window::OnDestroy() { // No-op; provided for subclasses. } -void Win32Window::UpdateTheme(HWND const window) { - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - - if (result == ERROR_SUCCESS) { - BOOL enable_dark_mode = light_mode == 0; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); +void Win32Window::UpdateTheme(HWND const window, BOOL dark_mode) { + BOOL enable_dark_mode; + + // Use provided dark_mode if specified (not -1), otherwise follow system + if (dark_mode != -1) { + enable_dark_mode = dark_mode; + } else { + // Check manual preference first + if (manual_dark_mode_ != -1) { + enable_dark_mode = manual_dark_mode_; + } else { + // Fall back to system theme + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + if (result == ERROR_SUCCESS) { + enable_dark_mode = light_mode == 0; + } else { + enable_dark_mode = FALSE; + } + } } + + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); +} + +void Win32Window::SetDarkMode(BOOL dark_mode) { + manual_dark_mode_ = dark_mode; } diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h index e901dde68..e956a5c67 100644 --- a/windows/runner/win32_window.h +++ b/windows/runner/win32_window.h @@ -55,6 +55,13 @@ class Win32Window { // Return a RECT representing the bounds of the current client area. RECT GetClientArea(); + // Update the window frame's theme. + // If dark_mode is specified, use that value; otherwise follow system theme. + static void UpdateTheme(HWND const window, BOOL dark_mode = -1); + + // Set manual dark mode preference and update all windows + static void SetDarkMode(BOOL dark_mode); + protected: // Processes and route salient window messages for mouse handling, // size change and DPI. Delegates handling of these to member overloads that @@ -87,11 +94,11 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; - // Update the window frame's theme to match the system theme. - static void UpdateTheme(HWND const window); - bool quit_on_close_ = false; + // Manually specified dark mode preference (-1 = follow system, 0 = light, 1 = dark) + static BOOL manual_dark_mode_; + // window handle for top level window. HWND window_handle_ = nullptr; From 983d4dd24772d5fd1c0dc85ef6e6e4f9e0c2f078 Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Fri, 10 Apr 2026 20:54:30 +0800 Subject: [PATCH 02/13] feat: refine Windows title bar theme handling based on system settings --- lib/app_widget.dart | 13 ++++--- lib/pages/settings/theme_settings_page.dart | 14 +------ lib/utils/utils.dart | 11 ------ windows/runner/flutter_window.cpp | 8 +--- windows/runner/win32_window.cpp | 41 ++++++--------------- windows/runner/win32_window.h | 11 ++---- 6 files changed, 25 insertions(+), 73 deletions(-) diff --git a/lib/app_widget.dart b/lib/app_widget.dart index 97a88d61a..27aa6d9f8 100644 --- a/lib/app_widget.dart +++ b/lib/app_widget.dart @@ -216,12 +216,15 @@ class _AppWidgetState extends State themeProvider.setThemeMode(ThemeMode.system, notify: false); } - // Set Windows title bar theme based on app theme + // Set Windows title bar theme based on app theme (only when using system title bar) if (Platform.isWindows) { - final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; - final isDark = themeProvider.themeMode == ThemeMode.dark || - (themeProvider.themeMode == ThemeMode.system && brightness == Brightness.dark); - Utils.setWindowTitleBarDarkMode(isDark); + bool showWindowButton = setting.get(SettingBoxKey.showWindowButton, defaultValue: false); + if (showWindowButton) { + final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; + final isDark = themeProvider.themeMode == ThemeMode.dark || + (themeProvider.themeMode == ThemeMode.system && brightness == Brightness.dark); + Utils.setWindowTitleBarDarkMode(isDark); + } } themeProvider.setFontFamily(useSystemFont, notify: false); diff --git a/lib/pages/settings/theme_settings_page.dart b/lib/pages/settings/theme_settings_page.dart index c840adcc3..ab278cd5f 100644 --- a/lib/pages/settings/theme_settings_page.dart +++ b/lib/pages/settings/theme_settings_page.dart @@ -123,8 +123,8 @@ class _ThemeSettingsPageState extends State { defaultThemeMode = theme; }); - // Update Windows title bar theme - if (Utils.isDesktop() && Platform.isWindows) { + // Update Windows title bar theme (only when using system title bar) + if (Platform.isWindows && showWindowButton) { final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; final isDark = theme == 'dark' || (theme == 'system' && brightness == Brightness.dark); Utils.setWindowTitleBarDarkMode(isDark); @@ -389,16 +389,6 @@ class _ThemeSettingsPageState extends State { showWindowButton = value ?? !showWindowButton; await setting.put( SettingBoxKey.showWindowButton, showWindowButton); - // Reset title bar theme to follow system when hiding system title bar - if (!showWindowButton && Platform.isWindows) { - Utils.resetWindowTitleBarTheme(); - } else if (showWindowButton && Platform.isWindows) { - // Update title bar theme based on current app theme when showing system title bar - final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; - final isDark = defaultThemeMode == 'dark' || - (defaultThemeMode == 'system' && brightness == Brightness.dark); - Utils.setWindowTitleBarDarkMode(isDark); - } setState(() {}); }, title: Text('使用系统标题栏', diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 8c93cab76..5a7920c4b 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -711,15 +711,4 @@ class Utils { KazumiLogger().e("Failed to set title bar dark mode: '${e.message}'."); } } - - /// 重置 Windows 标题栏跟随系统主题 - static Future resetWindowTitleBarTheme() async { - if (!Platform.isWindows) return; - const MethodChannel themeChannel = MethodChannel("com.predidit.kazumi/theme"); - try { - await themeChannel.invokeMethod("resetTitleBarTheme"); - } on PlatformException catch (e) { - KazumiLogger().e("Failed to reset title bar theme: '${e.message}'."); - } - } } \ No newline at end of file diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index 3815ef065..14fb49f31 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -193,8 +193,7 @@ void FlutterWindow::RegisterThemeChannel() { auto is_dark_it = arguments->find(flutter::EncodableValue("isDark")); if (is_dark_it != arguments->end()) { bool is_dark = std::get(is_dark_it->second); - Win32Window::SetDarkMode(is_dark ? TRUE : FALSE); - Win32Window::UpdateTheme(GetHandle()); + Win32Window::UpdateTheme(GetHandle(), is_dark); result->Success(); } else { result->Error("InvalidArguments", "Missing 'isDark' argument"); @@ -202,11 +201,6 @@ void FlutterWindow::RegisterThemeChannel() { } else { result->Error("InvalidArguments", "Arguments are not a map"); } - } else if (call.method_name() == "resetTitleBarTheme") { - // Reset to follow system theme - Win32Window::SetDarkMode(-1); - Win32Window::UpdateTheme(GetHandle()); - result->Success(); } else { result->NotImplemented(); } diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 824058561..7cd6395f1 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -55,9 +55,6 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { } // namespace -// Static member definition - must be outside anonymous namespace -BOOL Win32Window::manual_dark_mode_ = -1; - // Manages the Win32Window's window class registration. class WindowClassRegistrar { public: @@ -283,36 +280,20 @@ void Win32Window::OnDestroy() { // No-op; provided for subclasses. } -void Win32Window::UpdateTheme(HWND const window, BOOL dark_mode) { +void Win32Window::UpdateTheme(HWND const window, std::optional dark_mode) { BOOL enable_dark_mode; - - // Use provided dark_mode if specified (not -1), otherwise follow system - if (dark_mode != -1) { - enable_dark_mode = dark_mode; + if (dark_mode.has_value()) { + enable_dark_mode = dark_mode.value() ? TRUE : FALSE; } else { - // Check manual preference first - if (manual_dark_mode_ != -1) { - enable_dark_mode = manual_dark_mode_; - } else { - // Fall back to system theme - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - if (result == ERROR_SUCCESS) { - enable_dark_mode = light_mode == 0; - } else { - enable_dark_mode = FALSE; - } - } + // Follow system theme + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + enable_dark_mode = (result == ERROR_SUCCESS && light_mode == 0) ? TRUE : FALSE; } - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, &enable_dark_mode, sizeof(enable_dark_mode)); } - -void Win32Window::SetDarkMode(BOOL dark_mode) { - manual_dark_mode_ = dark_mode; -} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h index e956a5c67..42c181681 100644 --- a/windows/runner/win32_window.h +++ b/windows/runner/win32_window.h @@ -5,6 +5,7 @@ #include #include +#include #include // A class abstraction for a high DPI-aware Win32 Window. Intended to be @@ -56,11 +57,8 @@ class Win32Window { RECT GetClientArea(); // Update the window frame's theme. - // If dark_mode is specified, use that value; otherwise follow system theme. - static void UpdateTheme(HWND const window, BOOL dark_mode = -1); - - // Set manual dark mode preference and update all windows - static void SetDarkMode(BOOL dark_mode); + // If dark_mode is specified, use that; otherwise follow system theme. + static void UpdateTheme(HWND const window, std::optional dark_mode = std::nullopt); protected: // Processes and route salient window messages for mouse handling, @@ -96,9 +94,6 @@ class Win32Window { bool quit_on_close_ = false; - // Manually specified dark mode preference (-1 = follow system, 0 = light, 1 = dark) - static BOOL manual_dark_mode_; - // window handle for top level window. HWND window_handle_ = nullptr; From a51bce95435e27c486604c70e0dc4dd37e4c314b Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Fri, 10 Apr 2026 21:46:56 +0800 Subject: [PATCH 03/13] feat: update Windows title bar theme handling and method channel setup --- lib/app_widget.dart | 2 +- lib/pages/settings/theme_settings_page.dart | 2 +- windows/runner/flutter_window.cpp | 38 +++++++++++---------- windows/runner/flutter_window.h | 2 +- windows/runner/win32_window.cpp | 35 +++++++++++-------- windows/runner/win32_window.h | 9 ++--- 6 files changed, 49 insertions(+), 39 deletions(-) diff --git a/lib/app_widget.dart b/lib/app_widget.dart index 27aa6d9f8..b968e226a 100644 --- a/lib/app_widget.dart +++ b/lib/app_widget.dart @@ -216,7 +216,7 @@ class _AppWidgetState extends State themeProvider.setThemeMode(ThemeMode.system, notify: false); } - // Set Windows title bar theme based on app theme (only when using system title bar) + // Set Windows title bar theme based on app theme if (Platform.isWindows) { bool showWindowButton = setting.get(SettingBoxKey.showWindowButton, defaultValue: false); if (showWindowButton) { diff --git a/lib/pages/settings/theme_settings_page.dart b/lib/pages/settings/theme_settings_page.dart index ab278cd5f..e4beeea59 100644 --- a/lib/pages/settings/theme_settings_page.dart +++ b/lib/pages/settings/theme_settings_page.dart @@ -123,7 +123,7 @@ class _ThemeSettingsPageState extends State { defaultThemeMode = theme; }); - // Update Windows title bar theme (only when using system title bar) + // Update Windows title bar theme if (Platform.isWindows && showWindowButton) { final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; final isDark = theme == 'dark' || (theme == 'system' && brightness == Brightness.dark); diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index 14fb49f31..199313332 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -180,29 +180,31 @@ void FlutterWindow::RegisterShortcutChannel() { }); } -// Theme MethodChannel setup for immersive title bar +// Theme MethodChannel setup void FlutterWindow::RegisterThemeChannel() { auto channel = std::make_unique>( flutter_controller_->engine()->messenger(), "com.predidit.kazumi/theme", &flutter::StandardMethodCodec::GetInstance()); - channel->SetMethodCallHandler([this](const auto& call, auto result) { - if (call.method_name() == "setTitleBarDarkMode") { - const auto* arguments = std::get_if(call.arguments()); - if (arguments) { - auto is_dark_it = arguments->find(flutter::EncodableValue("isDark")); - if (is_dark_it != arguments->end()) { - bool is_dark = std::get(is_dark_it->second); - Win32Window::UpdateTheme(GetHandle(), is_dark); - result->Success(); + channel->SetMethodCallHandler( + [this](const flutter::MethodCall& call, + std::unique_ptr> result) { + if (call.method_name() == "setTitleBarDarkMode") { + const auto* arguments = std::get_if(call.arguments()); + if (arguments) { + auto is_dark_it = arguments->find(flutter::EncodableValue("isDark")); + if (is_dark_it != arguments->end()) { + bool is_dark = std::get(is_dark_it->second); + Win32Window::SetTitleBarDarkMode(GetHandle(), is_dark); + result->Success(); + } else { + result->Error("InvalidArguments", "Missing 'isDark' argument"); + } + } else { + result->Error("InvalidArguments", "Arguments are not a map"); + } } else { - result->Error("InvalidArguments", "Missing 'isDark' argument"); + result->NotImplemented(); } - } else { - result->Error("InvalidArguments", "Arguments are not a map"); - } - } else { - result->NotImplemented(); - } - }); + }); } diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h index 3cd548ced..87fc3b076 100644 --- a/windows/runner/flutter_window.h +++ b/windows/runner/flutter_window.h @@ -38,7 +38,7 @@ class FlutterWindow : public Win32Window { // Register Shortcut MethodChannel void RegisterShortcutChannel(); - // Register Theme MethodChannel for immersive title bar + // Register Theme MethodChannel void RegisterThemeChannel(); }; diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 7cd6395f1..304e0acef 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -221,6 +221,10 @@ Win32Window::MessageHandler(HWND hwnd, } return 0; + case WM_SETTINGCHANGE: + UpdateTheme(hwnd); + return 0; + case WM_DWMCOLORIZATIONCOLORCHANGED: UpdateTheme(hwnd); return 0; @@ -280,20 +284,23 @@ void Win32Window::OnDestroy() { // No-op; provided for subclasses. } -void Win32Window::UpdateTheme(HWND const window, std::optional dark_mode) { - BOOL enable_dark_mode; - if (dark_mode.has_value()) { - enable_dark_mode = dark_mode.value() ? TRUE : FALSE; - } else { - // Follow system theme - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - enable_dark_mode = (result == ERROR_SUCCESS && light_mode == 0) ? TRUE : FALSE; +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); } +} + +void Win32Window::SetTitleBarDarkMode(HWND const window, bool dark_mode) { + BOOL enable = dark_mode ? TRUE : FALSE; DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); + &enable, sizeof(enable)); } diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h index 42c181681..64d7d1770 100644 --- a/windows/runner/win32_window.h +++ b/windows/runner/win32_window.h @@ -5,7 +5,6 @@ #include #include -#include #include // A class abstraction for a high DPI-aware Win32 Window. Intended to be @@ -56,9 +55,8 @@ class Win32Window { // Return a RECT representing the bounds of the current client area. RECT GetClientArea(); - // Update the window frame's theme. - // If dark_mode is specified, use that; otherwise follow system theme. - static void UpdateTheme(HWND const window, std::optional dark_mode = std::nullopt); + // Set title bar dark mode directly (for app theme sync) + static void SetTitleBarDarkMode(HWND const window, bool dark_mode); protected: // Processes and route salient window messages for mouse handling, @@ -92,6 +90,9 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + bool quit_on_close_ = false; // window handle for top level window. From f3b7b3a0de7ad387e0c8faa03b3c4f2377aebd5a Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Fri, 10 Apr 2026 21:51:32 +0800 Subject: [PATCH 04/13] feat: simplify theme update handling by removing redundant message case and using SetTitleBarDarkMode --- windows/runner/win32_window.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 304e0acef..cac03feb5 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -224,10 +224,6 @@ Win32Window::MessageHandler(HWND hwnd, case WM_SETTINGCHANGE: UpdateTheme(hwnd); return 0; - - case WM_DWMCOLORIZATIONCOLORCHANGED: - UpdateTheme(hwnd); - return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -293,9 +289,7 @@ void Win32Window::UpdateTheme(HWND const window) { &light_mode_size); if (result == ERROR_SUCCESS) { - BOOL enable_dark_mode = light_mode == 0; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); + SetTitleBarDarkMode(window, light_mode == 0); } } From effaed3f25882109b34f09637a492bc06b19533a Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Fri, 10 Apr 2026 22:00:17 +0800 Subject: [PATCH 05/13] feat: enhance Windows title bar theme handling by simplifying logic and adding isEffectiveDark method --- lib/app_widget.dart | 9 ++------- lib/bean/settings/theme_provider.dart | 8 ++++++++ lib/pages/settings/theme_settings_page.dart | 5 ++--- windows/runner/win32_window.cpp | 3 ++- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/app_widget.dart b/lib/app_widget.dart index b968e226a..9cab4699a 100644 --- a/lib/app_widget.dart +++ b/lib/app_widget.dart @@ -218,13 +218,8 @@ class _AppWidgetState extends State // Set Windows title bar theme based on app theme if (Platform.isWindows) { - bool showWindowButton = setting.get(SettingBoxKey.showWindowButton, defaultValue: false); - if (showWindowButton) { - final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; - final isDark = themeProvider.themeMode == ThemeMode.dark || - (themeProvider.themeMode == ThemeMode.system && brightness == Brightness.dark); - Utils.setWindowTitleBarDarkMode(isDark); - } + final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; + Utils.setWindowTitleBarDarkMode(themeProvider.isEffectiveDark(brightness)); } themeProvider.setFontFamily(useSystemFont, notify: false); diff --git a/lib/bean/settings/theme_provider.dart b/lib/bean/settings/theme_provider.dart index 70fb8cbc9..0e3eabc8d 100644 --- a/lib/bean/settings/theme_provider.dart +++ b/lib/bean/settings/theme_provider.dart @@ -8,6 +8,14 @@ class ThemeProvider extends ChangeNotifier { late ThemeData dark; String? currentFontFamily = customAppFontFamily; + /// Returns true if the effective theme is dark mode. + /// When themeMode is ThemeMode.system, uses the provided platform brightness. + bool isEffectiveDark(Brightness platformBrightness) { + if (themeMode == ThemeMode.dark) return true; + if (themeMode == ThemeMode.light) return false; + return platformBrightness == Brightness.dark; + } + void setTheme(ThemeData light, ThemeData dark, {bool notify = true}) { this.light = light; this.dark = dark; diff --git a/lib/pages/settings/theme_settings_page.dart b/lib/pages/settings/theme_settings_page.dart index e4beeea59..00294b45e 100644 --- a/lib/pages/settings/theme_settings_page.dart +++ b/lib/pages/settings/theme_settings_page.dart @@ -124,10 +124,9 @@ class _ThemeSettingsPageState extends State { }); // Update Windows title bar theme - if (Platform.isWindows && showWindowButton) { + if (Platform.isWindows) { final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; - final isDark = theme == 'dark' || (theme == 'system' && brightness == Brightness.dark); - Utils.setWindowTitleBarDarkMode(isDark); + Utils.setWindowTitleBarDarkMode(themeProvider.isEffectiveDark(brightness)); } } diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index cac03feb5..7d70097d0 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -222,7 +222,8 @@ Win32Window::MessageHandler(HWND hwnd, return 0; case WM_SETTINGCHANGE: - UpdateTheme(hwnd); + // WM_SETTINGCHANGE is handled by Flutter layer rebuild, + // no need to update title bar theme here. return 0; } From b04b611319639e9c77b32285227707b45fd20e05 Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Fri, 10 Apr 2026 22:15:49 +0800 Subject: [PATCH 06/13] ref: use windowManager.setBrightness method --- lib/app_widget.dart | 2 +- lib/pages/settings/theme_settings_page.dart | 3 +- lib/utils/utils.dart | 12 +------- windows/runner/flutter_window.cpp | 31 --------------------- windows/runner/flutter_window.h | 3 -- windows/runner/win32_window.cpp | 13 +++------ windows/runner/win32_window.h | 3 -- 7 files changed, 8 insertions(+), 59 deletions(-) diff --git a/lib/app_widget.dart b/lib/app_widget.dart index 9cab4699a..cec6738c8 100644 --- a/lib/app_widget.dart +++ b/lib/app_widget.dart @@ -219,7 +219,7 @@ class _AppWidgetState extends State // Set Windows title bar theme based on app theme if (Platform.isWindows) { final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; - Utils.setWindowTitleBarDarkMode(themeProvider.isEffectiveDark(brightness)); + windowManager.setBrightness(themeProvider.isEffectiveDark(brightness) ? Brightness.dark : Brightness.light); } themeProvider.setFontFamily(useSystemFont, notify: false); diff --git a/lib/pages/settings/theme_settings_page.dart b/lib/pages/settings/theme_settings_page.dart index 00294b45e..ea46b65d2 100644 --- a/lib/pages/settings/theme_settings_page.dart +++ b/lib/pages/settings/theme_settings_page.dart @@ -13,6 +13,7 @@ import 'package:kazumi/bean/settings/color_type.dart'; import 'package:kazumi/utils/utils.dart'; import 'package:card_settings_ui/card_settings_ui.dart'; import 'package:provider/provider.dart'; +import 'package:window_manager/window_manager.dart'; class ThemeSettingsPage extends StatefulWidget { const ThemeSettingsPage({super.key}); @@ -126,7 +127,7 @@ class _ThemeSettingsPageState extends State { // Update Windows title bar theme if (Platform.isWindows) { final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; - Utils.setWindowTitleBarDarkMode(themeProvider.isEffectiveDark(brightness)); + await windowManager.setBrightness(themeProvider.isEffectiveDark(brightness) ? Brightness.dark : Brightness.light); } } diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 5a7920c4b..2e809f5d4 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -701,14 +701,4 @@ class Utils { }); } - /// 设置 Windows 标题栏深色模式 - static Future setWindowTitleBarDarkMode(bool isDark) async { - if (!Platform.isWindows) return; - const MethodChannel themeChannel = MethodChannel("com.predidit.kazumi/theme"); - try { - await themeChannel.invokeMethod("setTitleBarDarkMode", {"isDark": isDark}); - } on PlatformException catch (e) { - KazumiLogger().e("Failed to set title bar dark mode: '${e.message}'."); - } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index 199313332..a61f019b1 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -54,9 +54,6 @@ bool FlutterWindow::OnCreate() { // Register Shortcut MethodChannel RegisterShortcutChannel(); - // Register Theme MethodChannel - RegisterThemeChannel(); - return true; } @@ -180,31 +177,3 @@ void FlutterWindow::RegisterShortcutChannel() { }); } -// Theme MethodChannel setup -void FlutterWindow::RegisterThemeChannel() { - auto channel = std::make_unique>( - flutter_controller_->engine()->messenger(), "com.predidit.kazumi/theme", - &flutter::StandardMethodCodec::GetInstance()); - - channel->SetMethodCallHandler( - [this](const flutter::MethodCall& call, - std::unique_ptr> result) { - if (call.method_name() == "setTitleBarDarkMode") { - const auto* arguments = std::get_if(call.arguments()); - if (arguments) { - auto is_dark_it = arguments->find(flutter::EncodableValue("isDark")); - if (is_dark_it != arguments->end()) { - bool is_dark = std::get(is_dark_it->second); - Win32Window::SetTitleBarDarkMode(GetHandle(), is_dark); - result->Success(); - } else { - result->Error("InvalidArguments", "Missing 'isDark' argument"); - } - } else { - result->Error("InvalidArguments", "Arguments are not a map"); - } - } else { - result->NotImplemented(); - } - }); -} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h index 87fc3b076..f523a885e 100644 --- a/windows/runner/flutter_window.h +++ b/windows/runner/flutter_window.h @@ -37,9 +37,6 @@ class FlutterWindow : public Win32Window { // Register Shortcut MethodChannel void RegisterShortcutChannel(); - - // Register Theme MethodChannel - void RegisterThemeChannel(); }; #endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 7d70097d0..d3e34a46b 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -222,8 +222,7 @@ Win32Window::MessageHandler(HWND hwnd, return 0; case WM_SETTINGCHANGE: - // WM_SETTINGCHANGE is handled by Flutter layer rebuild, - // no need to update title bar theme here. + UpdateTheme(window_handle_); return 0; } @@ -290,12 +289,8 @@ void Win32Window::UpdateTheme(HWND const window) { &light_mode_size); if (result == ERROR_SUCCESS) { - SetTitleBarDarkMode(window, light_mode == 0); + BOOL enable = light_mode == 0 ? TRUE : FALSE; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable, sizeof(enable)); } } - -void Win32Window::SetTitleBarDarkMode(HWND const window, bool dark_mode) { - BOOL enable = dark_mode ? TRUE : FALSE; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable, sizeof(enable)); -} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h index 64d7d1770..e901dde68 100644 --- a/windows/runner/win32_window.h +++ b/windows/runner/win32_window.h @@ -55,9 +55,6 @@ class Win32Window { // Return a RECT representing the bounds of the current client area. RECT GetClientArea(); - // Set title bar dark mode directly (for app theme sync) - static void SetTitleBarDarkMode(HWND const window, bool dark_mode); - protected: // Processes and route salient window messages for mouse handling, // size change and DPI. Delegates handling of these to member overloads that From f8f2e4d7e56297cf6a8de3ee546bb0a777852523 Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Fri, 10 Apr 2026 22:20:22 +0800 Subject: [PATCH 07/13] fix: remove unnecessary newline --- lib/utils/utils.dart | 3 +-- windows/runner/flutter_window.cpp | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 2e809f5d4..1fdd4773b 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -700,5 +700,4 @@ class Utils { action?.call(); }); } - - } \ No newline at end of file +} \ No newline at end of file diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index a61f019b1..f16880f9a 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -176,4 +176,3 @@ void FlutterWindow::RegisterShortcutChannel() { } }); } - From 962f1e93f12d5d74ca712b9d931b883c1a2bb6c1 Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Fri, 10 Apr 2026 22:45:19 +0800 Subject: [PATCH 08/13] imp by review --- lib/app_widget.dart | 3 +-- lib/bean/settings/theme_provider.dart | 6 ++++-- lib/pages/settings/theme_settings_page.dart | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/app_widget.dart b/lib/app_widget.dart index cec6738c8..da8262e1f 100644 --- a/lib/app_widget.dart +++ b/lib/app_widget.dart @@ -218,8 +218,7 @@ class _AppWidgetState extends State // Set Windows title bar theme based on app theme if (Platform.isWindows) { - final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; - windowManager.setBrightness(themeProvider.isEffectiveDark(brightness) ? Brightness.dark : Brightness.light); + windowManager.setBrightness(themeProvider.isEffectiveDark() ? Brightness.dark : Brightness.light); } themeProvider.setFontFamily(useSystemFont, notify: false); diff --git a/lib/bean/settings/theme_provider.dart b/lib/bean/settings/theme_provider.dart index 0e3eabc8d..797739475 100644 --- a/lib/bean/settings/theme_provider.dart +++ b/lib/bean/settings/theme_provider.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; import 'package:kazumi/utils/constants.dart'; class ThemeProvider extends ChangeNotifier { @@ -9,10 +10,11 @@ class ThemeProvider extends ChangeNotifier { String? currentFontFamily = customAppFontFamily; /// Returns true if the effective theme is dark mode. - /// When themeMode is ThemeMode.system, uses the provided platform brightness. - bool isEffectiveDark(Brightness platformBrightness) { + /// Automatically gets platform brightness when themeMode is ThemeMode.system. + bool isEffectiveDark() { if (themeMode == ThemeMode.dark) return true; if (themeMode == ThemeMode.light) return false; + final platformBrightness = SchedulerBinding.instance.platformDispatcher.platformBrightness; return platformBrightness == Brightness.dark; } diff --git a/lib/pages/settings/theme_settings_page.dart b/lib/pages/settings/theme_settings_page.dart index ea46b65d2..35795c899 100644 --- a/lib/pages/settings/theme_settings_page.dart +++ b/lib/pages/settings/theme_settings_page.dart @@ -126,8 +126,7 @@ class _ThemeSettingsPageState extends State { // Update Windows title bar theme if (Platform.isWindows) { - final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; - await windowManager.setBrightness(themeProvider.isEffectiveDark(brightness) ? Brightness.dark : Brightness.light); + await windowManager.setBrightness(themeProvider.isEffectiveDark() ? Brightness.dark : Brightness.light); } } From fb481b6a88c38c4ae24777266ceaf1a21d75f75b Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Fri, 10 Apr 2026 22:48:22 +0800 Subject: [PATCH 09/13] revert --- windows/runner/win32_window.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index d3e34a46b..2c096a21a 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -289,8 +289,8 @@ void Win32Window::UpdateTheme(HWND const window) { &light_mode_size); if (result == ERROR_SUCCESS) { - BOOL enable = light_mode == 0 ? TRUE : FALSE; + BOOL enable_dark_mode = light_mode == 0; DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable, sizeof(enable)); + &enable_dark_mode, sizeof(enable_dark_mode)); } } From 4a27ec1a527f5ad2d5c3ca877d23b4d4c0106c43 Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Sat, 11 Apr 2026 16:46:14 +0800 Subject: [PATCH 10/13] fix: update theme handling in MessageHandler to use correct window handle --- windows/runner/win32_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 2c096a21a..39b0a4836 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -222,7 +222,7 @@ Win32Window::MessageHandler(HWND hwnd, return 0; case WM_SETTINGCHANGE: - UpdateTheme(window_handle_); + UpdateTheme(hwnd); return 0; } From 8e87e3e34a4d90d3c853176898709f8c0f8f61d6 Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Sat, 11 Apr 2026 18:36:41 +0800 Subject: [PATCH 11/13] feat: update title bar theme handling based on platform brightness changes --- lib/app_widget.dart | 15 +++++++++++++++ windows/runner/win32_window.cpp | 1 - 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/app_widget.dart b/lib/app_widget.dart index da8262e1f..b4afcb06c 100644 --- a/lib/app_widget.dart +++ b/lib/app_widget.dart @@ -164,6 +164,21 @@ class _AppWidgetState extends State } } + @override + void didChangePlatformBrightness() async { + super.didChangePlatformBrightness(); + final ThemeProvider themeProvider = Provider.of(context, listen: false); + KazumiLogger().i("Platform brightness changed, themeMode: ${themeProvider.themeMode}"); + + // Only update title bar theme when following system + // If user has forced a specific theme, keep title bar consistent with app content + if (themeProvider.themeMode == ThemeMode.system && Platform.isWindows) { + final brightness = WidgetsBinding.instance.platformDispatcher.platformBrightness; + KazumiLogger().i("Updating title bar brightness: $brightness"); + await windowManager.setBrightness(brightness); + } + } + Future _handleTray() async { if (Platform.isWindows) { await trayManager.setIcon('assets/images/logo/logo_lanczos.ico'); diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 39b0a4836..6b8f38a36 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -222,7 +222,6 @@ Win32Window::MessageHandler(HWND hwnd, return 0; case WM_SETTINGCHANGE: - UpdateTheme(hwnd); return 0; } From 791485b8845e79770e02839b9bbb0901284d9316 Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Sat, 11 Apr 2026 22:23:16 +0800 Subject: [PATCH 12/13] imp by review --- lib/app_widget.dart | 2 +- windows/runner/win32_window.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/app_widget.dart b/lib/app_widget.dart index b4afcb06c..f202e83aa 100644 --- a/lib/app_widget.dart +++ b/lib/app_widget.dart @@ -165,7 +165,7 @@ class _AppWidgetState extends State } @override - void didChangePlatformBrightness() async { + Future didChangePlatformBrightness() async { super.didChangePlatformBrightness(); final ThemeProvider themeProvider = Provider.of(context, listen: false); KazumiLogger().i("Platform brightness changed, themeMode: ${themeProvider.themeMode}"); diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 6b8f38a36..33c13cfaa 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -221,8 +221,13 @@ Win32Window::MessageHandler(HWND hwnd, } return 0; - case WM_SETTINGCHANGE: - return 0; + // Theme state is now maintained by Flutter side (app_widget.dart). + // WM_DWMCOLORIZATIONCOLORCHANGED is no longer needed because: + // - Title bar theme is controlled via windowManager.setBrightness() from Flutter + // - didChangePlatformBrightness() handles system theme changes with themeMode awareness + // case WM_DWMCOLORIZATIONCOLORCHANGED: + // UpdateTheme(hwnd); + // return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); From 11a7402033af63937b92c93da4c4186fbd708eff Mon Sep 17 00:00:00 2001 From: WingChunWong Date: Sat, 11 Apr 2026 22:25:02 +0800 Subject: [PATCH 13/13] remove llm slop --- windows/runner/win32_window.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 33c13cfaa..1217c619d 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -222,9 +222,6 @@ Win32Window::MessageHandler(HWND hwnd, return 0; // Theme state is now maintained by Flutter side (app_widget.dart). - // WM_DWMCOLORIZATIONCOLORCHANGED is no longer needed because: - // - Title bar theme is controlled via windowManager.setBrightness() from Flutter - // - didChangePlatformBrightness() handles system theme changes with themeMode awareness // case WM_DWMCOLORIZATIONCOLORCHANGED: // UpdateTheme(hwnd); // return 0;