编辑SystemUsesLightTheme注册表项后如何刷新Windows任务栏?

问题描述 投票:0回答:1

我正在尝试使用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(这意味着成功)。

我现在唯一的选择是在注册表值更改后重新启动资源管理器进程,但这并不理想,因为:

  1. 某些资源管理器窗口可能在后台打开,重新启动会关闭它们。
  2. 重新启动资源管理器后,突触触控板滚动不起作用,除非另一个进程被终止(通常
    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);
    }
}
windows winapi rust
1个回答
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")
© www.soinside.com 2019 - 2024. All rights reserved.