diff --git a/README.md b/README.md index d265750..c81574e 100644 --- a/README.md +++ b/README.md @@ -136,12 +136,14 @@ extern "system" { /* ... */ } - `AppsUseLightTheme` - 控制应用主题 - `SystemUsesLightTheme` - 控制系统主题 -然后发送系统广播消息通知主题变更: -- `WM_SETTINGCHANGE` -- `WM_THEMECHANGED` (注:目前在代码中已临时注释) -- `WM_SYSCOLORCHANGE` (注:目前在代码中已临时注释) - -**说明**:目前实测发现 `WM_THEMECHANGED` 与 `WM_SYSCOLORCHANGE` 的广播在本工具场景下非必须。为了便于排查并避免潜在副作用,这两处广播已在 standard 与 mini 两处分别临时注释(保留为注释以便将来恢复)。`WM_SETTINGCHANGE` 广播仍保留,用于通知主题字符串变化。若需要恢复,请在对应文件中移除注释(变更提交:暂时注释 WM_THEMECHANGED 与 WM_SYSCOLORCHANGE 广播,PR 已合并)。 +修改注册表后,广播以下消息通知所有应用主题变更: +- `WM_SETTINGCHANGE`(lParam 为字符串 `"ImmersiveColorSet"`) +- `WM_THEMECHANGED` +- `WM_SYSCOLORCHANGE` + +**说明**:`"ImmersiveColorSet"` 是 `WM_SETTINGCHANGE` 的 **lParam 通知标识字符串**(类似 `"Environment"` 表示环境变量变更),与注册表路径无关,`Personalize` 键下**默认不存在**同名注册表值。 +该字符串是 Windows 系统本身在切换主题时广播的标准通知,WinUI 3 应用(如 Windows 11 任务管理器)通过监听此 `WM_SETTINGCHANGE` 消息来感知主题变化,并结合读取 `AppsUseLightTheme`/`SystemUsesLightTheme` 注册表值来确定新主题。 +技术出处:[microsoft/terminal `WindowEmperor.cpp`](https://github.com/microsoft/terminal/blob/c334f91f80dfe4c882e60be466622a7a51ca5bb9/src/cascadia/WindowsTerminal/WindowEmperor.cpp#L1008)、[AutoDarkMode `DwmRefreshHandler.cs`](https://github.com/AutoDarkMode/Windows-Auto-Night-Mode/blob/59e24dc2fe65f220e112f862fd6efc6d02740555/AutoDarkModeSvc/Handlers/DwmRefreshHandler.cs)。 ## 系统要求 diff --git a/mini/src/main.rs b/mini/src/main.rs index b993083..9d74025 100644 --- a/mini/src/main.rs +++ b/mini/src/main.rs @@ -160,26 +160,24 @@ pub extern "system" fn mainCRTStartup() -> ! { 200, ptr::null_mut(), ); - - // 目前实测发现 WM_THEMECHANGED 和 WM_SYSCOLORCHANGE 的广播非必须,暂时注释掉(调试用) - // winapi::SendMessageTimeoutW( - // winapi::HWND_BROADCAST, - // winapi::WM_THEMECHANGED, - // 0, - // 0, - // winapi::SMTO_ABORTIFHUNG, - // 200, - // ptr::null_mut(), - // ); - // winapi::SendMessageTimeoutW( - // winapi::HWND_BROADCAST, - // winapi::WM_SYSCOLORCHANGE, - // 0, - // 0, - // winapi::SMTO_ABORTIFHUNG, - // 200, - // ptr::null_mut(), - // ); + winapi::SendMessageTimeoutW( + winapi::HWND_BROADCAST, + winapi::WM_THEMECHANGED, + 0, + 0, + winapi::SMTO_ABORTIFHUNG, + 200, + ptr::null_mut(), + ); + winapi::SendMessageTimeoutW( + winapi::HWND_BROADCAST, + winapi::WM_SYSCOLORCHANGE, + 0, + 0, + winapi::SMTO_ABORTIFHUNG, + 200, + ptr::null_mut(), + ); winapi::ExitProcess(0); } diff --git a/standard/src/main.rs b/standard/src/main.rs index 049ae0a..2b06a80 100644 --- a/standard/src/main.rs +++ b/standard/src/main.rs @@ -94,16 +94,13 @@ unsafe fn broadcast(msg: u32, lparam: isize) { unsafe fn refresh_theme() { let theme_str = to_utf16("ImmersiveColorSet"); broadcast(WM_SETTINGCHANGE, theme_str.as_ptr() as isize); - - // 目前实测发现 WM_THEMECHANGED 和 WM_SYSCOLORCHANGE 的广播非必须,暂时注释掉(调试用) - // broadcast(WM_THEMECHANGED, 0); - // broadcast(WM_SYSCOLORCHANGE, 0); + broadcast(WM_THEMECHANGED, 0); + broadcast(WM_SYSCOLORCHANGE, 0); } fn main() { unsafe { let current = read_reg_dword(HKEY_CURRENT_USER, PATH, "AppsUseLightTheme").unwrap_or(1); - // let new_value = if current == 0 { 1 } else { 0 }; let new_value = 1 - current; // 更简洁的切换逻辑 write_reg_dword(HKEY_CURRENT_USER, PATH, "AppsUseLightTheme", new_value);