文件更名

This commit is contained in:
2026-04-05 21:50:53 +08:00
parent 5aad206e0d
commit bcbece5bd6
30 changed files with 64 additions and 64 deletions
@@ -0,0 +1,584 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Media = System.Windows.Media;
namespace Ink_Canvas.Windows.SettingsViews
{
public static class MainWindowSettingsHelper
{
private static MainWindow GetMainWindow()
{
return Application.Current.MainWindow as MainWindow;
}
/// <summary>
/// 调用 MainWindow 中的方法
/// </summary>
public static void InvokeMainWindowMethod(string methodName, params object[] parameters)
{
try
{
var mainWindow = GetMainWindow();
if (mainWindow == null) return;
var method = mainWindow.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (method != null)
{
method.Invoke(mainWindow, parameters);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"调用 MainWindow 方法 {methodName} 失败: {ex.Message}");
}
}
/// <summary>
/// 调用 MainWindow 中的 ToggleSwitch 事件处理方法
/// </summary>
public static void InvokeToggleSwitchToggled(string toggleSwitchName, bool isOn)
{
try
{
var mainWindow = GetMainWindow();
if (mainWindow == null) return;
// 获取 MainWindow 中的 ToggleSwitch 控件
var toggleSwitch = mainWindow.FindName(toggleSwitchName);
if (toggleSwitch == null)
{
// 如果找不到控件,尝试通过反射设置属性
var property = mainWindow.GetType().GetProperty(toggleSwitchName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (property != null && property.PropertyType.Name.Contains("ToggleSwitch"))
{
var isOnProperty = property.PropertyType.GetProperty("IsOn");
if (isOnProperty != null)
{
var toggleSwitchInstance = property.GetValue(mainWindow);
if (toggleSwitchInstance != null)
{
isOnProperty.SetValue(toggleSwitchInstance, isOn);
}
}
}
// 即使找不到控件,也尝试触发事件(可能通过反射调用)
var toggledMethodName = toggleSwitchName + "_Toggled";
InvokeMainWindowMethod(toggledMethodName, null, new RoutedEventArgs());
// 通知新设置面板同步状态
NotifySettingsPanelsSyncState(toggleSwitchName);
return;
}
// 设置 ToggleSwitch 的 IsOn 属性
var toggleSwitchType = toggleSwitch.GetType();
var isOnProp = toggleSwitchType.GetProperty("IsOn");
if (isOnProp != null)
{
isOnProp.SetValue(toggleSwitch, isOn);
}
// 触发 Toggled 事件
var toggledMethodName2 = toggleSwitchName + "_Toggled";
InvokeMainWindowMethod(toggledMethodName2, toggleSwitch, new RoutedEventArgs());
// 通知新设置面板同步状态
NotifySettingsPanelsSyncState(toggleSwitchName);
// 检查是否需要更新主题
NotifyThemeUpdateIfNeeded(toggleSwitchName);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"调用 ToggleSwitch {toggleSwitchName} 失败: {ex.Message}");
}
}
/// <summary>
/// 调用 MainWindow 中的 ComboBox 事件处理方法
/// </summary>
public static void InvokeComboBoxSelectionChanged(string comboBoxName, object selectedItem)
{
try
{
var mainWindow = GetMainWindow();
if (mainWindow == null) return;
// 获取 MainWindow 中的 ComboBox 控件
var comboBox = mainWindow.FindName(comboBoxName) as System.Windows.Controls.ComboBox;
if (comboBox != null)
{
comboBox.SelectedItem = selectedItem;
// 触发 SelectionChanged 事件
var selectionChangedMethodName = comboBoxName + "_SelectionChanged";
InvokeMainWindowMethod(selectionChangedMethodName, comboBox, new System.Windows.Controls.SelectionChangedEventArgs(
System.Windows.Controls.Primitives.Selector.SelectionChangedEvent,
new System.Collections.IList[0],
new System.Collections.IList[0]));
}
// 通知新设置面板同步状态
NotifySettingsPanelsSyncState(comboBoxName);
// 检查是否需要更新主题
NotifyThemeUpdateIfNeeded(comboBoxName);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"调用 ComboBox {comboBoxName} 失败: {ex.Message}");
}
}
/// <summary>
/// 调用 MainWindow 中的 Slider 事件处理方法
/// </summary>
public static void InvokeSliderValueChanged(string sliderName, double value)
{
try
{
var mainWindow = GetMainWindow();
if (mainWindow == null) return;
// 获取 MainWindow 中的 Slider 控件
var slider = mainWindow.FindName(sliderName) as System.Windows.Controls.Slider;
if (slider != null)
{
var oldValue = slider.Value;
slider.Value = value;
// 触发 ValueChanged 事件
var valueChangedMethodName = sliderName + "_ValueChanged";
InvokeMainWindowMethod(valueChangedMethodName, slider,
new System.Windows.RoutedPropertyChangedEventArgs<double>(oldValue, value));
}
// 通知新设置面板同步状态
NotifySettingsPanelsSyncState(sliderName);
// 检查是否需要更新主题(某些Slider可能影响UI外观)
NotifyThemeUpdateIfNeeded(sliderName);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"调用 Slider {sliderName} 失败: {ex.Message}");
}
}
/// <summary>
/// 调用 MainWindow 中的 CheckBox 事件处理方法
/// </summary>
public static void InvokeCheckBoxCheckedChanged(string checkBoxName, bool isChecked)
{
try
{
var mainWindow = GetMainWindow();
if (mainWindow == null) return;
// 获取 MainWindow 中的 CheckBox 控件
var checkBox = mainWindow.FindName(checkBoxName) as System.Windows.Controls.CheckBox;
if (checkBox != null)
{
checkBox.IsChecked = isChecked;
// 尝试多种可能的方法名
var methodNames = new[]
{
checkBoxName + "_IsCheckChanged",
checkBoxName + "_IsCheckChange",
checkBoxName + "_Checked",
checkBoxName + "_Unchecked"
};
foreach (var methodName in methodNames)
{
var method = mainWindow.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (method != null)
{
InvokeMainWindowMethod(methodName, checkBox, new RoutedEventArgs());
break;
}
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"调用 CheckBox {checkBoxName} 失败: {ex.Message}");
}
}
/// <summary>
/// 安全地修改设置并保存,优先调用 MainWindow 中的事件处理方法
/// 如果找不到对应的事件处理方法,则直接修改设置并保存
/// </summary>
/// <param name="action">设置修改的 Action,例如:() => MainWindow.Settings.Startup.IsAutoUpdate = true</param>
/// <param name="eventHandlerName">可选:要调用的 MainWindow 事件处理方法名(如 "ToggleSwitchIsAutoUpdate_Toggled"</param>
/// <param name="controlName">可选:控件名称,用于状态同步(如 "ToggleSwitchIsAutoUpdate"</param>
/// <param name="eventHandlerParams">可选:事件处理方法的参数</param>
public static void UpdateSettingSafely(Action action, string eventHandlerName = null, string controlName = null, params object[] eventHandlerParams)
{
try
{
// 如果提供了事件处理方法名,优先调用
if (!string.IsNullOrEmpty(eventHandlerName))
{
var mainWindow = GetMainWindow();
if (mainWindow != null)
{
var method = mainWindow.GetType().GetMethod(eventHandlerName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (method != null)
{
// 调用事件处理方法(它会自动保存设置并触发状态同步)
method.Invoke(mainWindow, eventHandlerParams);
// 如果提供了控件名称,确保状态同步
if (!string.IsNullOrEmpty(controlName))
{
NotifySettingsPanelsSyncState(controlName);
}
return;
}
}
}
// 如果没有事件处理方法或调用失败,直接修改设置并保存
action?.Invoke();
MainWindow.SaveSettingsToFile();
// 如果提供了控件名称,通知面板同步状态
if (!string.IsNullOrEmpty(controlName))
{
NotifySettingsPanelsSyncState(controlName);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"更新设置失败: {ex.Message}");
}
}
/// <summary>
/// 直接修改设置属性并保存(用于没有对应事件处理方法的设置项)
/// </summary>
/// <param name="action">设置修改的 Action</param>
/// <param name="controlName">可选:控件名称,用于状态同步(如 "ToggleSwitchIsAutoUpdate"</param>
public static void UpdateSettingDirectly(Action action, string controlName = null)
{
try
{
action?.Invoke();
MainWindow.SaveSettingsToFile();
// 如果提供了控件名称,通知面板同步状态
if (!string.IsNullOrEmpty(controlName))
{
NotifySettingsPanelsSyncState(controlName);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"直接更新设置失败: {ex.Message}");
}
}
/// <summary>
/// 调用 MainWindow 中的 TextBox 事件处理方法
/// </summary>
public static void InvokeTextBoxTextChanged(string textBoxName, string text)
{
try
{
var mainWindow = GetMainWindow();
if (mainWindow == null) return;
// 获取 MainWindow 中的 TextBox 控件
var textBox = mainWindow.FindName(textBoxName) as System.Windows.Controls.TextBox;
if (textBox != null)
{
textBox.Text = text;
// 触发 TextChanged 事件
var textChangedMethodName = textBoxName + "_TextChanged";
InvokeMainWindowMethod(textChangedMethodName, textBox, new System.Windows.Controls.TextChangedEventArgs(
System.Windows.Controls.Primitives.TextBoxBase.TextChangedEvent,
System.Windows.Controls.UndoAction.None));
}
// 通知新设置面板同步状态
NotifySettingsPanelsSyncState(textBoxName);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"调用 TextBox {textBoxName} 失败: {ex.Message}");
}
}
/// <summary>
/// 通知所有新设置面板同步指定控件的状态
/// </summary>
public static void NotifySettingsPanelsSyncState(string controlName)
{
try
{
// 延迟执行,确保设置已经保存
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
// 查找所有打开的设置窗口
foreach (Window window in Application.Current.Windows)
{
if (window.GetType().Name == "SettingsWindow")
{
// 同步所有面板(保守策略)
SyncAllPanels(window);
break; // 通常只有一个设置窗口
}
}
}), System.Windows.Threading.DispatcherPriority.Background);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"通知设置面板同步状态失败: {ex.Message}");
}
}
/// <summary>
/// 同步所有面板的状态(保守策略)
/// </summary>
private static void SyncAllPanels(Window settingsWindow)
{
try
{
// 获取所有页面属性
var pageProperties = settingsWindow.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType.Name.EndsWith("Page") &&
p.PropertyType.IsSubclassOf(typeof(System.Windows.Controls.Page)));
foreach (var pageProp in pageProperties)
{
try
{
var page = pageProp.GetValue(settingsWindow) as System.Windows.Controls.Page;
if (page != null)
{
// 调用 LoadSettings 方法
var loadMethod = page.GetType().GetMethod("LoadSettings",
BindingFlags.Public | BindingFlags.Instance);
if (loadMethod != null)
{
loadMethod.Invoke(page, null);
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"同步页面 {pageProp.Name} 状态失败: {ex.Message}");
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"同步所有页面状态失败: {ex.Message}");
}
}
/// <summary>
/// 检查并通知设置窗口更新主题(如果设置变化可能影响主题)
/// </summary>
/// <param name="controlName">控件名称,用于判断是否是主题相关的设置</param>
public static void NotifyThemeUpdateIfNeeded(string controlName)
{
try
{
if (string.IsNullOrEmpty(controlName)) return;
// 定义可能影响主题的控件名称列表(扩展版)
var themeRelatedControls = new[]
{
"ComboBoxTheme", // 主题选择
"ToggleSwitchEnableTrayIcon", // 托盘图标(可能影响图标颜色)
"ComboBoxFloatingBarImg", // 浮动栏图标
"ComboBoxUnFoldBtnImg", // 展开按钮图标
"ComboBoxSplashScreenStyle", // 启动画面样式
"ToggleSwitchEnableSplashScreen", // 启动画面开关
"ViewboxFloatingBarScaleTransformValueSlider", // 浮动栏缩放(可能影响UI
"ViewboxFloatingBarOpacityValueSlider", // 浮动栏透明度
"ViewboxFloatingBarOpacityInPPTValueSlider", // PPT中浮动栏透明度
"UnFoldBtnImg", // 展开按钮图标(选项按钮)
"FloatingBarImg", // 浮动栏图标(选项按钮)
"Theme" // 主题(选项按钮)
};
// 检查是否是主题相关的设置(使用更灵活的匹配)
bool isThemeRelated = false;
string controlNameLower = controlName.ToLower();
foreach (var themeControl in themeRelatedControls)
{
string themeControlLower = themeControl.ToLower();
// 检查是否包含或匹配
if (controlNameLower.Contains(themeControlLower) ||
themeControlLower.Contains(controlNameLower) ||
controlNameLower == themeControlLower)
{
isThemeRelated = true;
break;
}
}
if (isThemeRelated)
{
// 延迟通知,确保设置已保存
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
// 通知设置窗口更新主题
NotifySettingsWindowThemeUpdate();
}), System.Windows.Threading.DispatcherPriority.Background);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"通知主题更新失败: {ex.Message}");
}
}
/// <summary>
/// 通知设置窗口更新所有页面的主题
/// </summary>
private static void NotifySettingsWindowThemeUpdate()
{
try
{
// 查找所有打开的设置窗口
foreach (Window window in Application.Current.Windows)
{
// 使用类型名称匹配,因为 SettingsWindow 在不同的命名空间中
if (window.GetType().Name == "SettingsWindow")
{
// 同时调用 ApplyTheme 方法更新窗口本身
var applyThemeMethod = window.GetType().GetMethod("ApplyTheme",
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (applyThemeMethod != null)
{
applyThemeMethod.Invoke(window, null);
}
break; // 通常只有一个设置窗口
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"通知设置窗口主题更新失败: {ex.Message}");
}
}
/// <summary>
/// 强制更新所有设置页面的主题(公共方法,可在外部调用)
/// </summary>
public static void ForceUpdateAllPanelsTheme()
{
NotifySettingsWindowThemeUpdate();
}
/// <summary>
/// 调用 MainWindow 中的 ComboBox 事件处理方法(增强版,支持主题更新通知)
/// </summary>
public static void InvokeComboBoxSelectionChangedWithThemeCheck(string comboBoxName, object selectedItem)
{
InvokeComboBoxSelectionChanged(comboBoxName, selectedItem);
NotifyThemeUpdateIfNeeded(comboBoxName);
}
/// <summary>
/// 调用 MainWindow 中的 ToggleSwitch 事件处理方法(增强版,支持主题更新通知)
/// </summary>
public static void InvokeToggleSwitchToggledWithThemeCheck(string toggleSwitchName, bool isOn)
{
InvokeToggleSwitchToggled(toggleSwitchName, isOn);
NotifyThemeUpdateIfNeeded(toggleSwitchName);
}
/// <summary>
/// 为控件树中的所有交互控件启用触摸支持(公共方法,可在外部调用)
/// </summary>
/// <param name="parent">父控件</param>
public static void EnableTouchSupportForControls(DependencyObject parent)
{
if (parent == null) return;
for (int i = 0; i < Media.VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = Media.VisualTreeHelper.GetChild(parent, i);
// 为 Border 控件(ToggleSwitch、选项按钮等)启用触摸支持
if (child is Border border)
{
// 检查是否是交互控件(有 Tag 或 Cursor 为 Hand
if (border.Tag != null || border.Cursor == Cursors.Hand)
{
border.IsManipulationEnabled = true;
// 添加触摸事件支持,将触摸事件转换为鼠标事件
border.TouchDown += (s, e) =>
{
var touchPoint = e.GetTouchPoint(border);
var mouseEvent = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left)
{
RoutedEvent = UIElement.MouseLeftButtonDownEvent,
Source = border
};
border.RaiseEvent(mouseEvent);
border.CaptureTouch(e.TouchDevice);
e.Handled = true;
};
// 添加触摸释放事件
border.TouchUp += (s, e) =>
{
border.ReleaseTouchCapture(e.TouchDevice);
e.Handled = true;
};
}
}
// 为 Button 控件启用触摸支持
else if (child is Button button)
{
button.IsManipulationEnabled = true;
}
// 为 ComboBox 启用触摸支持
else if (child is ComboBox comboBox)
{
comboBox.IsManipulationEnabled = true;
}
// 为 Slider 启用触摸支持
else if (child is Slider slider)
{
slider.IsManipulationEnabled = true;
}
// 为 TextBox 启用触摸支持
else if (child is TextBox textBox)
{
textBox.IsManipulationEnabled = true;
}
// 为 CheckBox 启用触摸支持
else if (child is CheckBox checkBox)
{
checkBox.IsManipulationEnabled = true;
}
// 为 RadioButton 启用触摸支持
else if (child is RadioButton radioButton)
{
radioButton.IsManipulationEnabled = true;
}
// 递归处理子元素
EnableTouchSupportForControls(child);
}
}
}
}
@@ -0,0 +1,17 @@
<ui:Page
x:Class="Ink_Canvas.Windows.SettingsViews.Pages.AboutPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
Title="关于"
mc:Ignorable="d">
<Grid>
<StackPanel Margin="24">
<TextBlock Text="关于 InkCanvasForClass" Style="{DynamicResource TitleTextBlockStyle}" Margin="0,0,0,16" />
<TextBlock Text="这里是关于页面" Style="{DynamicResource BodyTextBlockStyle}" />
</StackPanel>
</Grid>
</ui:Page>
@@ -0,0 +1,12 @@
using iNKORE.UI.WPF.Modern.Controls;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class AboutPage : Page
{
public AboutPage()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,49 @@
<Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.AppearancePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="外观">
<Grid Margin="24">
<StackPanel>
<TextBlock Text="外观设置" Style="{DynamicResource TitleTextBlockStyle}" Margin="0,0,0,16" />
<ui:SettingsCard
Header="主题"
Description="点击跳转到主题设置页面"
IsClickEnabled="True"
Click="SettingsCard_Click">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Color}"/>
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard
Header="颜色"
Description="点击跳转到颜色设置页面"
IsClickEnabled="True"
Click="SettingsCard_Click_1"
Margin="0,8,0,0">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Color}"/>
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard
Header="字体"
Description="点击跳转到字体设置页面"
IsClickEnabled="True"
Click="SettingsCard_Click_2"
Margin="0,8,0,0">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Font}"/>
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
</StackPanel>
</Grid>
</Page>
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class AppearancePage : Page
{
public AppearancePage()
{
InitializeComponent();
}
private void SettingsCard_Click(object sender, RoutedEventArgs e)
{
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
settingsWindow.NavigateToPage("ThemePage");
}
}
private void SettingsCard_Click_1(object sender, RoutedEventArgs e)
{
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
settingsWindow.NavigateToPage("ColorsPage");
}
}
private void SettingsCard_Click_2(object sender, RoutedEventArgs e)
{
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
settingsWindow.NavigateToPage("FontsPage");
}
}
}
}
@@ -0,0 +1,48 @@
<Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.BasicPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:i18n="clr-namespace:Ink_Canvas.MarkupExtensions"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="基本">
<ScrollViewer Padding="59,0,59,0">
<!-- These styles can be referenced to create a consistent SettingsPage layout -->
<FrameworkElement.Resources>
<!-- Spacing between cards -->
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
<!-- Style (inc. the correct spacing) of a section header -->
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
TargetType="TextBlock">
<Style.Setters>
<Setter Property="Margin" Value="1,30,0,6" />
</Style.Setters>
</Style>
</FrameworkElement.Resources>
<Grid>
<ikw:SimpleStackPanel MaxWidth="800"
HorizontalAlignment="Stretch"
Spacing="{StaticResource SettingsCardSpacing}">
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="启动时行为" />
<ui:SettingsCard
Header="启动设置"
Description="点击跳转到启动设置页面"
IsClickEnabled="True"
Click="SettingsCard_Click">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Play}"/>
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
</ikw:SimpleStackPanel>
</Grid>
</ScrollViewer>
</Page>
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
/// <summary>
/// Basic.xaml 的交互逻辑
/// </summary>
public partial class BasicPage : Page
{
public BasicPage()
{
InitializeComponent();
}
private void SettingsCard_Click(object sender, RoutedEventArgs e)
{
// 找到SettingsWindow窗口
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
// 调用NavigateToPage方法导航到启动页面
settingsWindow.NavigateToPage("StartupPage");
}
}
}
}
@@ -0,0 +1,17 @@
<ui:Page
x:Class="Ink_Canvas.Windows.SettingsViews.Pages.ColorsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
Title="颜色设置"
mc:Ignorable="d">
<Grid>
<StackPanel Margin="24">
<TextBlock Text="颜色设置" Style="{DynamicResource TitleTextBlockStyle}" Margin="0,0,0,16" />
<TextBlock Text="这里是颜色设置页面" Style="{DynamicResource BodyTextBlockStyle}" />
</StackPanel>
</Grid>
</ui:Page>
@@ -0,0 +1,12 @@
using iNKORE.UI.WPF.Modern.Controls;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class ColorsPage : Page
{
public ColorsPage()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,38 @@
<Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.DesignPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="设计">
<Grid Margin="24">
<StackPanel>
<TextBlock Text="设计设置" Style="{DynamicResource TitleTextBlockStyle}" Margin="0,0,0,16" />
<ui:SettingsCard
Header="图标"
Description="点击跳转到图标设置页面"
IsClickEnabled="True"
Click="SettingsCard_Click">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Home}"/>
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard
Header="排版"
Description="点击跳转到排版设置页面"
IsClickEnabled="True"
Click="SettingsCard_Click_1"
Margin="0,8,0,0">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Font}"/>
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
</StackPanel>
</Grid>
</Page>
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class DesignPage : Page
{
public DesignPage()
{
InitializeComponent();
}
private void SettingsCard_Click(object sender, RoutedEventArgs e)
{
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
settingsWindow.NavigateToPage("IconographyPage");
}
}
private void SettingsCard_Click_1(object sender, RoutedEventArgs e)
{
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
settingsWindow.NavigateToPage("TypographyPage");
}
}
}
}
@@ -0,0 +1,17 @@
<ui:Page
x:Class="Ink_Canvas.Windows.SettingsViews.Pages.FontsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
Title="字体设置"
mc:Ignorable="d">
<Grid>
<StackPanel Margin="24">
<TextBlock Text="字体设置" Style="{DynamicResource TitleTextBlockStyle}" Margin="0,0,0,16" />
<TextBlock Text="这里是字体设置页面" Style="{DynamicResource BodyTextBlockStyle}" />
</StackPanel>
</Grid>
</ui:Page>
@@ -0,0 +1,12 @@
using iNKORE.UI.WPF.Modern.Controls;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class FontsPage : Page
{
public FontsPage()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,78 @@
<Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.HomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:i18n="clr-namespace:Ink_Canvas.MarkupExtensions"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="首页">
<ScrollViewer Padding="59,0,59,0">
<!-- These styles can be referenced to create a consistent SettingsPage layout -->
<FrameworkElement.Resources>
<!-- Spacing between cards -->
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
<!-- Style (inc. the correct spacing) of a section header -->
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
TargetType="TextBlock">
<Style.Setters>
<Setter Property="Margin" Value="1,30,0,6" />
</Style.Setters>
</Style>
</FrameworkElement.Resources>
<Grid>
<ikw:SimpleStackPanel MaxWidth="800"
HorizontalAlignment="Stretch"
Spacing="{StaticResource SettingsCardSpacing}">
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="快速导航" />
<ui:SettingsCard
Header="基本设置"
Description="点击跳转到基本设置页面"
IsClickEnabled="True"
Click="SettingsCard_Basic_Click">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Home}"/>
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard
Header="页面 2"
Description="点击跳转到页面 2"
IsClickEnabled="True"
Click="SettingsCard_Page2_Click">
<ui:SettingsCard.HeaderIcon>
<ui:SymbolIcon Symbol="Document" />
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard
Header="设计设置"
Description="点击跳转到设计设置页面"
IsClickEnabled="True"
Click="SettingsCard_Design_Click">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Design}"/>
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard
Header="外观设置"
Description="点击跳转到外观设置页面"
IsClickEnabled="True"
Click="SettingsCard_Appearance_Click">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Color}"/>
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
</ikw:SimpleStackPanel>
</Grid>
</ScrollViewer>
</Page>
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
/// <summary>
/// HomePage.xaml 的交互逻辑
/// </summary>
public partial class HomePage : Page
{
public HomePage()
{
InitializeComponent();
}
private void SettingsCard_Basic_Click(object sender, RoutedEventArgs e)
{
// 找到SettingsWindow窗口
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
// 调用NavigateToPage方法导航到基本设置页面
settingsWindow.NavigateToPage("BasicPage");
}
}
private void SettingsCard_Page2_Click(object sender, RoutedEventArgs e)
{
// 找到SettingsWindow窗口
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
// 调用NavigateToPage方法导航到页面2
settingsWindow.NavigateToPage("Page2Page");
}
}
private void SettingsCard_Design_Click(object sender, RoutedEventArgs e)
{
// 找到SettingsWindow窗口
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
// 调用NavigateToPage方法导航到设计设置页面
settingsWindow.NavigateToPage("DesignPage");
}
}
private void SettingsCard_Appearance_Click(object sender, RoutedEventArgs e)
{
// 找到SettingsWindow窗口
SettingsWindow settingsWindow = Window.GetWindow(this) as SettingsWindow;
if (settingsWindow != null)
{
// 调用NavigateToPage方法导航到外观设置页面
settingsWindow.NavigateToPage("AppearancePage");
}
}
}
}
@@ -0,0 +1,39 @@
<ui:Page
x:Class="Ink_Canvas.Windows.SettingsViews.Pages.IconographyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:controls="clr-namespace:Ink_Canvas.Controls"
Title="图标设置"
mc:Ignorable="d">
<Grid x:Name="RootGrid">
<StackPanel Margin="24">
<ui:SettingsExpander x:Name="settingsCard" VerticalAlignment="Top"
Description="The SettingsExpander has the same properties as a Card, and you can set SettingsCard as part of the Items collection."
Header="SettingsExpander" IsEnabled="True">
<ui:SettingsExpander.HeaderIcon>
<ui:FontIcon Glyph="&#xE91B;"/>
</ui:SettingsExpander.HeaderIcon>
<controls:CopyButton Text="You can override the Left indention of a SettingsCard by overriding the SettingsCardLeftIndention"/>
<ui:SettingsExpander.Items>
<ui:SettingsCard Description="You can override the Left indention of a SettingsCard by overriding the SettingsCardLeftIndention"
Header="Customization">
<ui:SettingsCard.Resources>
<sys:Double x:Key="SettingsCardLeftIndention">0</sys:Double>
</ui:SettingsCard.Resources>
</ui:SettingsCard>
</ui:SettingsExpander.Items>
</ui:SettingsExpander>
</StackPanel>
</Grid>
</ui:Page>
@@ -0,0 +1,10 @@
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class IconographyPage : iNKORE.UI.WPF.Modern.Controls.Page
{
public IconographyPage()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,14 @@
<Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.Page2Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Page2">
<Grid>
</Grid>
</Page>
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
/// <summary>
/// Page2.xaml 的交互逻辑
/// </summary>
public partial class Page2Page : Page
{
public Page2Page()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,17 @@
<ui:Page
x:Class="Ink_Canvas.Windows.SettingsViews.Pages.SettingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
Title="设置"
mc:Ignorable="d">
<Grid>
<StackPanel Margin="24">
<TextBlock Text="设置" Style="{DynamicResource TitleTextBlockStyle}" Margin="0,0,0,16" />
<TextBlock Text="这里是设置页面" Style="{DynamicResource BodyTextBlockStyle}" />
</StackPanel>
</Grid>
</ui:Page>
@@ -0,0 +1,12 @@
using iNKORE.UI.WPF.Modern.Controls;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class SettingsPage : Page
{
public SettingsPage()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,117 @@
<Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.StartupPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Ink_Canvas.Windows.SettingsViews.Pages"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:i18n="clr-namespace:Ink_Canvas.MarkupExtensions"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="950" d:DesignWidth="800"
Title="启动">
<ScrollViewer Padding="59,0,59,0">
<FrameworkElement.Resources>
<!-- Spacing between cards -->
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
<!-- Style (inc. the correct spacing) of a section header -->
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
TargetType="TextBlock">
<Style.Setters>
<Setter Property="Margin" Value="1,30,0,6" />
</Style.Setters>
</Style>
</FrameworkElement.Resources>
<Grid>
<ikw:SimpleStackPanel MaxWidth="1000"
HorizontalAlignment="Stretch"
Spacing="{StaticResource SettingsCardSpacing}">
<!-- 窗口设置 -->
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="窗口设置" />
<!-- 窗口无焦点模式 -->
<ui:SettingsCard Description="{i18n:I18n Key=Startup_NoFocusModeHint}"
Header="{i18n:I18n Key=Startup_NoFocusMode}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.View}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch Name="ToggleSwitchNoFocusMode" Toggled="ToggleSwitchNoFocusMode_Toggled" />
</ui:SettingsCard>
<!-- 窗口无边框模式 -->
<ui:SettingsCard Description="{i18n:I18n Key=Startup_NoBorderModeHint}"
Header="{i18n:I18n Key=Startup_NoBorderMode}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.FullScreen}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch Name="ToggleSwitchWindowMode" Toggled="ToggleSwitchWindowMode_Toggled" />
</ui:SettingsCard>
<!-- 窗口置顶 -->
<ui:SettingsCard Description="{i18n:I18n Key=Startup_TopMostHint}"
Header="{i18n:I18n Key=Startup_TopMost}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Pinned}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch Name="ToggleSwitchAlwaysOnTop" Toggled="ToggleSwitchAlwaysOnTop_Toggled" />
</ui:SettingsCard>
<!-- UIA置顶 -->
<ui:SettingsCard Description="{i18n:I18n Key=Startup_UIAccessTopMostHint_1}"
Header="{i18n:I18n Key=Startup_UIATopMost}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Shield}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch Name="ToggleSwitchUIAccessTopMost" Toggled="ToggleSwitchUIAccessTopMost_Toggled" />
</ui:SettingsCard>
<!-- 启动设置 -->
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="启动设置" />
<!-- 开机时运行 -->
<ui:SettingsCard Description="{i18n:I18n Key=Startup_RunAtStartupHint}"
Header="{i18n:I18n Key=Startup_RunAtStartup}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}"/>
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch Name="ToggleSwitchRunAtStartup" Toggled="ToggleSwitchRunAtStartup_Toggled" />
</ui:SettingsCard>
<!-- 开机运行后收纳到侧边栏 -->
<ui:SettingsCard Description="{i18n:I18n Key=Startup_FoldAtStartupHint}"
Header="{i18n:I18n Key=Startup_FoldAtStartup}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.ChevronLeft}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch Name="ToggleSwitchFoldAtStartup" Toggled="ToggleSwitchFoldAtStartup_Toggled" />
</ui:SettingsCard>
<!-- 模式设置 -->
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="模式设置" />
<ui:SettingsExpander Description="{i18n:I18n Key=Settings_ModeDesc}"
Header="{i18n:I18n Key=Settings_ModeDesc_1}">
<ui:SettingsExpander.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
</ui:SettingsExpander.HeaderIcon>
<ui:SettingsExpander.Items>
<ui:SettingsCard Header="仅PPT模式">
<ui:ToggleSwitch Name="ToggleSwitchPPTOnlyMode" Toggled="ToggleSwitchPPTOnlyMode_Toggled" />
</ui:SettingsCard>
</ui:SettingsExpander.Items>
</ui:SettingsExpander>
<!-- 底部空白 -->
<Rectangle Height="48" />
</ikw:SimpleStackPanel>
</Grid>
</ScrollViewer>
</Page>
@@ -0,0 +1,247 @@
using System;
using System.Windows;
using System.Windows.Controls;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
/// <summary>
/// StartupPage.xaml 的交互逻辑
/// </summary>
public partial class StartupPage : Page
{
private bool _isLoaded = false;
public StartupPage()
{
InitializeComponent();
Loaded += StartupPage_Loaded;
}
private void StartupPage_Loaded(object sender, RoutedEventArgs e)
{
LoadSettings();
_isLoaded = true;
}
/// <summary>
/// 加载设置到UI
/// </summary>
private void LoadSettings()
{
if (MainWindow.Settings == null) return;
_isLoaded = false;
try
{
// 窗口无焦点模式
if (MainWindow.Settings.Advanced != null)
{
ToggleSwitchNoFocusMode.IsOn = MainWindow.Settings.Advanced.IsNoFocusMode;
}
// 窗口无边框模式
if (MainWindow.Settings.Advanced != null)
{
ToggleSwitchWindowMode.IsOn = MainWindow.Settings.Advanced.WindowMode;
}
// 窗口置顶
if (MainWindow.Settings.Advanced != null)
{
ToggleSwitchAlwaysOnTop.IsOn = MainWindow.Settings.Advanced.IsAlwaysOnTop;
}
// UIA置顶
if (MainWindow.Settings.Advanced != null)
{
ToggleSwitchUIAccessTopMost.IsOn = MainWindow.Settings.Advanced.EnableUIAccessTopMost;
}
// 开机时运行
bool runAtStartup = System.IO.File.Exists(
System.Environment.GetFolderPath(System.Environment.SpecialFolder.Startup) + "\\Ink Canvas Annotation.lnk");
ToggleSwitchRunAtStartup.IsOn = runAtStartup;
// 启动时折叠
if (MainWindow.Settings.Startup != null)
{
ToggleSwitchFoldAtStartup.IsOn = MainWindow.Settings.Startup.IsFoldAtStartup;
}
// 仅PPT模式
if (MainWindow.Settings.ModeSettings != null)
{
ToggleSwitchPPTOnlyMode.IsOn = MainWindow.Settings.ModeSettings.IsPPTOnlyMode;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"加载启动设置时出错: {ex.Message}");
}
_isLoaded = true;
}
#region
/// <summary>
/// 窗口无焦点模式开关事件
/// </summary>
private void ToggleSwitchNoFocusMode_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
bool newState = ToggleSwitchNoFocusMode.IsOn;
// 使用Helper类更新设置并应用
Windows.SettingsViews.MainWindowSettingsHelper.InvokeToggleSwitchToggled("ToggleSwitchNoFocusMode", newState);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"设置窗口无焦点模式时出错: {ex.Message}");
}
}
/// <summary>
/// 窗口无边框模式开关事件
/// </summary>
private void ToggleSwitchWindowMode_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
bool newState = ToggleSwitchWindowMode.IsOn;
// 使用Helper类更新设置并应用
Windows.SettingsViews.MainWindowSettingsHelper.InvokeToggleSwitchToggled("ToggleSwitchWindowMode", newState);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"设置窗口无边框模式时出错: {ex.Message}");
}
}
/// <summary>
/// 窗口置顶开关事件
/// </summary>
private void ToggleSwitchAlwaysOnTop_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
bool newState = ToggleSwitchAlwaysOnTop.IsOn;
// 使用Helper类更新设置并应用
Windows.SettingsViews.MainWindowSettingsHelper.InvokeToggleSwitchToggled("ToggleSwitchAlwaysOnTop", newState);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"设置窗口置顶时出错: {ex.Message}");
}
}
/// <summary>
/// UIA置顶开关事件
/// </summary>
private void ToggleSwitchUIAccessTopMost_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
bool newState = ToggleSwitchUIAccessTopMost.IsOn;
// 更新Settings对象
if (MainWindow.Settings.Advanced != null)
{
MainWindow.Settings.Advanced.EnableUIAccessTopMost = newState;
}
// 保存设置
MainWindow.SaveSettingsToFile();
// 通知其他面板同步状态
Windows.SettingsViews.MainWindowSettingsHelper.NotifySettingsPanelsSyncState("ToggleSwitchUIAccessTopMost");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"设置UIA置顶时出错: {ex.Message}");
}
}
#endregion
#region
/// <summary>
/// 开机时运行开关事件
/// </summary>
private void ToggleSwitchRunAtStartup_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
bool newState = ToggleSwitchRunAtStartup.IsOn;
// 使用Helper类更新设置并应用
Windows.SettingsViews.MainWindowSettingsHelper.InvokeToggleSwitchToggled("ToggleSwitchRunAtStartup", newState);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"设置开机启动时出错: {ex.Message}");
}
}
/// <summary>
/// 开机运行后收纳到侧边栏开关事件
/// </summary>
private void ToggleSwitchFoldAtStartup_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
bool newState = ToggleSwitchFoldAtStartup.IsOn;
// 使用Helper类更新设置并应用
Windows.SettingsViews.MainWindowSettingsHelper.InvokeToggleSwitchToggled("ToggleSwitchFoldAtStartup", newState);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"设置开机折叠时出错: {ex.Message}");
}
}
#endregion
#region
/// <summary>
/// 仅PPT模式开关事件
/// </summary>
private void ToggleSwitchPPTOnlyMode_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
bool newState = ToggleSwitchPPTOnlyMode.IsOn;
// 使用Helper类更新设置并应用
Windows.SettingsViews.MainWindowSettingsHelper.InvokeToggleSwitchToggled("ToggleSwitchMode", newState);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"设置仅PPT模式时出错: {ex.Message}");
}
}
#endregion
}
}
@@ -0,0 +1,17 @@
<ui:Page
x:Class="Ink_Canvas.Windows.SettingsViews.Pages.ThemePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
Title="主题设置"
mc:Ignorable="d">
<Grid>
<StackPanel Margin="24">
<TextBlock Text="主题设置" Style="{DynamicResource TitleTextBlockStyle}" Margin="0,0,0,16" />
<TextBlock Text="这里是主题设置页面" Style="{DynamicResource BodyTextBlockStyle}" />
</StackPanel>
</Grid>
</ui:Page>
@@ -0,0 +1,12 @@
using iNKORE.UI.WPF.Modern.Controls;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class ThemePage : Page
{
public ThemePage()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,17 @@
<ui:Page
x:Class="Ink_Canvas.Windows.SettingsViews.Pages.TypographyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
Title="排版设置"
mc:Ignorable="d">
<Grid>
<StackPanel Margin="24">
<TextBlock Text="排版设置" Style="{DynamicResource TitleTextBlockStyle}" Margin="0,0,0,16" />
<TextBlock Text="这里是排版设置页面" Style="{DynamicResource BodyTextBlockStyle}" />
</StackPanel>
</Grid>
</ui:Page>
@@ -0,0 +1,12 @@
using iNKORE.UI.WPF.Modern.Controls;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class TypographyPage : Page
{
public TypographyPage()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,247 @@
<Window
x:Class="Ink_Canvas.Windows.SettingsViews.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
Title="InkCanvasForClass 设置"
Width="1138" Height="750"
MinWidth="270" MinHeight="220"
WindowStartupLocation="CenterScreen"
ui:ThemeManager.IsThemeAware="True"
ui:TitleBar.ExtendViewIntoTitleBar="True"
ui:WindowHelper.SystemBackdropType="Mica"
ui:WindowHelper.UseModernWindowStyle="True"
ui:TitleBar.Height="48"
mc:Ignorable="d">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemeResources CanBeAccessedAcrossThreads="True">
<ui:ThemeResources.ThemeDictionaries>
</ui:ThemeResources.ThemeDictionaries>
</ui:ThemeResources>
</ResourceDictionary.MergedDictionaries>
<!-- L-Pattern Overwriting resources -->
<Thickness x:Key="NavigationViewContentMargin">0,48,0,0</Thickness>
<Thickness x:Key="NavigationViewContentGridBorderThickness">1,1,0,0</Thickness>
<CornerRadius x:Key="NavigationViewContentGridCornerRadius">8,0,0,0</CornerRadius>
<Thickness x:Key="NavigationViewHeaderMargin">56,34,0,0</Thickness>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="13*"/>
<RowDefinition Height="134*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border
x:Name="AppTitleBar"
Grid.Column="1"
Height="{Binding ElementName=NavigationViewControl, Path=CompactPaneLength}"
VerticalAlignment="Top"
Background="Transparent"
IsHitTestVisible="True"
Canvas.ZIndex="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="137"/>
</Grid.ColumnDefinitions>
<ikw:SimpleStackPanel x:Name="AppTitle" Grid.Column="0" Orientation="Horizontal" Spacing="12" VerticalAlignment="Center">
<Image Source="\Resources\icc.ico" Width="20" RenderOptions.BitmapScalingMode="HighQuality"/>
<TextBlock x:Name="AppTitleText"
VerticalAlignment="Center"
Text="应用设置" TextWrapping="NoWrap"/>
</ikw:SimpleStackPanel>
</Grid>
</Border>
<ui:NavigationView
x:Name="NavigationViewControl"
Grid.Column="1"
AlwaysShowHeader="True"
Canvas.ZIndex="0"
Header=" "
IsFooterSeparatorVisible="True"
PaneTitle=""
IsTabStop="False"
IsTitleBarAutoPaddingEnabled="False"
PaneDisplayMode="Auto"
SelectionChanged="OnNavigationViewSelectionChanged"
BackRequested="OnNavigationViewBackRequested"
DisplayModeChanged="NavigationViewControl_DisplayModeChanged"
IsSettingsVisible="False"
IsBackButtonVisible="Visible"
IsBackEnabled="True"
OpenPaneLength="240"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" Grid.RowSpan="2">
<ui:NavigationView.HeaderTemplate>
<DataTemplate>
<Grid Margin="0,8,0,12">
<TextBlock
Text="{Binding}"
FontSize="20"
FontWeight="SemiBold"/>
</Grid>
</DataTemplate>
</ui:NavigationView.HeaderTemplate>
<ui:NavigationView.AutoSuggestBox>
<ui:AutoSuggestBox
x:Name="controlsSearchBox"
MinWidth="200"
VerticalAlignment="Center"
x:FieldModifier="public"
PlaceholderText="查找设置"
QuerySubmitted="OnControlsSearchBoxQuerySubmitted"
TextChanged="OnControlsSearchBoxTextChanged">
<ui:AutoSuggestBox.QueryIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Search}" FontSize="12"/>
</ui:AutoSuggestBox.QueryIcon>
</ui:AutoSuggestBox>
</ui:NavigationView.AutoSuggestBox>
<ui:NavigationView.MenuItems>
<ui:NavigationViewItem
x:Name="HomeItem"
Content="首页"
Tag="HomePage"
ToolTipService.ToolTip="首页">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Home}"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItemHeader Content="ICC CE 设置"/>
<!-- 基本设置 -->
<ui:NavigationViewItem
x:Name="BasicItem"
Content="基本"
Tag="BasicPage"
SelectsOnInvoked="True"
ToolTipService.ToolTip="基本设置">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Home}"/>
</ui:NavigationViewItem.Icon>
<ui:NavigationViewItem.MenuItems>
<ui:NavigationViewItem
x:Name="StartupPageItem"
Content="启动"
Tag="StartupPage"
ToolTipService.ToolTip="启动设置">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Play}"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationViewItem.MenuItems>
</ui:NavigationViewItem>
<!-- 页面2 -->
<ui:NavigationViewItem
x:Name="Page2Item"
Content="页面 2"
Tag="Page2Page">
<ui:NavigationViewItem.Icon>
<ui:SymbolIcon Symbol="Document" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<!-- 设计设置 -->
<ui:NavigationViewItem
x:Name="DesignItem"
Content="设计"
Tag="DesignPage"
SelectsOnInvoked="True">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Design}"/>
</ui:NavigationViewItem.Icon>
<ui:NavigationViewItem.MenuItems>
<ui:NavigationViewItem
x:Name="IconographyItem"
Content="图标"
Tag="IconographyPage"
ToolTipService.ToolTip="图标设置">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.AllApps}"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem
x:Name="TypographyItem"
Content="排版"
Tag="TypographyPage"
ToolTipService.ToolTip="排版设置">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Font}"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationViewItem.MenuItems>
</ui:NavigationViewItem>
<!-- 外观设置 -->
<ui:NavigationViewItem
x:Name="AppearanceItem"
Content="外观"
Tag="AppearancePage"
SelectsOnInvoked="True">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Color}"/>
</ui:NavigationViewItem.Icon>
<ui:NavigationViewItem.MenuItems>
<ui:NavigationViewItem
x:Name="ThemeItem"
Content="主题"
Tag="ThemePage"
ToolTipService.ToolTip="主题设置">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:FluentSystemIcons.DarkTheme_24_Regular}"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem
x:Name="ColorsItem"
Content="颜色"
Tag="ColorsPage"
ToolTipService.ToolTip="颜色设置">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Highlight}"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem
x:Name="FontsItem"
Content="字体"
Tag="FontsPage"
ToolTipService.ToolTip="字体设置">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Font}"/>
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationViewItem.MenuItems>
</ui:NavigationViewItem>
<ui:NavigationViewItemHeader Content="插件设置"/>
</ui:NavigationView.MenuItems>
<ui:NavigationView.FooterMenuItems>
<ui:NavigationViewItem
x:Name="AboutItem"
Content="关于 InkCanvasForClass"
Tag="AboutPage">
<ui:NavigationViewItem.Icon>
<ui:SymbolIcon Symbol="Help" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationView.FooterMenuItems>
<ui:Frame x:Name="rootFrame" Navigated="OnRootFrameNavigated" NavigationUIVisibility="Hidden" />
</ui:NavigationView>
</Grid>
</Window>
@@ -0,0 +1,464 @@
using Ink_Canvas.Windows.SettingsViews.Pages;
using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Interop;
using System.Windows.Input;
using System.Linq;
using MessageBox = System.Windows.MessageBox;
using Screen = System.Windows.Forms.Screen;
namespace Ink_Canvas.Windows.SettingsViews
{
public partial class SettingsWindow : Window
{
private readonly Dictionary<string, Type> _pageTypes;
private readonly Dictionary<string, object> _pages = new Dictionary<string, object>();
// 保存窗口原始位置和大小
private double _originalLeft;
private double _originalTop;
private double _originalWidth;
private double _originalHeight;
// 标记窗口是否曾经最大化过
private bool _wasMaximized = false;
public SettingsWindow()
{
InitializeComponent();
// 初始化内置页面映射
_pageTypes = new Dictionary<string, Type>
{
{ "HomePage", typeof(HomePage) },
{ "BasicPage", typeof(BasicPage) },
{ "Page2Page", typeof(Page2Page) },
{ "DesignPage", typeof(DesignPage) },
{ "AppearancePage", typeof(AppearancePage) },
{ "IconographyPage", typeof(IconographyPage) },
{ "TypographyPage", typeof(TypographyPage) },
{ "ThemePage", typeof(ThemePage) },
{ "ColorsPage", typeof(ColorsPage) },
{ "FontsPage", typeof(FontsPage) },
{ "StartupPage", typeof(StartupPage) },
{ "AboutPage", typeof(AboutPage) },
{ "Settings", typeof(SettingsPage) }
};
// 默认选中首页
if (NavigationViewControl.MenuItems.Count > 0)
{
// 首先导航到首页
NavigateToPage("HomePage");
// 然后选中首页菜单项
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems[0];
NavigationViewControl.Header = "首页";
}
// 初始化标题栏边距
UpdateAppTitleBarMargin();
// 窗口生命周期事件注册
this.Loaded += (sender, e) =>
{
SetMaxSizeAndCenter();
RegisterDpiChangedListener();
};
// 窗口关闭时释放资源
this.Closed += (sender, e) =>
{
UnregisterDpiChangedListener();
_pages.Clear();
_pageTypes.Clear();
};
// 修复触摸屏操作后鼠标指针消失的问题
FixTouchScreenCursorIssue();
// 窗口状态改变时调整大小限制
this.StateChanged += (sender, e) =>
{
if (this.WindowState == WindowState.Maximized)
{
// 保存窗口原始位置和大小
_originalLeft = this.Left;
_originalTop = this.Top;
_originalWidth = this.Width;
_originalHeight = this.Height;
// 标记窗口曾经最大化过
_wasMaximized = true;
// 最大化时清除最大尺寸限制
this.MaxWidth = double.PositiveInfinity;
this.MaxHeight = double.PositiveInfinity;
}
else if (this.WindowState == WindowState.Normal && _wasMaximized)
{
// 从最大化恢复到正常状态时,恢复窗口原始位置和大小
this.Left = _originalLeft;
this.Top = _originalTop;
this.Width = _originalWidth;
this.Height = _originalHeight;
// 重置标记
_wasMaximized = false;
// 只设置最大尺寸,不改变窗口位置
SetMaxSizeOnly();
}
else if (this.WindowState == WindowState.Normal)
{
// 正常状态下只设置最大尺寸限制
SetMaxSizeOnly();
}
// 窗口状态改变时更新标题栏显示
UpdateAppTitleBarMargin();
};
// 窗口大小改变时更新标题栏显示
this.SizeChanged += (sender, e) =>
{
if (NavigationViewControl.DisplayMode == NavigationViewDisplayMode.Minimal)
{
UpdateAppTitleBarMargin();
}
};
}
#region
private void FixTouchScreenCursorIssue()
{
// 触摸结束时强制显示鼠标指针
this.TouchUp += (s, e) =>
{
ShowCursor(true);
};
// 鼠标进入窗口时确保指针可见
this.MouseEnter += (s, e) =>
{
ShowCursor(true);
};
// 窗口激活时确保指针可见
this.Activated += (s, e) =>
{
ShowCursor(true);
};
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int ShowCursor(bool bShow);
#endregion
#region DPI/
/// <summary>
/// 获取当前窗口所在屏幕的工作区尺寸(DIP单位)
/// </summary>
private void GetWorkAreaSize(out double workAreaWidthDip, out double workAreaHeightDip, out double screenLeftDip, out double screenTopDip)
{
// 1. 获取窗口当前所在屏幕
var windowHandle = new WindowInteropHelper(this).Handle;
var currentScreen = Screen.FromHandle(windowHandle);
var workingArea = currentScreen.WorkingArea;
var screenBounds = currentScreen.Bounds;
// 2. 获取当前窗口的DPI缩放因子
var source = PresentationSource.FromVisual(this);
double dpiScaleX = 1.0;
double dpiScaleY = 1.0;
if (source?.CompositionTarget != null)
{
dpiScaleX = source.CompositionTarget.TransformToDevice.M11;
dpiScaleY = source.CompositionTarget.TransformToDevice.M22;
}
// 3. 物理像素 → WPF设备无关像素(DIP)转换
workAreaWidthDip = workingArea.Width / dpiScaleX;
workAreaHeightDip = workingArea.Height / dpiScaleY;
screenLeftDip = screenBounds.Left / dpiScaleX;
screenTopDip = screenBounds.Top / dpiScaleY;
}
private void SetMaxSizeAndCenter()
{
if (!this.IsLoaded) return;
GetWorkAreaSize(out double workAreaWidthDip, out double workAreaHeightDip, out double screenLeftDip, out double screenTopDip);
// 设置窗口最大尺寸
this.MaxWidth = workAreaWidthDip;
this.MaxHeight = workAreaHeightDip;
// 窗口在当前屏幕居中(解决副屏居中跑偏问题)
this.Left = screenLeftDip + (workAreaWidthDip - this.ActualWidth) / 2;
this.Top = screenTopDip + (workAreaHeightDip - this.ActualHeight) / 2;
}
private void SetMaxSizeOnly()
{
if (!this.IsLoaded) return;
GetWorkAreaSize(out double workAreaWidthDip, out double workAreaHeightDip, out _, out _);
// 只设置窗口最大尺寸,不改变窗口位置
this.MaxWidth = workAreaWidthDip;
this.MaxHeight = workAreaHeightDip;
}
#region DPI/
private HwndSource _hwndSource;
private void RegisterDpiChangedListener()
{
_hwndSource = PresentationSource.FromVisual(this) as HwndSource;
_hwndSource?.AddHook(DpiChangedWndProc);
}
private void UnregisterDpiChangedListener()
{
_hwndSource?.RemoveHook(DpiChangedWndProc);
_hwndSource = null;
}
private IntPtr DpiChangedWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
const int WM_DPICHANGED = 0x02E0;
// 系统DPI/缩放变化时自动重新计算窗口参数
if (msg == WM_DPICHANGED)
{
SetMaxSizeAndCenter();
handled = true;
}
return IntPtr.Zero;
}
#endregion
#endregion
#region
private void OnNavigationViewSelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
{
// 处理自带的设置项导航
if (args.IsSettingsSelected)
{
NavigateToPage("Settings");
NavigationViewControl.Header = "设置";
return;
}
// 处理普通导航项
if (args.SelectedItem is NavigationViewItem selectedItem)
{
string tag = selectedItem.Tag as string;
if (!string.IsNullOrEmpty(tag) && _pageTypes.ContainsKey(tag))
{
// 避免重复导航到当前页面
if (rootFrame.SourcePageType != _pageTypes[tag])
{
NavigateToPage(tag);
}
NavigationViewControl.Header = selectedItem.Content;
}
}
}
public void NavigateToPage(string pageTag)
{
if (!_pageTypes.TryGetValue(pageTag, out Type pageType)) return;
try
{
// 页面缓存:已创建的页面直接复用,保留状态,避免重复初始化
if (!_pages.TryGetValue(pageTag, out var cachedPage))
{
cachedPage = Activator.CreateInstance(pageType);
_pages.Add(pageTag, cachedPage);
}
// 导航到缓存页面
rootFrame.Navigate(cachedPage.GetType(), cachedPage);
}
catch (Exception ex)
{
MessageBox.Show($"导航到页面时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void OnNavigationViewBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
{
if (rootFrame.CanGoBack) rootFrame.GoBack();
}
private void OnRootFrameNavigated(object sender, NavigationEventArgs e)
{
// 导航后同步导航项选中状态
Type currentPageType = rootFrame.SourcePageType;
// 处理设置项的选中状态
if (currentPageType == typeof(SettingsPage))
{
NavigationViewControl.SelectedItem = NavigationViewControl.SettingsItem;
NavigationViewControl.Header = "设置";
return;
}
// 同步其他页面的选中状态
foreach (var kvp in _pageTypes)
{
if (kvp.Value == currentPageType)
{
var targetItem = FindNavigationViewItemByTag(kvp.Key);
if (targetItem != null && NavigationViewControl.SelectedItem != targetItem)
{
NavigationViewControl.SelectedItem = targetItem;
NavigationViewControl.Header = targetItem.Content;
}
break;
}
}
}
private void NavigationViewControl_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args)
{
UpdateAppTitleBarMargin(sender);
}
private void UpdateAppTitleBarMargin()
{
UpdateAppTitleBarMargin(NavigationViewControl);
}
private void UpdateAppTitleBarMargin(NavigationView sender)
{
Thickness currMargin = AppTitleBar.Margin;
if (sender.DisplayMode == NavigationViewDisplayMode.Minimal)
{
AppTitleBar.Margin = new Thickness((sender.CompactPaneLength * 2), currMargin.Top, currMargin.Right, currMargin.Bottom);
// 当窗口宽度非常小时,隐藏图标和应用设置文字
if (this.ActualWidth < 400)
{
AppTitle.Visibility = Visibility.Collapsed;
}
else
{
AppTitle.Visibility = Visibility.Visible;
}
}
else
{
AppTitleBar.Margin = new Thickness(sender.CompactPaneLength, currMargin.Top, currMargin.Right, currMargin.Bottom);
AppTitle.Visibility = Visibility.Visible;
}
AppTitleBar.Visibility = sender.PaneDisplayMode == NavigationViewPaneDisplayMode.Top ? Visibility.Collapsed : Visibility.Visible;
}
private NavigationViewItem FindNavigationViewItemByTag(string tag)
{
// 遍历主菜单
foreach (var item in NavigationViewControl.MenuItems)
{
if (item is NavigationViewItem navItem)
{
if (navItem.Tag as string == tag)
return navItem;
// 遍历子菜单,自动展开父项
foreach (var childItem in navItem.MenuItems)
{
if (childItem is NavigationViewItem childNavItem && childNavItem.Tag as string == tag)
{
navItem.IsExpanded = true;
return childNavItem;
}
}
}
}
// 遍历底部菜单
foreach (var item in NavigationViewControl.FooterMenuItems)
{
if (item is NavigationViewItem navItem && navItem.Tag as string == tag)
{
return navItem;
}
}
return null;
}
#endregion
#region
private void OnControlsSearchBoxQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
if (string.IsNullOrWhiteSpace(args.QueryText)) return;
string query = args.QueryText.Trim().ToLower();
var allNavItems = GetAllNavigationItems();
var targetItem = allNavItems.FirstOrDefault(item =>
item.Content?.ToString().ToLower().Contains(query) == true);
if (targetItem != null)
{
NavigationViewControl.SelectedItem = targetItem;
}
}
private void OnControlsSearchBoxTextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
if (args.Reason != AutoSuggestionBoxTextChangeReason.UserInput) return;
string query = sender.Text.Trim().ToLower();
var suggestions = new List<string>();
if (!string.IsNullOrEmpty(query))
{
var allNavItems = GetAllNavigationItems();
suggestions = allNavItems
.Where(item => item.Content?.ToString().ToLower().Contains(query) == true)
.Select(item => item.Content.ToString())
.ToList();
}
sender.ItemsSource = suggestions;
}
// 统一获取所有导航项(主菜单+子菜单+底部菜单)
private List<NavigationViewItem> GetAllNavigationItems()
{
var items = new List<NavigationViewItem>();
// 主菜单+子菜单
foreach (var item in NavigationViewControl.MenuItems)
{
if (item is NavigationViewItem navItem)
{
items.Add(navItem);
foreach (var child in navItem.MenuItems)
{
if (child is NavigationViewItem childNavItem)
items.Add(childNavItem);
}
}
}
// 底部菜单
foreach (var item in NavigationViewControl.FooterMenuItems)
{
if (item is NavigationViewItem navItem)
items.Add(navItem);
}
return items;
}
#endregion
}
}