Merge pull request #3844 from JasonWues/master

add follow system theme func
pull/3852/head
2dust 2023-05-13 20:04:41 +08:00 committed by GitHub
commit d9bf31d4f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 139 additions and 11 deletions

View File

@ -20,6 +20,8 @@
<system:Double x:Key="StdFontSize1">13</system:Double>
<system:Double x:Key="StdFontSize2">14</system:Double>
<system:Double x:Key="StdFontSizeMsg">11</system:Double>
<conv:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
<Thickness
x:Key="ServerItemMargin"
Bottom="4"

View File

@ -0,0 +1,24 @@
using System.Globalization;
using System.Windows.Data;
namespace v2rayN.Converters
{
[ValueConversion(typeof(bool), typeof(bool))]
public class InverseBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(targetType != typeof(bool))
{
throw new InvalidOperationException("The target must be a boolean");
}
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -116,6 +116,7 @@ namespace v2rayN.Mode
public double mainGirdHeight1 { get; set; }
public double mainGirdHeight2 { get; set; }
public bool colorModeDark { get; set; }
public bool followSystemTheme { get; set; }
public string? colorPrimaryName { get; set; }
public string currentLanguage { get; set; }
public string currentFontFamily { get; set; }

View File

@ -2527,6 +2527,15 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Follow System Theme 的本地化字符串。
/// </summary>
public static string TbSettingsFollowSystemTheme {
get {
return ResourceManager.GetString("TbSettingsFollowSystemTheme", resourceCulture);
}
}
/// <summary>
/// 查找类似 FontSize 的本地化字符串。
/// </summary>

View File

@ -505,6 +505,9 @@
<data name="TbSettingsColorMode" xml:space="preserve">
<value>Dark Mode</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Follow System Theme</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>Language(Restart)</value>
</data>

View File

@ -505,6 +505,9 @@
<data name="TbSettingsColorMode" xml:space="preserve">
<value>Тёмный режим</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>следить за системной темой</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>Язык (требуется перезапуск)</value>
</data>

View File

@ -505,6 +505,9 @@
<data name="TbSettingsColorMode" xml:space="preserve">
<value>暗黑模式</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>是否跟随系统主题</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>语言(重启)</value>
</data>

View File

@ -1047,6 +1047,13 @@ namespace v2rayN
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize);
}
public static bool IsLightTheme()
{
using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
var value = key?.GetValue("AppsUseLightTheme");
return value is int i && i > 0;
}
#endregion 杂项
#region TempPath

View File

@ -12,8 +12,10 @@ using System.Drawing;
using System.IO;
using System.Reactive;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using v2rayN.Base;
using v2rayN.Handler;
@ -237,6 +239,9 @@ namespace v2rayN.ViewModels
[Reactive]
public int CurrentFontSize { get; set; }
[Reactive]
public bool FollowSystemTheme { get; set; }
[Reactive]
public string CurrentLanguage { get; set; }
@ -244,7 +249,7 @@ namespace v2rayN.ViewModels
#region Init
public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue, Action<EViewAction> updateView)
public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue, Action<EViewAction> updateView,HwndSource hwndSource)
{
_updateView = updateView;
ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
@ -309,7 +314,7 @@ namespace v2rayN.ViewModels
y => y == true)
.Subscribe(c => DoEnableTun(c));
BindingUI();
BindingUI(hwndSource);
RestoreUI();
AutoHideStartup();
@ -1665,9 +1670,10 @@ namespace v2rayN.ViewModels
{
}
private void BindingUI()
private void BindingUI(HwndSource hwndSource)
{
ColorModeDark = _config.uiItem.colorModeDark;
FollowSystemTheme = _config.uiItem.followSystemTheme;
_swatches.AddRange(new SwatchesProvider().Swatches);
if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty())
{
@ -1690,6 +1696,57 @@ namespace v2rayN.ViewModels
}
});
this.WhenAnyValue(x => x.FollowSystemTheme,
y => y == true)
.Subscribe(c =>
{
if (_config.uiItem.followSystemTheme != FollowSystemTheme)
{
_config.uiItem.followSystemTheme = FollowSystemTheme;
if (FollowSystemTheme)
{
hwndSource.AddHook((IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
{
const int WM_SETTINGCHANGE = 0x001A;
if (msg == WM_SETTINGCHANGE)
{
if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet")
{
var isLightTheme = Utils.IsLightTheme();
ColorModeDark = !isLightTheme;
}
}
return IntPtr.Zero;
});
var isLightTheme = Utils.IsLightTheme();
ColorModeDark = !isLightTheme;
}
else
{
hwndSource.RemoveHook((IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
{
const int WM_SETTINGCHANGE = 0x001A;
if (msg == WM_SETTINGCHANGE)
{
if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet")
{
var isLightTheme = Utils.IsLightTheme();
ColorModeDark = !isLightTheme;
}
}
return IntPtr.Zero;
});
}
ConfigHandler.SaveConfig(ref _config);
}
});
this.WhenAnyValue(
x => x.SelectedSwatch,
y => y != null && !y.Name.IsNullOrEmpty())

View File

@ -301,6 +301,7 @@
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
@ -319,17 +320,30 @@
x:Name="togDarkMode"
Grid.Row="0"
Grid.Column="1"
Margin="8"
IsEnabled="{Binding ElementName=followSystemTheme, Path=IsChecked, Converter={StaticResource InverseBooleanConverter}}"/>
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
<ToggleButton
x:Name="followSystemTheme"
Grid.Row="1"
Grid.Column="1"
Margin="8" />
<TextBlock
Grid.Row="1"
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsColor}" />
<ComboBox
x:Name="cmbSwatches"
Grid.Row="1"
Grid.Row="2"
Grid.Column="1"
Width="100"
Margin="8"
@ -337,28 +351,28 @@
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="2"
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsFontSize}" />
<ComboBox
x:Name="cmbCurrentFontSize"
Grid.Row="2"
Grid.Row="3"
Grid.Column="1"
Width="100"
Margin="8"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="3"
Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLanguage}" />
<ComboBox
x:Name="cmbCurrentLanguage"
Grid.Row="3"
Grid.Row="4"
Grid.Column="1"
Width="100"
Margin="8"
@ -560,7 +574,7 @@
<MenuItem
x:Name="menuSpeedServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuSpeedServer}" />
Header="{x:Static resx:ResUI.menuSpeedServer}"/>
<MenuItem
x:Name="menuSortServerResult"
Height="{StaticResource MenuItemHeight}"

View File

@ -2,6 +2,7 @@
using Splat;
using System.ComponentModel;
using System.Reactive.Disposables;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
@ -43,7 +44,10 @@ namespace v2rayN.Views
lstProfiles.Drop += LstProfiles_Drop;
}
ViewModel = new MainWindowViewModel(MainSnackbar.MessageQueue!, UpdateViewHandler);
var helper = new WindowInteropHelper(this);
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
ViewModel = new MainWindowViewModel(MainSnackbar.MessageQueue!, UpdateViewHandler,hwndSource);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 8; i++)
@ -183,6 +187,7 @@ namespace v2rayN.Views
//UI
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.followSystemTheme.IsChecked).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);