我正在尝试使用Windows API制作一个应用程序,通过修改注册表值
AppsUseLightTheme
和SystemUsesLightTheme
下的HKCU\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize
来更改Windows 10/11中的颜色主题。
现在,当
AppsUseLightTheme
更改时,无论是使用 regedit.exe
或 reg /add
命令,甚至是 RegSetKeyValueW()
(来自 API),所有打开的应用程序都会自动刷新其主题。
但是,更改
SystemUsesLightTheme
(会影响任务栏、“开始”菜单、通知中心和操作中心)会触发上述所有内容的刷新,任务栏除外,任务栏将保持这种状态,直到重新启动 explorer.exe
。
WM_SETTINGCHANGE
向所有顶级窗口发送 SendMessageTimeoutW()
消息,正如 Raymond Chen 本人 here 所建议的那样,但任务栏仍然不尊重配置,即使虽然返回 1(这意味着成功)。
我现在唯一的选择是在注册表值更改后重新启动资源管理器进程,但这并不理想,因为:
syntpenh.exe
)(对我有用,但有证据表明它不适用于所有人)。那么还有其他选择吗?
windows
Rust 板条箱,如下所示:
Cargo.toml:
[dependencies]
windows = { version = "0.46.0", features = ["Win32_Foundation", "Win32_System_WindowsProgramming", "Win32_System_Registry", "Win32_UI_WindowsAndMessaging"] }
main.rs:
use std::ffi::c_void;
use windows::w;
use windows::Win32::Foundation::*;
use windows::Win32::System::Registry::*;
use windows::Win32::UI::WindowsAndMessaging::*;
#[allow(non_snake_case)]
fn main() {
unsafe {
let mut handle = HKEY::default();
// open the key
let ret_code = RegOpenKeyExW(
HKEY_CURRENT_USER,
w!(r"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"),
0,
KEY_ALL_ACCESS,
&mut handle,
);
if ret_code.is_err() {
println!("{}", ret_code.to_hresult().message());
return;
}
// write the value
let buf: [u8; 4] = 0u32.to_le_bytes(); // 0 for Dark, 1 for Light
let ret_code = RegSetKeyValueW(
handle,
None,
w!("SystemUsesLightTheme"),
4,
Some(&buf as *const _ as *const c_void),
4,
);
if ret_code.is_err() {
println!("{}", ret_code.to_hresult().message());
return;
}
println!("Done changing");
// send message
let ret_code = SendMessageTimeoutW(
HWND(0xffff), // HWND_BROADCAST
WM_SETTINGCHANGE,
WPARAM(0),
LPARAM(w!("Policy").as_ptr() as isize),
SMTO_BLOCK,
5000,
None,
);
println!("{}", ret_code.0);
}
}
虽然 Python 不是这里讨论的语言,但我想提供一个潜在的解决方案,以回应建议此任务可能无法实现的评论。您可以通过重置“explorer.exe”进程以编程方式更新 Windows 任务栏。
如果您在 Python 脚本中运行此代码,它会将任务栏更新为浅色主题。在撰写本文时已在 Windows 11 中进行测试和运行。
import os
import subprocess
registry_path = "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"
# AppsUseLightTheme applies to apps, SystemUsesLightTheme applies to Windows UI.
# Use 0 for dark mode and 1 for light mode.
subprocess.run(['powershell', '-Command', f'Set-ItemProperty -Path {registry_path} -Name "AppsUseLightTheme" -Value 1'], check=True)
subprocess.run(['powershell', '-Command', f'Set-ItemProperty -Path {registry_path} -Name "SystemUsesLightTheme" -Value 1'], check=True)
# Restart the explorer.exe process for the theme to take effect on all UI elements.
os.system("taskkill /f /im explorer.exe")
os.system("start explorer.exe")