gpt4 book ai didi

c# - 有没有办法让 WPF 应用程序尊重 Windows 10 中暗/亮主题的系统选择?

转载 作者:行者123 更新时间:2023-12-04 13:39:38 24 4
gpt4 key购买 nike

Windows 10 最近添加了深色模式;有没有办法让我的 WPF 应用程序尊重这个设置?最好是一个可以自动翻转它的开关,但如果没有,我想我可以在某处读取系统设置并切换到我的代码或其他东西中的备用主题......

最佳答案

没有直接的 API/事件可以从 wpf 检测暗模式或高对比度模式。这在 uwp 中可用。但是有一种方法可以通过 WMI 查询来检测主题更改事件,以查看相关注册表项的注册表更改。您会找到详细信息 here .
我有一个简化的类,您可以通过它检测注册表更改。

public class ThemeWatcher
{
private const string RegistryKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";

private const string RegistryValueName = "AppsUseLightTheme";
private static WindowsTheme windowsTheme;

public WindowsTheme WindowsTheme
{
get { return windowsTheme; }
set { windowsTheme = value; }
}

public void StartThemeWatching()
{
var currentUser = WindowsIdentity.GetCurrent();
string query = string.Format(
CultureInfo.InvariantCulture,
@"SELECT * FROM RegistryValueChangeEvent WHERE Hive = 'HKEY_USERS' AND KeyPath = '{0}\\{1}' AND ValueName = '{2}'",
currentUser.User.Value,
RegistryKeyPath.Replace(@"\", @"\\"),
RegistryValueName);

try
{
windowsTheme = GetWindowsTheme();
MergeThemeDictionaries(windowsTheme);

var watcher = new ManagementEventWatcher(query);
watcher.EventArrived += Watcher_EventArrived;
SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged;
// Start listening for events
watcher.Start();
}
catch (Exception ex)
{
// This can fail on Windows 7
windowsTheme = WindowsTheme.Default;

}

}

private void MergeThemeDictionaries(WindowsTheme windowsTheme)
{
string appTheme = "Light";
switch (windowsTheme)
{
case WindowsTheme.Light:
appTheme = "Light";
break;
case WindowsTheme.Dark:
appTheme = "Dark";
break;
case WindowsTheme.HighContrast:
appTheme = "HighContrast";
break;
}

App.Current.Resources.MergedDictionaries[0].Source = new Uri($"/Themes/{appTheme}.xaml", UriKind.Relative);

}

private void SystemParameters_StaticPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
windowsTheme = GetWindowsTheme();

MergeThemeDictionaries(windowsTheme);

ThemeChangedArgument themeChangedArgument = new ThemeChangedArgument();
themeChangedArgument.WindowsTheme = windowsTheme;

App.WindowsThemeChanged?.Invoke(this, themeChangedArgument);

}

private void Watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
windowsTheme = GetWindowsTheme();

MergeThemeDictionaries(windowsTheme);

ThemeChangedArgument themeChangedArgument = new ThemeChangedArgument();
themeChangedArgument.WindowsTheme = windowsTheme;

App.WindowsThemeChanged?.Invoke(this, themeChangedArgument);

}

public WindowsTheme GetWindowsTheme()
{
WindowsTheme theme = WindowsTheme.Light;

try
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistryKeyPath))
{
object registryValueObject = key?.GetValue(RegistryValueName);
if (registryValueObject == null)
{
return WindowsTheme.Light;
}

int registryValue = (int)registryValueObject;

if (SystemParameters.HighContrast)
theme = WindowsTheme.HighContrast;

theme = registryValue > 0 ? WindowsTheme.Light : WindowsTheme.Dark;
}

return theme;
}
catch (Exception ex)
{
return theme;
}
}
}
为逻辑实现创建真实的枚举:
public enum WindowsTheme
{
Default = 0,
Light = 1,
Dark = 2,
HighContrast = 3
}
将相关资源文件添加到项目中。
enter image description here
定义一个回调参数,该参数将在发生注册表更改时通过事件处理程序传递。
public class ThemeChangedArgument
{
public WindowsTheme WindowsTheme { set; get; }
}
现在开始观看从 App.xaml.cs 的 OnStartup 方法更改的主题。
public partial class App : Application
{
private ThemeWatcher themeWatcher;
private WindowsTheme systrayTheme = WindowsTheme.Light;
public static EventHandler<ThemeChangedArgument> WindowsThemeChanged;
.......

protected override void OnStartup(StartupEventArgs e)
{
.......................
themeWatcher = new ThemeWatcher();
systrayTheme = themeWatcher.GetWindowsTheme();
themeWatcher.StartThemeWatching();

if(WindowsThemeChanged != null)
{
WindowsThemeChanged -= OnWindowsThemeChanged;
}

WindowsThemeChanged += OnWindowsThemeChanged;
.......................
}

private void OnWindowsThemeChanged(object sender, ThemeChangedArgument e)
{
systrayTheme = e.WindowsTheme;
//Now do whatever you want to do with this updated theme.
}


protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);

try
{
if (WindowsThemeChanged != null)
{
WindowsThemeChanged -= OnWindowsThemeChanged;
}
Application.Current?.Shutdown();
Process.GetCurrentProcess()?.Kill();
}
catch (Exception ex)
{

}
}

}
注意:我们已经将来自 ThemeWatcher 类的相关样式资源与方法 合并了。 MergeThemeDictionaries() 由于主题改变事件被触发。您也可以根据需要从这里更新它。
调用以下方法以在由于运行时更改资源后更新 UI。
    private void InvalidedMainWindow()
{
if (!Application.Current.Dispatcher.CheckAccess())
{
Application.Current.Dispatcher.InvokeAsync(() => InvalidedMainWindow());
return;
}

App.Current.MainWindow.UpdateLayout();
}

关于c# - 有没有办法让 WPF 应用程序尊重 Windows 10 中暗/亮主题的系统选择?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59366391/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com