using H.NotifyIcon; using Ink_Canvas.Helpers; using Ink_Canvas.Windows.SettingsViews.Helpers; using Newtonsoft.Json; using OSVersionExtension; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Http; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Forms; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; using Application = System.Windows.Application; using CheckBox = System.Windows.Controls.CheckBox; using ComboBox = System.Windows.Controls.ComboBox; using File = System.IO.File; using MessageBox = iNKORE.UI.WPF.Modern.Controls.MessageBox; using ToggleSwitch = iNKORE.UI.WPF.Modern.Controls.ToggleSwitch; using OpenFileDialog = Microsoft.Win32.OpenFileDialog; using OperatingSystem = OSVersionExtension.OperatingSystem; using RadioButton = System.Windows.Controls.RadioButton; namespace Ink_Canvas { public partial class MainWindow : Window { #region Behavior /// /// 内部标记:是否正在内部更改更新通道 /// private bool _isChangingUpdateChannelInternally; /// 内部标记:是否正在内部更改「更新包架构」(32/64 位 ZIP) private bool _isChangingUpdatePackageArchInternally; /// /// 处理PowerPoint支持开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当PowerPoint支持开关状态更改时: /// 1. 保存PowerPoint支持设置 /// 2. 如果关闭PowerPoint支持,同时也关闭WPS支持 /// 3. 如果开启PowerPoint支持,初始化PPT管理器并开始监控 /// 4. 如果关闭PowerPoint支持,停止监控 /// private void ToggleSwitchSupportPowerPoint_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; if (!Settings.PowerPointSettings.PowerPointSupport) { if (Settings.PowerPointSettings.IsSupportWPS) { Settings.PowerPointSettings.IsSupportWPS = false; if (_pptManager != null) { _pptManager.IsSupportWPS = false; } } } SaveSettingsToFile(); // 使用新的PPT管理器 if (Settings.PowerPointSettings.PowerPointSupport) { if (_pptManager == null) { InitializePPTManagers(); } StartPPTMonitoring(); } else { StopPPTMonitoring(); } } /// /// 处理使用ROT PPT链接开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当使用ROT PPT链接开关状态更改时: /// 1. 保存ROT PPT链接设置 /// 2. 停止PPT监控 /// 3. 如果开启ROT PPT链接且启用了PowerPoint增强,关闭PowerPoint增强 /// 4. 初始化PPT管理器 /// 5. 如果启用了PowerPoint支持,开始PPT监控 /// 6. 记录切换PPT联动架构的日志 /// private void ToggleSwitchUseRotPptLink_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); try { StopPPTMonitoring(); if (Settings.PowerPointSettings.UseRotPptLink && Settings.PowerPointSettings.EnablePowerPointEnhancement) { Settings.PowerPointSettings.EnablePowerPointEnhancement = false; { } StopPowerPointProcessMonitoring(); SaveSettingsToFile(); } InitializePPTManagers(); if (Settings.PowerPointSettings.PowerPointSupport) { StartPPTMonitoring(); } LogHelper.WriteLogToFile( $"已切换 PPT 联动架构为 {(Settings.PowerPointSettings.UseRotPptLink ? "ROT" : "COM")}", LogHelper.LogType.Event); } catch (Exception ex) { LogHelper.WriteLogToFile($"切换 PPT 联动架构失败: {ex}", LogHelper.LogType.Error); } } /// /// 处理新幻灯片放映时显示画布开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当新幻灯片放映时显示画布开关状态更改时,保存设置到文件 /// private void ToggleSwitchShowCanvasAtNewSlideShow_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } #endregion #region Startup /// /// 处理笔尖模式开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当笔尖模式开关状态更改时: /// 1. 同步更新两个笔尖模式开关的状态 /// 2. 保存笔尖模式设置 /// 3. 根据笔尖模式设置更新边界宽度 /// private void ToggleSwitchEnableNibMode_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; if (sender == ToggleSwitchEnableNibMode) BoardToggleSwitchEnableNibMode.IsOn = ToggleSwitchEnableNibMode.IsOn; ToggleSwitchEnableNibMode.IsOn = BoardToggleSwitchEnableNibMode.IsOn; Settings.Startup.IsEnableNibMode = ToggleSwitchEnableNibMode.IsOn; if (Settings.Startup.IsEnableNibMode) BoundsWidth = Settings.Advanced.NibModeBoundsWidth; BoundsWidth = Settings.Advanced.FingerModeBoundsWidth; SaveSettingsToFile(); } #endregion #region Appearance /// /// 处理显示笔尖模式切换开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当显示笔尖模式切换开关状态更改时: /// 1. 保存显示笔尖模式切换设置 /// 2. 根据设置显示或隐藏笔尖模式切换面板 /// private void ToggleSwitchEnableDisPlayNibModeToggle_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } //private void ToggleSwitchIsColorfulViewboxFloatingBar_Toggled(object sender, RoutedEventArgs e) { // if (!isLoaded) return; // Settings.Appearance.IsColorfulViewboxFloatingBar = ToggleSwitchColorfulViewboxFloatingBar.IsOn; // SaveSettingsToFile(); //} /// /// 处理快速面板开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当快速面板开关状态更改时,保存设置到文件 /// private void ToggleSwitchEnableQuickPanel_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } /// /// 处理启动屏幕开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当启动屏幕开关状态更改时,保存设置到文件 /// private void ToggleSwitchEnableSplashScreen_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } /// /// 处理启动屏幕样式选择更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当选择启动屏幕样式时,保存设置到文件 /// private void ComboBoxSplashScreenStyle_SelectionChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } /// /// 处理浮动栏缩放值滑块值更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当浮动栏缩放值滑块值更改时: /// 1. 保存浮动栏缩放设置 /// 2. 应用缩放值到浮动栏(限制在0.5-1.25范围内) /// 3. 等待UI更新后重新计算浮动栏位置,确保居中计算准确 /// 4. 只在屏幕模式下重新计算浮动栏位置 /// private void ViewboxFloatingBarScaleTransformValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { double val = Settings.Appearance.ViewboxFloatingBarScaleTransformValue; ViewboxFloatingBarScaleTransform.ScaleX = val > 0.5 && val < 1.25 ? val : val <= 0.5 ? 0.5 : val >= 1.25 ? 1.25 : 1; ViewboxFloatingBarScaleTransform.ScaleY = ViewboxFloatingBarScaleTransform.ScaleX; SaveSettingsToFile(); } catch { } } /// /// 处理浮动栏透明度值滑块值更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当浮动栏透明度值滑块值更改时: /// 1. 保存浮动栏透明度设置 /// 2. 应用透明度值到浮动栏 /// private void ViewboxFloatingBarOpacityValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { ViewboxFloatingBar.Opacity = Settings.Appearance.ViewboxFloatingBarOpacityValue; SaveSettingsToFile(); } catch { } } /// /// 处理PPT中浮动栏透明度值滑块值更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当PPT中浮动栏透明度值滑块值更改时,保存设置到文件 /// private void ViewboxFloatingBarOpacityInPPTValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { SaveSettingsToFile(); } catch { } } /// /// 处理托盘图标开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当托盘图标开关状态更改时: /// 1. 保存托盘图标设置 /// 2. 根据设置显示或隐藏托盘图标示例图像 /// 3. 根据设置显示或隐藏系统托盘图标 /// private void ToggleSwitchEnableTrayIcon_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; var _taskbar = (TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"]; SaveSettingsToFile(); } /// /// 处理展开按钮图像选择更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当选择展开按钮图像类型时: /// 1. 保存展开按钮图像类型设置 /// 2. 根据选择的图像类型更新左右展开按钮的图标 /// 3. 为不同的图像类型设置不同的大小和旋转角度 /// private void ComboBoxUnFoldBtnImg_SelectionChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); { RightUnFoldBtnImgChevron.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/unfold-chevron.png")); RightUnFoldBtnImgChevron.Width = 14; RightUnFoldBtnImgChevron.Height = 14; RightUnFoldBtnImgChevron.RenderTransform = new RotateTransform(180); LeftUnFoldBtnImgChevron.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/unfold-chevron.png")); LeftUnFoldBtnImgChevron.Width = 14; LeftUnFoldBtnImgChevron.Height = 14; LeftUnFoldBtnImgChevron.RenderTransform = null; } { RightUnFoldBtnImgChevron.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/pen-white.png")); RightUnFoldBtnImgChevron.Width = 18; RightUnFoldBtnImgChevron.Height = 18; RightUnFoldBtnImgChevron.RenderTransform = null; LeftUnFoldBtnImgChevron.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/pen-white.png")); LeftUnFoldBtnImgChevron.Width = 18; LeftUnFoldBtnImgChevron.Height = 18; LeftUnFoldBtnImgChevron.RenderTransform = null; } } private static readonly Lazy HitokotoHttpClient = new Lazy(CreateHitokotoClient, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication); /// /// 创建用于获取一言(Hitokoto)数据的HttpClient /// /// 创建的HttpClient实例,如果创建失败则返回null /// /// 创建HttpClient时: /// 1. 设置超时时间为5秒 /// 2. 尝试设置User-Agent头 /// 3. 捕获并记录创建过程中的异常 /// private static object CreateHitokotoClient() { try { var client = new HttpClient { Timeout = TimeSpan.FromSeconds(5) }; try { client.DefaultRequestHeaders.UserAgent.ParseAdd("InkCanvas-Hitokoto/1.0"); } catch { } return client; } catch (Exception ex) { try { LogHelper.WriteLogToFile($"无法创建 HttpClient (System.Net.Http 可能缺失): {ex.Message}", LogHelper.LogType.Warning); } catch { } return null; } } /// /// 根据当前外观设置更新白板水印的名言文本。 /// /// /// 当配置为内置来源时(0:OSUPlayer、1:名言警句、2:高考俗语)从对应数组中随机选择一条并设置为水印文本; /// 当配置为一言(3)时会异步请求 Hitokoto API 并在请求中显示占位提示,成功时将返回文本设为水印,失败时记录警告日志并设置可读的失败提示文本。此方法会修改 BlackBoardWaterMark.Text,并在发生异常时记录日志且设置合适的回退文本。 /// private async Task UpdateChickenSoupTextAsync() { try { if (!Settings.Appearance.EnableChickenSoupInWhiteboardMode) { return; } if (Settings.Appearance.ChickenSoupSource == 0) { int randChickenSoupIndex = new Random().Next(ChickenSoup.OSUPlayerYuLu.Length); BlackBoardWaterMark.Text = ChickenSoup.OSUPlayerYuLu[randChickenSoupIndex]; } else if (Settings.Appearance.ChickenSoupSource == 1) { int randChickenSoupIndex = new Random().Next(ChickenSoup.MingYanJingJu.Length); BlackBoardWaterMark.Text = ChickenSoup.MingYanJingJu[randChickenSoupIndex]; } else if (Settings.Appearance.ChickenSoupSource == 2) { int randChickenSoupIndex = new Random().Next(ChickenSoup.GaoKaoPhrases.Length); BlackBoardWaterMark.Text = ChickenSoup.GaoKaoPhrases[randChickenSoupIndex]; } else if (Settings.Appearance.ChickenSoupSource == 3) { BlackBoardWaterMark.Text = "正在获取一言..."; try { object clientObj = null; try { clientObj = HitokotoHttpClient.Value; } catch (Exception initEx) { LogHelper.WriteLogToFile($"一言 HTTP 客户端初始化失败: {initEx.Message}", LogHelper.LogType.Warning); BlackBoardWaterMark.Text = "一言功能不可用(HTTP 库不可用)"; return; } if (clientObj == null || !(clientObj is HttpClient client)) { BlackBoardWaterMark.Text = "一言功能不可用(HTTP 库不可用)"; return; } var cats = Settings.Appearance.HitokotoCategories; if (cats == null || cats.Count == 0) cats = new List { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l" }; var urlBuilder = new StringBuilder("https://v1.hitokoto.cn/?encode=text"); foreach (var category in cats) { urlBuilder.Append($"&c={category}"); } var response = await client.GetAsync(urlBuilder.ToString()).ConfigureAwait(true); response.EnsureSuccessStatusCode(); var text = await response.Content.ReadAsStringAsync().ConfigureAwait(true); if (!string.IsNullOrWhiteSpace(text)) { BlackBoardWaterMark.Text = text.Trim(); } else { BlackBoardWaterMark.Text = "一言暂时没有返回内容"; } } catch (Exception ex) { LogHelper.WriteLogToFile($"一言 API 请求失败: {ex.Message}", LogHelper.LogType.Warning); BlackBoardWaterMark.Text = "一言功能不可用"; } } } catch (Exception ex) { LogHelper.WriteLogToFile($"更新白板名言时出错: {ex.Message}", LogHelper.LogType.Warning); if (Settings.Appearance.ChickenSoupSource == 3 && BlackBoardWaterMark != null) { try { BlackBoardWaterMark.Text = "一言功能不可用"; } catch (Exception innerEx) { System.Diagnostics.Debug.WriteLine(innerEx); } } } } /// /// 处理名言来源选择更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当选择名言来源时: /// 1. 保存名言来源设置 /// 2. 异步更新白板水印的名言文本 /// private async void ComboBoxChickenSoupSource_SelectionChanged(object sender, RoutedEventArgs e) { if (_suppressChickenSoupSourceSelectionChanged) return; if (!isLoaded) return; var idx = (sender as System.Windows.Controls.ComboBox)?.SelectedIndex ?? -1; if (idx < 0) return; if (Settings.Appearance.ChickenSoupSource == idx) return; Settings.Appearance.ChickenSoupSource = idx; SaveSettingsToFile(); await UpdateChickenSoupTextAsync(); } private async void BtnHitokotoCustomize_Click(object sender, RoutedEventArgs e) { var categories = new Dictionary { { "a", "动画" }, { "b", "漫画" }, { "c", "游戏" }, { "d", "文学" }, { "e", "原创" }, { "f", "来自网络" }, { "g", "其他" }, { "h", "影视" }, { "i", "诗词" }, { "j", "网易云" }, { "k", "哲学" }, { "l", "抖机灵" } }; // 创建弹窗内容 var contentPanel = new StackPanel { Margin = new Thickness(20), Orientation = System.Windows.Controls.Orientation.Vertical }; // 全选复选框 var selectAllCheckBox = new CheckBox { Content = "全选", FontSize = 14, FontFamily = new FontFamily("Microsoft YaHei UI"), Margin = new Thickness(0, 0, 0, 8) }; // 存储各个分类的复选框 var categoryCheckBoxes = new Dictionary(); var savedHitokoto = Settings.Appearance.HitokotoCategories; bool implicitAllCategories = savedHitokoto == null || savedHitokoto.Count == 0; // 创建分类复选框 foreach (var category in categories) { var checkBox = new CheckBox { Content = category.Value, Tag = category.Key, FontSize = 13, FontFamily = new FontFamily("Microsoft YaHei UI"), IsChecked = implicitAllCategories || savedHitokoto.Contains(category.Key), Margin = new Thickness(0, 0, 0, 8) }; categoryCheckBoxes[category.Key] = checkBox; contentPanel.Children.Add(checkBox); } // 全选复选框逻辑 bool isUpdatingSelectAll = false; selectAllCheckBox.IsChecked = implicitAllCategories || savedHitokoto.Count == categories.Count; selectAllCheckBox.Checked += (s, args) => { if (isUpdatingSelectAll) return; isUpdatingSelectAll = true; foreach (var checkBox in categoryCheckBoxes.Values) { checkBox.IsChecked = true; } isUpdatingSelectAll = false; }; selectAllCheckBox.Unchecked += (s, args) => { if (isUpdatingSelectAll) return; isUpdatingSelectAll = true; foreach (var checkBox in categoryCheckBoxes.Values) { checkBox.IsChecked = false; } isUpdatingSelectAll = false; }; // 监听各个复选框的变化,更新全选状态 foreach (var checkBox in categoryCheckBoxes.Values) { checkBox.Checked += (s, args) => { if (isUpdatingSelectAll) return; isUpdatingSelectAll = true; // 检查所有分类复选框是否都被勾选 bool allChecked = categoryCheckBoxes.Values.All(cb => cb.IsChecked == true); selectAllCheckBox.IsChecked = allChecked; isUpdatingSelectAll = false; }; checkBox.Unchecked += (s, args) => { if (isUpdatingSelectAll) return; isUpdatingSelectAll = true; selectAllCheckBox.IsChecked = false; isUpdatingSelectAll = false; }; } // 将全选复选框添加到顶部 var mainPanel = new StackPanel { Margin = new Thickness(0), Orientation = System.Windows.Controls.Orientation.Vertical }; mainPanel.Children.Add(selectAllCheckBox); mainPanel.Children.Add(new Separator { Margin = new Thickness(0, 8, 0, 8) }); mainPanel.Children.Add(contentPanel); var scrollViewer = new ScrollViewer { Content = mainPanel, MaxHeight = 400, VerticalScrollBarVisibility = ScrollBarVisibility.Auto }; // 创建ContentDialog显示自定义内容 var contentDialog = new iNKORE.UI.WPF.Modern.Controls.ContentDialog { Title = "自定义一言分类", Content = scrollViewer, PrimaryButtonText = "确定", SecondaryButtonText = "取消", DefaultButton = iNKORE.UI.WPF.Modern.Controls.ContentDialogButton.Primary, Owner = this }; var dialogResult = await contentDialog.ShowAsync(); if (dialogResult == iNKORE.UI.WPF.Modern.Controls.ContentDialogResult.Primary) { // 保存选中的分类 Settings.Appearance.HitokotoCategories = categoryCheckBoxes .Where(kvp => kvp.Value.IsChecked == true) .Select(kvp => kvp.Key) .ToList(); // 如果没有任何选中,默认全选 if (Settings.Appearance.HitokotoCategories.Count == 0) { Settings.Appearance.HitokotoCategories = categories.Keys.ToList(); } SaveSettingsToFile(); // 如果当前正在使用API,更新名言 if (Settings.Appearance.ChickenSoupSource == 3 && Settings.Appearance.EnableChickenSoupInWhiteboardMode) { _ = UpdateChickenSoupTextAsync(); } } } private void ToggleSwitchEnableViewboxBlackBoardScaleTransform_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.Appearance.EnableViewboxBlackBoardScaleTransform = (sender as ToggleSwitch)?.IsOn ?? false; SaveSettingsToFile(); LoadSettings(); } /// /// 处理浮动栏图标选择更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当选择浮动栏图标时: /// 1. 保存浮动栏图标设置 /// 2. 更新浮动栏图标 /// 3. 保存设置到文件 /// public void ComboBoxFloatingBarImg_SelectionChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarIcon(); SaveSettingsToFile(); } /// /// 根据设置更新浮动栏图标 /// /// /// 根据设置的浮动栏图标索引更新图标: /// 1. 为不同的图标索引设置不同的图标源 /// 2. 为不同的图标设置不同的边距 /// 3. 支持自定义图标 /// 4. 自定义图标加载失败时使用默认图标 /// public void UpdateFloatingBarIcon() { int index = Settings.Appearance.FloatingBarImg; if (index == 0) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc.png")); FloatingbarHeadIconImg.Margin = new Thickness(0.5); } else if (index == 1) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc-noshadow.png")); FloatingbarHeadIconImg.Margin = new Thickness(0.5); } else if (index == 2) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc-dark.png")); FloatingbarHeadIconImg.Margin = new Thickness(0.5); } else if (index == 3) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc-sharpdark.png")); FloatingbarHeadIconImg.Margin = new Thickness(0.5); } else if (index == 4) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc-transparent-light-small.png")); FloatingbarHeadIconImg.Margin = new Thickness(0.5); } else if (index == 5) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc-transparent-dark-small.png")); FloatingbarHeadIconImg.Margin = new Thickness(1.2); } else if (index == 6) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuandoujiyanhuaji.png")); FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5); } else if (index == 7) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanshounvhuaji.png")); FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5); } else if (index == 8) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanciya.png")); FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5); } else if (index == 9) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanneikuhuaji.png")); FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5); } else if (index == 10) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuandogeyuanliangwo.png")); FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5); } else if (index == 11) { FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/tiebahuaji.png")); FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1); } else if (index >= 12 && index - 12 < Settings.Appearance.CustomFloatingBarImgs.Count) { // 使用自定义图标 var customIcon = Settings.Appearance.CustomFloatingBarImgs[index - 12]; try { var dpi = VisualTreeHelper.GetDpi(this); var targetPixels = (int)Math.Round(58 * dpi.DpiScaleX); var decodePixels = targetPixels * 2; if (decodePixels < 64) decodePixels = 64; if (decodePixels > 512) decodePixels = 512; FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri(customIcon.FilePath), decodePixels); FloatingbarHeadIconImg.Margin = new Thickness(2); } catch { // 如果加载失败,使用默认图标 FloatingbarHeadIconImg.Source = CreateBitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc.png")); FloatingbarHeadIconImg.Margin = new Thickness(0.5); } } } private static BitmapImage CreateBitmapImage(Uri uri, int decodePixelWidth = 0) { var image = new BitmapImage(); image.BeginInit(); image.UriSource = uri; image.CacheOption = BitmapCacheOption.OnLoad; if (decodePixelWidth > 0) { image.DecodePixelWidth = decodePixelWidth; } image.EndInit(); image.Freeze(); return image; } /// /// 更新组合框中的自定义图标选项 /// /// /// 更新自定义图标选项时: /// 1. 保留前12个内置图标选项 /// 2. 移除所有现有的自定义图标选项 /// 3. 添加新的自定义图标选项 /// 4. 为自定义图标选项设置字体 /// public void UpdateCustomIconsInComboBox() { // 保留前12个内置图标选项 { } // 添加自定义图标选项 foreach (var customIcon in Settings.Appearance.CustomFloatingBarImgs) { ComboBoxItem item = new ComboBoxItem(); item.Content = customIcon.Name; item.FontFamily = new FontFamily("Microsoft YaHei UI"); } } /// /// 处理添加自定义图标按钮点击事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当点击添加自定义图标按钮时: /// 1. 显示添加自定义图标窗口 /// 2. 如果添加成功,自动选中新添加的图标 /// private void ButtonAddCustomIcon_Click(object sender, RoutedEventArgs e) { AddCustomIconWindow dialog = new AddCustomIconWindow(this); dialog.Owner = this; dialog.ShowDialog(); if (dialog.IsSuccess) { // 自动选中新添加的图标 } } /// /// 处理管理自定义图标按钮点击事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当点击管理自定义图标按钮时,显示自定义图标管理窗口 /// private void ButtonManageCustomIcons_Click(object sender, RoutedEventArgs e) { CustomIconWindow dialog = new CustomIconWindow(this); dialog.Owner = this; dialog.ShowDialog(); } /// /// 处理白板模式下时间显示开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当白板模式下时间显示开关状态更改时: /// 1. 保存时间显示设置 /// 2. 如果当前是白板模式,根据设置显示或隐藏时间和日期水印 /// 3. 保存设置到文件 /// 4. 重新加载设置以应用更改 /// private void ToggleSwitchEnableTimeDisplayInWhiteboardMode_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; if (currentMode == 1) { if (Settings.Appearance.EnableTimeDisplayInWhiteboardMode) { WaterMarkTime.Visibility = Visibility.Visible; WaterMarkDate.Visibility = Visibility.Visible; } else { WaterMarkTime.Visibility = Visibility.Collapsed; WaterMarkDate.Visibility = Visibility.Collapsed; } } SaveSettingsToFile(); LoadSettings(); } /// /// 处理白板模式下名言显示开关状态更改事件 /// /// 事件发送者 /// 路由事件参数 /// /// 当白板模式下名言显示开关状态更改时: /// 1. 保存名言显示设置 /// 2. 如果当前是白板模式,根据时间显示设置显示或隐藏名言水印 /// 3. 保存设置到文件 /// 4. 重新加载设置以应用更改 /// private void ToggleSwitchEnableChickenSoupInWhiteboardMode_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; if (currentMode == 1) { if (Settings.Appearance.EnableChickenSoupInWhiteboardMode) { BlackBoardWaterMark.Visibility = Visibility.Visible; } else { BlackBoardWaterMark.Visibility = Visibility.Collapsed; } } SaveSettingsToFile(); LoadSettings(); } //[Obsolete] //private void ToggleSwitchShowButtonPPTNavigation_OnToggled(object sender, RoutedEventArgs e) { // if (!isLoaded) return; // Settings.PowerPointSettings.IsShowPPTNavigation = ToggleSwitchShowButtonPPTNavigation.IsOn; // var vis = Settings.PowerPointSettings.IsShowPPTNavigation ? Visibility.Visible : Visibility.Collapsed; // PPTLBPageButton.Visibility = vis; // PPTRBPageButton.Visibility = vis; // PPTLSPageButton.Visibility = vis; // PPTRSPageButton.Visibility = vis; // SaveSettingsToFile(); //} //[Obsolete] //private void ToggleSwitchShowBottomPPTNavigationPanel_OnToggled(object sender, RoutedEventArgs e) { // if (!isLoaded) return; // Settings.PowerPointSettings.IsShowBottomPPTNavigationPanel = ToggleSwitchShowBottomPPTNavigationPanel.IsOn; // if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) // //BottomViewboxPPTSidesControl.Visibility = Settings.PowerPointSettings.IsShowBottomPPTNavigationPanel // // ? Visibility.Visible // // : Visibility.Collapsed; // SaveSettingsToFile(); //} //[Obsolete] //private void ToggleSwitchShowSidePPTNavigationPanel_OnToggled(object sender, RoutedEventArgs e) { // if (!isLoaded) return; // Settings.PowerPointSettings.IsShowSidePPTNavigationPanel = ToggleSwitchShowSidePPTNavigationPanel.IsOn; // if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { // LeftSidePanelForPPTNavigation.Visibility = Settings.PowerPointSettings.IsShowSidePPTNavigationPanel // ? Visibility.Visible // : Visibility.Collapsed; // RightSidePanelForPPTNavigation.Visibility = Settings.PowerPointSettings.IsShowSidePPTNavigationPanel // ? Visibility.Visible // : Visibility.Collapsed; // } // SaveSettingsToFile(); //} private void ToggleSwitchShowPPTButton_OnToggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); // 更新PPT UI管理器设置 if (_pptUIManager != null) { _pptUIManager.ShowPPTButton = Settings.PowerPointSettings.ShowPPTButton; _pptUIManager.UpdateNavigationPanelsVisibility(); } UpdatePPTBtnPreview(); } private void ToggleSwitchShowPPTSidebarByDefault_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (BtnPPTSlideShowEnd?.Visibility == Visibility.Visible) UpdatePPTQuickPanelVisibility(); } private void ToggleSwitchEnablePPTButtonPageClickable_OnToggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchEnablePPTButtonLongPressPageTurn_OnToggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void PPTLSButtonOpacityValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; var roundedValue = Math.Round((sender as Slider)?.Value ?? 0, 2); Settings.PowerPointSettings.PPTLSButtonOpacity = roundedValue; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLSButtonOpacity = roundedValue; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTRSButtonOpacityValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; var roundedValue = Math.Round((sender as Slider)?.Value ?? 0, 2); Settings.PowerPointSettings.PPTRSButtonOpacity = roundedValue; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRSButtonOpacity = roundedValue; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTLBButtonOpacityValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; var roundedValue = Math.Round((sender as Slider)?.Value ?? 0, 2); Settings.PowerPointSettings.PPTLBButtonOpacity = roundedValue; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLBButtonOpacity = roundedValue; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTRBButtonOpacityValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; var roundedValue = Math.Round((sender as Slider)?.Value ?? 0, 2); Settings.PowerPointSettings.PPTRBButtonOpacity = roundedValue; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRBButtonOpacity = roundedValue; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } // 左侧透明度按钮 private void PPTLSOpacityPlusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLSButtonOpacity = Settings.PowerPointSettings.PPTLSButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTLSOpacityMinusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLSButtonOpacity = Settings.PowerPointSettings.PPTLSButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTLSOpacitySyncBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRSButtonOpacity = Settings.PowerPointSettings.PPTRSButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } // 右侧透明度按钮 private void PPTRSOpacityPlusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRSButtonOpacity = Settings.PowerPointSettings.PPTRSButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTRSOpacityMinusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRSButtonOpacity = Settings.PowerPointSettings.PPTRSButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTRSOpacitySyncBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLSButtonOpacity = Settings.PowerPointSettings.PPTLSButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } // 左下透明度按钮 private void PPTLBOpacityPlusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLBButtonOpacity = Settings.PowerPointSettings.PPTLBButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTLBOpacityMinusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLBButtonOpacity = Settings.PowerPointSettings.PPTLBButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTLBOpacitySyncBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRBButtonOpacity = Settings.PowerPointSettings.PPTRBButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } // 右下透明度按钮 private void PPTRBOpacityPlusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRBButtonOpacity = Settings.PowerPointSettings.PPTRBButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTRBOpacityMinusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRBButtonOpacity = Settings.PowerPointSettings.PPTRBButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTRBOpacitySyncBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLBButtonOpacity = Settings.PowerPointSettings.PPTLBButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTLSOpacityResetBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.PowerPointSettings.PPTLSButtonOpacity = 0.5; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLSButtonOpacity = 0.5; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTRSOpacityResetBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.PowerPointSettings.PPTRSButtonOpacity = 0.5; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRSButtonOpacity = 0.5; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTLBOpacityResetBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.PowerPointSettings.PPTLBButtonOpacity = 0.5; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTLBButtonOpacity = 0.5; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void PPTRBOpacityResetBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.PowerPointSettings.PPTRBButtonOpacity = 0.5; SaveSettingsToFile(); if (_pptUIManager != null) { _pptUIManager.PPTRBButtonOpacity = 0.5; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void CheckboxEnableLBPPTButton_IsCheckChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString(); char[] c = str.ToCharArray(); c[0] = (bool)((CheckBox)sender).IsChecked ? '2' : '1'; Settings.PowerPointSettings.PPTButtonsDisplayOption = int.Parse(new string(c)); SaveSettingsToFile(); // 更新PPT UI管理器设置 if (_pptUIManager != null && BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { _pptUIManager.PPTButtonsDisplayOption = Settings.PowerPointSettings.PPTButtonsDisplayOption; _pptUIManager.UpdateNavigationPanelsVisibility(); } UpdatePPTBtnPreview(); } private void CheckboxEnableRBPPTButton_IsCheckChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString(); char[] c = str.ToCharArray(); c[1] = (bool)((CheckBox)sender).IsChecked ? '2' : '1'; Settings.PowerPointSettings.PPTButtonsDisplayOption = int.Parse(new string(c)); SaveSettingsToFile(); // 更新PPT UI管理器设置 if (_pptUIManager != null && BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { _pptUIManager.PPTButtonsDisplayOption = Settings.PowerPointSettings.PPTButtonsDisplayOption; _pptUIManager.UpdateNavigationPanelsVisibility(); } UpdatePPTBtnPreview(); } private void CheckboxEnableLSPPTButton_IsCheckChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString(); char[] c = str.ToCharArray(); c[2] = (bool)((CheckBox)sender).IsChecked ? '2' : '1'; Settings.PowerPointSettings.PPTButtonsDisplayOption = int.Parse(new string(c)); SaveSettingsToFile(); // 更新PPT UI管理器设置 if (_pptUIManager != null && BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { _pptUIManager.PPTButtonsDisplayOption = Settings.PowerPointSettings.PPTButtonsDisplayOption; _pptUIManager.UpdateNavigationPanelsVisibility(); } UpdatePPTBtnPreview(); } private void CheckboxEnableRSPPTButton_IsCheckChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString(); char[] c = str.ToCharArray(); c[3] = (bool)((CheckBox)sender).IsChecked ? '2' : '1'; Settings.PowerPointSettings.PPTButtonsDisplayOption = int.Parse(new string(c)); SaveSettingsToFile(); // 更新PPT UI管理器设置 if (_pptUIManager != null && BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { _pptUIManager.PPTButtonsDisplayOption = Settings.PowerPointSettings.PPTButtonsDisplayOption; _pptUIManager.UpdateNavigationPanelsVisibility(); } UpdatePPTBtnPreview(); } private void CheckboxSPPTDisplayPage_IsCheckChange(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTSButtonsOption.ToString(); char[] c = str.ToCharArray(); c[0] = (bool)((CheckBox)sender).IsChecked ? '2' : '1'; Settings.PowerPointSettings.PPTSButtonsOption = int.Parse(new string(c)); SaveSettingsToFile(); // 更新PPT UI管理器设置 if (_pptUIManager != null && BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { _pptUIManager.PPTSButtonsOption = Settings.PowerPointSettings.PPTSButtonsOption; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void CheckboxSPPTHalfOpacity_IsCheckChange(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTSButtonsOption.ToString(); char[] c = str.ToCharArray(); bool isHalfOpacity = (bool)((CheckBox)sender).IsChecked; c[1] = isHalfOpacity ? '2' : '1'; Settings.PowerPointSettings.PPTSButtonsOption = int.Parse(new string(c)); // 如果开启半透明选项,设置默认透明度为0.5;否则为1.0 if (isHalfOpacity) { if (Settings.PowerPointSettings.PPTLSButtonOpacity == 1.0) Settings.PowerPointSettings.PPTLSButtonOpacity = 0.5; if (Settings.PowerPointSettings.PPTRSButtonOpacity == 1.0) Settings.PowerPointSettings.PPTRSButtonOpacity = 0.5; } else { if (Settings.PowerPointSettings.PPTLSButtonOpacity == 0.5) Settings.PowerPointSettings.PPTLSButtonOpacity = 1.0; if (Settings.PowerPointSettings.PPTRSButtonOpacity == 0.5) Settings.PowerPointSettings.PPTRSButtonOpacity = 1.0; } SaveSettingsToFile(); // 更新PPT UI管理器设置 if (_pptUIManager != null && BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { _pptUIManager.PPTSButtonsOption = Settings.PowerPointSettings.PPTSButtonsOption; _pptUIManager.PPTLSButtonOpacity = Settings.PowerPointSettings.PPTLSButtonOpacity; _pptUIManager.PPTRSButtonOpacity = Settings.PowerPointSettings.PPTRSButtonOpacity; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void CheckboxSPPTBlackBackground_IsCheckChange(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTSButtonsOption.ToString(); char[] c = str.ToCharArray(); c[2] = (bool)((CheckBox)sender).IsChecked ? '2' : '1'; Settings.PowerPointSettings.PPTSButtonsOption = int.Parse(new string(c)); SaveSettingsToFile(); // 更新PPT UI管理器设置 if (_pptUIManager != null && BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { _pptUIManager.PPTSButtonsOption = Settings.PowerPointSettings.PPTSButtonsOption; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void CheckboxBPPTDisplayPage_IsCheckChange(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTBButtonsOption.ToString(); char[] c = str.ToCharArray(); c[0] = (bool)((CheckBox)sender).IsChecked ? '2' : '1'; Settings.PowerPointSettings.PPTBButtonsOption = int.Parse(new string(c)); SaveSettingsToFile(); // 更新PPT UI管理器设置 if (_pptUIManager != null && BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { _pptUIManager.PPTBButtonsOption = Settings.PowerPointSettings.PPTBButtonsOption; _pptUIManager.UpdateNavigationButtonStyles(); } UpdatePPTBtnPreview(); } private void CheckboxBPPTHalfOpacity_IsCheckChange(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTBButtonsOption.ToString(); char[] c = str.ToCharArray(); bool isHalfOpacity = (bool)((CheckBox)sender).IsChecked; c[1] = isHalfOpacity ? '2' : '1'; Settings.PowerPointSettings.PPTBButtonsOption = int.Parse(new string(c)); // 如果开启半透明选项,设置默认透明度为0.5;否则为1.0 if (isHalfOpacity) { if (Settings.PowerPointSettings.PPTLBButtonOpacity == 1.0) Settings.PowerPointSettings.PPTLBButtonOpacity = 0.5; if (Settings.PowerPointSettings.PPTRBButtonOpacity == 1.0) Settings.PowerPointSettings.PPTRBButtonOpacity = 0.5; } else { if (Settings.PowerPointSettings.PPTLBButtonOpacity == 0.5) Settings.PowerPointSettings.PPTLBButtonOpacity = 1.0; if (Settings.PowerPointSettings.PPTRBButtonOpacity == 0.5) Settings.PowerPointSettings.PPTRBButtonOpacity = 1.0; } SaveSettingsToFile(); UpdatePPTUIManagerSettings(); UpdatePPTBtnPreview(); } private void CheckboxBPPTBlackBackground_IsCheckChange(object sender, RoutedEventArgs e) { if (!isLoaded) return; var str = Settings.PowerPointSettings.PPTBButtonsOption.ToString(); char[] c = str.ToCharArray(); c[2] = (bool)((CheckBox)sender).IsChecked ? '2' : '1'; Settings.PowerPointSettings.PPTBButtonsOption = int.Parse(new string(c)); SaveSettingsToFile(); UpdatePPTUIManagerSettings(); UpdatePPTBtnPreview(); } private void PPTButtonLeftPositionValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); UpdatePPTUIManagerSettings(); SliderDelayAction.DebounceAction(2000, null, SaveSettingsToFile); UpdatePPTBtnPreview(); } private void UpdatePPTBtnSlidersStatus() { } private void PPTBtnLSPlusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnLSMinusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnLSSyncBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnLSResetBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); Settings.PowerPointSettings.PPTLSButtonPosition = 0; SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnRSPlusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnRSMinusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnRSSyncBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnRSResetBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); Settings.PowerPointSettings.PPTRSButtonPosition = 0; SaveSettingsToFile(); UpdatePPTBtnPreview(); } private DelayAction SliderDelayAction = new DelayAction(); private void PPTButtonRightPositionValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); UpdatePPTUIManagerSettings(); SliderDelayAction.DebounceAction(2000, null, SaveSettingsToFile); UpdatePPTBtnPreview(); } /// /// 更新PPT UI管理器设置的通用方法 /// private void UpdatePPTUIManagerSettings() { if (_pptUIManager != null && BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { _pptUIManager.PPTButtonsDisplayOption = Settings.PowerPointSettings.PPTButtonsDisplayOption; _pptUIManager.PPTSButtonsOption = Settings.PowerPointSettings.PPTSButtonsOption; _pptUIManager.PPTBButtonsOption = Settings.PowerPointSettings.PPTBButtonsOption; _pptUIManager.PPTLSButtonPosition = Settings.PowerPointSettings.PPTLSButtonPosition; _pptUIManager.PPTRSButtonPosition = Settings.PowerPointSettings.PPTRSButtonPosition; _pptUIManager.PPTLBButtonPosition = Settings.PowerPointSettings.PPTLBButtonPosition; _pptUIManager.PPTRBButtonPosition = Settings.PowerPointSettings.PPTRBButtonPosition; _pptUIManager.EnablePPTButtonPageClickable = Settings.PowerPointSettings.EnablePPTButtonPageClickable; _pptUIManager.EnablePPTButtonLongPressPageTurn = Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn; _pptUIManager.PPTLSButtonOpacity = Settings.PowerPointSettings.PPTLSButtonOpacity; _pptUIManager.PPTRSButtonOpacity = Settings.PowerPointSettings.PPTRSButtonOpacity; _pptUIManager.PPTLBButtonOpacity = Settings.PowerPointSettings.PPTLBButtonOpacity; _pptUIManager.PPTRBButtonOpacity = Settings.PowerPointSettings.PPTRBButtonOpacity; _pptUIManager.UpdateNavigationPanelsVisibility(); _pptUIManager.UpdateNavigationButtonStyles(); } } private void UpdatePPTBtnPreview() { try { if (_pptUIManager != null) { _pptUIManager.PPTLSButtonPosition = Settings.PowerPointSettings.PPTLSButtonPosition; _pptUIManager.PPTRSButtonPosition = Settings.PowerPointSettings.PPTRSButtonPosition; _pptUIManager.PPTLBButtonPosition = Settings.PowerPointSettings.PPTLBButtonPosition; _pptUIManager.PPTRBButtonPosition = Settings.PowerPointSettings.PPTRBButtonPosition; _pptUIManager.EnablePPTButtonPageClickable = Settings.PowerPointSettings.EnablePPTButtonPageClickable; _pptUIManager.EnablePPTButtonLongPressPageTurn = Settings.PowerPointSettings.EnablePPTButtonLongPressPageTurn; _pptUIManager.PPTLSButtonOpacity = Settings.PowerPointSettings.PPTLSButtonOpacity; _pptUIManager.PPTRSButtonOpacity = Settings.PowerPointSettings.PPTRSButtonOpacity; _pptUIManager.PPTLBButtonOpacity = Settings.PowerPointSettings.PPTLBButtonOpacity; _pptUIManager.PPTRBButtonOpacity = Settings.PowerPointSettings.PPTRBButtonOpacity; _pptUIManager.UpdateNavigationPanelsVisibility(); _pptUIManager.UpdateNavigationButtonStyles(); } } catch { } } #endregion #region Canvas /// 笔锋下拉 UI 顺序:0 实时笔锋,1 基于点集,2 基于速率,3 关闭。与存储值 InkStyle:3,0,1,2 对应。 private static int PenStyleUiIndexFromInkStyle(int inkStyle) { switch (inkStyle) { case 3: return 0; case 0: return 1; case 1: return 2; case 2: return 3; default: return 1; } } private static int InkStyleFromPenStyleUiIndex(int uiIndex) { switch (uiIndex) { case 0: return 3; case 1: return 0; case 2: return 1; case 3: return 2; default: return 0; } } private void ComboBoxPenStyle_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded) return; int uiIndex = sender == ComboBoxPenStyle ? ComboBoxPenStyle.SelectedIndex : BoardComboBoxPenStyle.SelectedIndex; if (uiIndex < 0) return; Settings.Canvas.InkStyle = InkStyleFromPenStyleUiIndex(uiIndex); if (sender == ComboBoxPenStyle) BoardComboBoxPenStyle.SelectedIndex = uiIndex; ComboBoxPenStyle.SelectedIndex = uiIndex; SaveSettingsToFile(); } private void SwitchToCircleEraser(object sender, MouseButtonEventArgs e) { if (!isLoaded) return; Settings.Canvas.EraserShapeType = 0; SaveSettingsToFile(); CheckEraserTypeTab(); // 使用新的高级橡皮擦形状应用方法 ApplyAdvancedEraserShape(); // 确保当前处于橡皮擦模式时能立即看到效果 inkCanvas.EditingMode = InkCanvasEditingMode.Ink; inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint; } private void SwitchToRectangleEraser(object sender, MouseButtonEventArgs e) { if (!isLoaded) return; Settings.Canvas.EraserShapeType = 1; SaveSettingsToFile(); CheckEraserTypeTab(); // 使用新的高级橡皮擦形状应用方法 ApplyAdvancedEraserShape(); // 确保当前处于橡皮擦模式时能立即看到效果 inkCanvas.EditingMode = InkCanvasEditingMode.Ink; inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint; } private void InkWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (!isLoaded) return; if (sender == BoardInkWidthSlider) InkWidthSlider.Value = ((Slider)sender).Value; if (sender == InkWidthSlider) BoardInkWidthSlider.Value = ((Slider)sender).Value; drawingAttributes.Height = ((Slider)sender).Value / 2; drawingAttributes.Width = ((Slider)sender).Value / 2; Settings.Canvas.InkWidth = ((Slider)sender).Value / 2; SaveSettingsToFile(); } private void HighlighterWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (!isLoaded) return; // if (sender == BoardInkWidthSlider) InkWidthSlider.Value = ((Slider)sender).Value; // if (sender == InkWidthSlider) BoardInkWidthSlider.Value = ((Slider)sender).Value; drawingAttributes.Height = ((Slider)sender).Value; drawingAttributes.Width = ((Slider)sender).Value / 2; Settings.Canvas.HighlighterWidth = ((Slider)sender).Value; SaveSettingsToFile(); } /// /// 将画笔不透明度更新为滑块的当前值,并保存到设置中。 /// /// /// 使用滑块的当前值作为 alpha 通道更新 drawingAttributes.Color,同时将该值写入 Settings.Canvas.InkAlpha 并持久化配置文件。 /// private void InkAlphaSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (!isLoaded) return; // if (sender == BoardInkWidthSlider) InkWidthSlider.Value = ((Slider)sender).Value; // if (sender == InkWidthSlider) BoardInkWidthSlider.Value = ((Slider)sender).Value; var NowR = drawingAttributes.Color.R; var NowG = drawingAttributes.Color.G; var NowB = drawingAttributes.Color.B; // Trace.WriteLine(BitConverter.GetBytes(((Slider)sender).Value)); drawingAttributes.Color = Color.FromArgb((byte)((Slider)sender).Value, NowR, NowG, NowB); Settings.Canvas.InkAlpha = ((Slider)sender).Value; SaveSettingsToFile(); } /// /// 根据组合框的当前选择更新双曲线渐近线选项(Settings.Canvas.HyperbolaAsymptoteOption),并将更改保存到设置文件。 /// #endregion #region Automation private void StartOrStoptimerCheckAutoFold() { if (Settings.Automation.IsEnableAutoFold) _unifiedMainWindowTimer?.Start(); _unifiedMainWindowTimer?.Stop(); } private void ToggleSwitchAutoFoldInEasiNote_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInEasiNoteIgnoreDesktopAnno_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.Automation.IsAutoFoldInEasiNoteIgnoreDesktopAnno = (sender as ToggleSwitch)?.IsOn ?? false; SaveSettingsToFile(); } private void ToggleSwitchAutoFoldInEasiCamera_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInEasiNote3_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInEasiNote3C_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInEasiNote5C_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInSeewoPincoTeacher_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInHiteTouchPro_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInHiteLightBoard_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInHiteCamera_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInWxBoardMain_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInOldZyBoard_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInMSWhiteboard_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInAdmoxWhiteboard_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInAdmoxBooth_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInQPoint_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInYiYunVisualPresenter_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInMaxHubWhiteboard_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoFoldInPPTSlideShow_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; // 记录设置变更前的状态 bool previousState = Settings.Automation.IsAutoFoldInPPTSlideShow; // 如果设置状态发生变化,重置PPT相关状态变量 if (previousState != Settings.Automation.IsAutoFoldInPPTSlideShow) { ResetPPTStateVariables(); LogHelper.WriteLogToFile($"PPT自动收纳设置已变更: {Settings.Automation.IsAutoFoldInPPTSlideShow}, 已重置相关状态变量", LogHelper.LogType.Trace); } if (Settings.Automation.IsAutoFoldInPPTSlideShow) { } else { } SaveSettingsToFile(); StartOrStoptimerCheckAutoFold(); } private void ToggleSwitchAutoKillPptService_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) timerKillProcess.Start(); timerKillProcess.Stop(); } private void ToggleSwitchAutoKillEasiNote_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) timerKillProcess.Start(); timerKillProcess.Stop(); } private void ToggleSwitchAutoKillHiteAnnotation_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) timerKillProcess.Start(); timerKillProcess.Stop(); } private void ToggleSwitchAutoKillVComYouJiao_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) timerKillProcess.Start(); timerKillProcess.Stop(); } private void ToggleSwitchAutoKillSeewoLauncher2DesktopAnnotation_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) timerKillProcess.Start(); timerKillProcess.Stop(); } private void ToggleSwitchAutoKillInkCanvas_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) timerKillProcess.Start(); timerKillProcess.Stop(); } private void ToggleSwitchAutoKillICA_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) timerKillProcess.Start(); timerKillProcess.Stop(); } private void ToggleSwitchAutoKillIDT_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) timerKillProcess.Start(); timerKillProcess.Stop(); } private void ToggleSwitchAutoEnterAnnotationModeWhenExitFoldMode_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchAutoFoldWhenExitWhiteboard_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchSaveScreenshotsInDateFolders_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchAutoSaveStrokesAtScreenshot_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchAutoSaveStrokesAtClear_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } // 注释掉这些方法,因为对应的UI控件还没有在XAML中定义 /* private void ToggleSwitchAsyncInkSmoothing_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.Canvas.UseAsyncInkSmoothing = ToggleSwitchAsyncInkSmoothing.IsOn; _inkSmoothingManager?.UpdateConfig(); SaveSettingsToFile(); } private void ToggleSwitchHardwareAcceleration_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.Canvas.UseHardwareAcceleration = ToggleSwitchHardwareAcceleration.IsOn; _inkSmoothingManager?.UpdateConfig(); SaveSettingsToFile(); } private void ComboBoxInkSmoothingQuality_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded) return; Settings.Canvas.InkSmoothingQuality = ComboBoxInkSmoothingQuality.SelectedIndex; _inkSmoothingManager?.UpdateConfig(); SaveSettingsToFile(); } private void SliderMaxConcurrentTasks_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (!isLoaded) return; Settings.Canvas.MaxConcurrentSmoothingTasks = (int)SliderMaxConcurrentTasks.Value; _inkSmoothingManager?.UpdateConfig(); SaveSettingsToFile(); } private void ButtonApplyRecommendedSettings_Click(object sender, RoutedEventArgs e) { // 应用推荐的性能设置 Helpers.InkSmoothingManager.ApplyRecommendedSettings(); LoadSettings(false); _inkSmoothingManager?.UpdateConfig(); SaveSettingsToFile(); ShowNotification("已应用推荐的性能设置"); } private void ButtonShowPerformanceStats_Click(object sender, RoutedEventArgs e) { if (_inkSmoothingManager != null) { var stats = _inkSmoothingManager.GetPerformanceStats(); ShowNotification($"性能统计: {stats}"); } } */ private void ToggleSwitchAutoSaveStrokesInPowerPoint_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchNotifyPreviousPage_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchNotifyHiddenPage_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchNotifyAutoPlayPresentation_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void SideControlMinimumAutomationSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void AutoSavedStrokesLocationTextBox_TextChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void AutoSavedStrokesLocationButton_Click(object sender, RoutedEventArgs e) { var folderBrowser = new FolderBrowserDialog(); folderBrowser.ShowDialog(); SaveSettingsToFile(); } private void SetAutoSavedStrokesLocationToDiskDButton_Click(object sender, RoutedEventArgs e) { SaveSettingsToFile(); } private void SetAutoSavedStrokesLocationToDocumentFolderButton_Click(object sender, RoutedEventArgs e) { Settings.Automation.AutoSavedStrokesLocation = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Ink Canvas"; SaveSettingsToFile(); } private void BtnCloudStorageManagementSettingsManage_Click(object sender, RoutedEventArgs e) { if (isOpeningOrHidingSettingsPane) return; HideSubPanels(); try { // 打开设置管理窗口 var CloudStorageManagementSettingsWindow = new Windows.CloudStorageManagementWindow(); CloudStorageManagementSettingsWindow.Owner = this; CloudStorageManagementSettingsWindow.ShowDialog(); } catch (Exception ex) { LogHelper.WriteLogToFile($"打开云存储管理窗口时出错: {ex.Message}", LogHelper.LogType.Error); MessageBox.Show($"打开云存储管理窗口时发生错误: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } private void ToggleSwitchAutoDelSavedFiles_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ComboBoxAutoDelSavedFilesDaysThreshold_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded) return; Settings.Automation.AutoDelSavedFilesDaysThreshold = (sender as System.Windows.Controls.ComboBox)?.SelectedIndex ?? 0; SaveSettingsToFile(); } private void ToggleSwitchAutoSaveScreenShotInPowerPoint_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint = (sender as ToggleSwitch)?.IsOn ?? false; SaveSettingsToFile(); } private void ToggleSwitchSaveFullPageStrokes_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchSaveStrokesAsXML_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchEnableAutoSaveStrokes_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); // 更新定时器状态 UpdateAutoSaveStrokesTimer(); } private void ComboBoxAutoSaveStrokesInterval_SelectionChanged(object sender, SelectionChangedEventArgs e) { var selectedItem = (sender as ComboBox)?.SelectedItem as ComboBoxItem; if (selectedItem?.Tag != null && int.TryParse(selectedItem.Tag.ToString(), out int intervalMinutes)) { Settings.Automation.AutoSaveStrokesIntervalMinutes = intervalMinutes; SaveSettingsToFile(); // 更新定时器间隔 UpdateAutoSaveStrokesTimer(); } } #endregion #region Gesture private void ToggleSwitchEnableFingerGestureSlideShowControl_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.PowerPointSettings.IsEnableFingerGestureSlideShowControl = (sender as ToggleSwitch)?.IsOn ?? false; SaveSettingsToFile(); } private void ToggleSwitchAutoSwitchTwoFingerGesture_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchEnableTwoFingerZoom_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { Settings.Gesture.IsEnableTwoFingerZoom = true; SaveSettingsToFile(); } catch { } } private void ToggleSwitchEnableTwoFingerTranslate_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { Settings.Gesture.IsEnableTwoFingerTranslate = true; SaveSettingsToFile(); } catch { } } private void ToggleSwitchEnableMultiTouchMode_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { Settings.Gesture.IsEnableMultiTouchMode = true; SaveSettingsToFile(); } catch { } } private void ToggleSwitchEnableTwoFingerRotation_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { Settings.Gesture.IsEnableTwoFingerRotation = true; SaveSettingsToFile(); } catch { } } private void ToggleSwitchEnableTwoFingerGestureInPresentationMode_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode = true; SaveSettingsToFile(); } #endregion #region Reset /// /// 将应用设置重置为推荐的默认配置。 /// /// /// 该方法会重新创建全局 Settings 实例并应用推荐值,覆盖大部分子模块配置(如外观、画布、自动化、PPT、手势、高级选项等)。 /// 在重置过程中会保留并恢复当前 Settings.Automation 中的 AutoDelSavedFiles 与 AutoDelSavedFilesDaysThreshold 两项值以避免意外删除策略变化。 /// public static void SetSettingsToRecommendation() { var AutoDelSavedFilesDays = Settings.Automation.AutoDelSavedFiles; var AutoDelSavedFilesDaysThreshold = Settings.Automation.AutoDelSavedFilesDaysThreshold; Settings = new Settings(); Settings.Advanced.IsSpecialScreen = true; Settings.Advanced.IsQuadIR = false; Settings.Advanced.TouchMultiplier = 0.3; Settings.Advanced.NibModeBoundsWidth = 5; Settings.Advanced.FingerModeBoundsWidth = 20; Settings.Advanced.NibModeBoundsWidthThresholdValue = 2.5; Settings.Advanced.FingerModeBoundsWidthThresholdValue = 2.5; Settings.Advanced.NibModeBoundsWidthEraserSize = 0.8; Settings.Advanced.FingerModeBoundsWidthEraserSize = 0.8; Settings.Advanced.EraserBindTouchMultiplier = true; Settings.Advanced.IsLogEnabled = true; Settings.Advanced.IsSecondConfirmWhenShutdownApp = false; Settings.Advanced.IsEnableEdgeGestureUtil = false; Settings.Advanced.EdgeGestureUtilOnlyAffectBlackboardMode = false; Settings.Advanced.IsEnableFullScreenHelper = false; Settings.Advanced.IsEnableAvoidFullScreenHelper = false; Settings.Advanced.IsEnableForceFullScreen = false; Settings.Advanced.IsEnableDPIChangeDetection = false; Settings.Advanced.IsEnableResolutionChangeDetection = false; Settings.Appearance.IsEnableDisPlayNibModeToggler = false; Settings.Appearance.IsColorfulViewboxFloatingBar = false; Settings.Appearance.ViewboxFloatingBarScaleTransformValue = 1; Settings.Appearance.EnableViewboxBlackBoardScaleTransform = false; Settings.Appearance.IsTransparentButtonBackground = true; Settings.Appearance.IsShowExitButton = true; Settings.Appearance.IsShowEraserButton = true; Settings.Appearance.IsShowHideControlButton = false; Settings.Appearance.IsShowLRSwitchButton = false; Settings.Appearance.IsShowModeFingerToggleSwitch = true; Settings.Appearance.IsShowQuickPanel = true; Settings.Appearance.Theme = 0; Settings.Appearance.EnableChickenSoupInWhiteboardMode = true; Settings.Appearance.EnableTimeDisplayInWhiteboardMode = true; Settings.Appearance.ChickenSoupSource = 1; Settings.Appearance.ViewboxFloatingBarOpacityValue = 1.0; Settings.Appearance.ViewboxFloatingBarOpacityInPPTValue = 1.0; Settings.Appearance.EnableTrayIcon = true; // 浮动栏按钮显示控制默认值 Settings.Appearance.IsShowShapeButton = true; Settings.Appearance.IsShowUndoButton = true; Settings.Appearance.IsShowRedoButton = true; Settings.Appearance.IsShowClearButton = true; Settings.Appearance.IsShowWhiteboardButton = true; Settings.Appearance.IsShowHideButton = true; Settings.Appearance.IsShowLassoSelectButton = true; Settings.Appearance.IsShowClearAndMouseButton = true; Settings.Appearance.IsShowQuickColorPalette = false; Settings.Appearance.QuickColorPaletteDisplayMode = 1; Settings.Appearance.EraserDisplayOption = 0; Settings.Automation.IsAutoFoldInEasiNote = true; Settings.Automation.IsAutoFoldInEasiNoteIgnoreDesktopAnno = true; Settings.Automation.IsAutoFoldInEasiCamera = true; Settings.Automation.IsAutoFoldInEasiNote3C = false; Settings.Automation.IsAutoFoldInEasiNote3 = false; Settings.Automation.IsAutoFoldInEasiNote5C = true; Settings.Automation.IsAutoFoldInSeewoPincoTeacher = false; Settings.Automation.IsAutoFoldInHiteTouchPro = false; Settings.Automation.IsAutoFoldInHiteCamera = false; Settings.Automation.IsAutoFoldInWxBoardMain = false; Settings.Automation.IsAutoFoldInOldZyBoard = false; Settings.Automation.IsAutoFoldInMSWhiteboard = false; Settings.Automation.IsAutoFoldInAdmoxWhiteboard = false; Settings.Automation.IsAutoFoldInAdmoxBooth = false; Settings.Automation.IsAutoFoldInQPoint = false; Settings.Automation.IsAutoFoldInYiYunVisualPresenter = false; Settings.Automation.IsAutoFoldInMaxHubWhiteboard = false; Settings.Automation.IsAutoFoldInPPTSlideShow = false; Settings.Automation.IsAutoKillPptService = false; Settings.Automation.IsAutoKillEasiNote = false; Settings.Automation.IsAutoKillVComYouJiao = false; Settings.Automation.IsAutoKillInkCanvas = false; Settings.Automation.IsAutoKillICA = false; Settings.Automation.IsAutoKillIDT = false; Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation = false; Settings.Automation.IsSaveScreenshotsInDateFolders = false; Settings.Automation.IsAutoSaveStrokesAtScreenshot = true; Settings.Automation.IsAutoSaveStrokesAtClear = true; Settings.Automation.IsAutoClearWhenExitingWritingMode = false; Settings.Automation.MinimumAutomationStrokeNumber = 0; Settings.Automation.AutoDelSavedFiles = AutoDelSavedFilesDays; Settings.Automation.AutoDelSavedFilesDaysThreshold = AutoDelSavedFilesDaysThreshold; //Settings.PowerPointSettings.IsShowPPTNavigation = true; //Settings.PowerPointSettings.IsShowBottomPPTNavigationPanel = false; //Settings.PowerPointSettings.IsShowSidePPTNavigationPanel = true; Settings.PowerPointSettings.PowerPointSupport = true; Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow = false; Settings.PowerPointSettings.IsNoClearStrokeOnSelectWhenInPowerPoint = true; Settings.PowerPointSettings.IsShowStrokeOnSelectInPowerPoint = false; Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint = true; Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint = true; Settings.PowerPointSettings.IsNotifyPreviousPage = false; Settings.PowerPointSettings.IsNotifyHiddenPage = false; Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode = false; Settings.PowerPointSettings.IsEnableFingerGestureSlideShowControl = false; Settings.PowerPointSettings.IsSupportWPS = false; Settings.Canvas.InkWidth = 2.5; Settings.Canvas.IsShowCursor = false; Settings.Canvas.InkStyle = 0; Settings.Canvas.HighlighterWidth = 20; Settings.Canvas.EraserSize = 1; Settings.Canvas.EraserType = 0; Settings.Canvas.EraserShapeType = 1; Settings.Canvas.HideStrokeWhenSelecting = false; Settings.Canvas.ClearCanvasAndClearTimeMachine = false; Settings.Canvas.FitToCurve = false; Settings.Canvas.UseAdvancedBezierSmoothing = true; Settings.Canvas.EnablePressureTouchMode = false; Settings.Canvas.DisablePressure = false; Settings.Canvas.AutoStraightenLine = true; Settings.Canvas.AutoStraightenLineThreshold = 80; Settings.Canvas.LineEndpointSnapping = true; Settings.Canvas.LineEndpointSnappingThreshold = 15; Settings.Canvas.UsingWhiteboard = false; Settings.Canvas.HyperbolaAsymptoteOption = 0; Settings.Gesture.AutoSwitchTwoFingerGesture = true; Settings.Gesture.IsEnableTwoFingerTranslate = true; Settings.Gesture.IsEnableTwoFingerZoom = false; Settings.Gesture.IsEnableTwoFingerRotation = false; Settings.Gesture.IsEnableTwoFingerRotationOnSelection = false; Settings.InkToShape.IsInkToShapeEnabled = true; Settings.InkToShape.IsInkToShapeNoFakePressureRectangle = false; Settings.InkToShape.IsInkToShapeNoFakePressureTriangle = false; Settings.InkToShape.IsInkToShapeTriangle = true; Settings.InkToShape.IsInkToShapeRectangle = true; Settings.InkToShape.IsInkToShapeRounded = true; Settings.InkToShape.EnableWinRtHandwritingStrokeBeautify = false; Settings.InkToShape.HandwritingCorrectionFontFamily = "Ink Free,KaiTi,Segoe Script"; Settings.Startup.IsEnableNibMode = false; Settings.Startup.IsAutoUpdate = true; Settings.Startup.IsAutoUpdateWithSilence = true; Settings.Startup.AutoUpdateWithSilenceStartTime = "06:00"; Settings.Startup.AutoUpdateWithSilenceEndTime = "22:00"; Settings.Startup.IsFoldAtStartup = false; } /// /// 将应用设置重置为推荐的默认值,并保存与重新加载配置以应用更改。 /// /// /// 如果配置重置受安全密码保护,则会提示用户输入密码;在验证失败时中止重置。方法会暂时停止加载标志以避免触发事件、将“开机启动”切换置为关闭,并在完成后显示一条通知。任何内部异常将被吞噬以保证流程不中断。 /// public async void BtnResetToSuggestion_Click(object sender, RoutedEventArgs e) { try { if (sender != null && Ink_Canvas.Helpers.SecurityManager.IsPasswordRequiredForResetConfig(Settings)) { bool ok = await Ink_Canvas.Helpers.SecurityManager.PromptAndVerifyAsync(Settings, this, "重置配置验证", "请输入安全密码以确认重置配置。"); if (!ok) return; } } catch { } try { isLoaded = false; SetSettingsToRecommendation(); SaveSettingsToFile(); LoadSettings(isStartup: false, skipAutoUpdateCheck: true); isLoaded = true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); } ShowNotification("设置已重置为默认推荐设置~"); } private async void SpecialVersionResetToSuggestion_Click() { await Task.Delay(1000); try { isLoaded = false; SetSettingsToRecommendation(); Settings.Automation.AutoDelSavedFiles = true; Settings.Automation.AutoDelSavedFilesDaysThreshold = 15; SetAutoSavedStrokesLocationToDiskDButton_Click(null, null); SaveSettingsToFile(); LoadSettings(isStartup: false, skipAutoUpdateCheck: true); isLoaded = true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); } } #endregion #region Ink To Shape #endregion #region Advanced private void ToggleSwitchIsSpecialScreen_OnToggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsEnableUriScheme_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; bool success = false; var newState = (sender as ToggleSwitch)?.IsOn ?? false; try { if (newState) { if (!UriSchemeHelper.IsUriSchemeRegistered()) { success = UriSchemeHelper.RegisterUriScheme(); } else { success = true; } } else { if (UriSchemeHelper.IsUriSchemeRegistered()) { success = UriSchemeHelper.UnregisterUriScheme(); } else { success = true; } } } catch (Exception ex) { LogHelper.WriteLogToFile($"切换URI Scheme状态失败: {ex.Message}", LogHelper.LogType.Error); success = false; } if (success) { Settings.Advanced.IsEnableUriScheme = newState; SaveSettingsToFile(); } else { // 回滚 UI 状态 isLoaded = false; isLoaded = true; ShowNotification("设置外部协议失败,请检查权限或日志"); } } private void TouchMultiplierSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (!isLoaded) return; Settings.Advanced.TouchMultiplier = e.NewValue; SaveSettingsToFile(); } private void BorderCalculateMultiplier_TouchDown(object sender, TouchEventArgs e) { var args = e.GetTouchPoint(null).Bounds; double value; if (!Settings.Advanced.IsQuadIR) value = args.Width; } private void ToggleSwitchIsEnableFullScreenHelper_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsEnableAvoidFullScreenHelper_OnToggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsEnableEdgeGestureUtil_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsEnableForceFullScreen_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsEnableDPIChangeDetection_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsEnableResolutionChangeDetection_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchEraserBindTouchMultiplier_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void NibModeBoundsWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (!isLoaded) return; Settings.Advanced.NibModeBoundsWidth = (int)e.NewValue; if (Settings.Startup.IsEnableNibMode) BoundsWidth = Settings.Advanced.NibModeBoundsWidth; BoundsWidth = Settings.Advanced.FingerModeBoundsWidth; SaveSettingsToFile(); } private void FingerModeBoundsWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (!isLoaded) return; Settings.Advanced.FingerModeBoundsWidth = (int)e.NewValue; if (Settings.Startup.IsEnableNibMode) BoundsWidth = Settings.Advanced.NibModeBoundsWidth; BoundsWidth = Settings.Advanced.FingerModeBoundsWidth; SaveSettingsToFile(); } private void ToggleSwitchIsQuadIR_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsLogEnabled_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsSaveLogByDate_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsSecondConfimeWhenShutdownApp_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsAutoBackupBeforeUpdate_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchIsAutoBackupEnabled_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ComboBoxAutoBackupInterval_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded) return; var selectedItem = (sender as ComboBox)?.SelectedItem as ComboBoxItem; { if (selectedItem != null && selectedItem.Tag != null && int.TryParse(selectedItem.Tag.ToString(), out int interval)) { Settings.Advanced.AutoBackupIntervalDays = interval; SaveSettingsToFile(); } } } private void BtnManualBackup_Click(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { // 确保Backups目录存在 string backupDir = Path.Combine(App.RootPath, "Backups"); if (!Directory.Exists(backupDir)) { Directory.CreateDirectory(backupDir); LogHelper.WriteLogToFile($"创建备份目录: {backupDir}"); } // 创建备份文件名(使用当前日期时间) string backupFileName = $"Settings_Backup_{DateTime.Now:yyyyMMdd_HHmmss}.json"; string backupPath = Path.Combine(backupDir, backupFileName); // 序列化当前设置并保存到备份文件 string settingsJson = JsonConvert.SerializeObject(Settings, Formatting.Indented); File.WriteAllText(backupPath, settingsJson); LogHelper.WriteLogToFile($"成功创建设置备份: {backupPath}"); MessageBox.Show($"设置已成功备份到:\n{backupPath}", "备份成功", MessageBoxButton.OK, MessageBoxImage.Information); } catch (Exception ex) { LogHelper.WriteLogToFile($"创建设置备份时出错: {ex.Message}", LogHelper.LogType.Error); MessageBox.Show($"创建备份失败: {ex.Message}", "备份失败", MessageBoxButton.OK, MessageBoxImage.Error); } } private void BtnRestoreBackup_Click(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { // 确保Backups目录存在 string backupDir = Path.Combine(App.RootPath, "Backups"); if (!Directory.Exists(backupDir)) { Directory.CreateDirectory(backupDir); LogHelper.WriteLogToFile($"创建备份目录: {backupDir}"); MessageBox.Show("没有找到备份文件,请先创建备份", "还原失败", MessageBoxButton.OK, MessageBoxImage.Warning); return; } // 打开文件选择对话框 OpenFileDialog dlg = new OpenFileDialog(); dlg.InitialDirectory = backupDir; dlg.Filter = "设置备份文件|Settings_Backup_*.json|所有JSON文件|*.json"; dlg.Title = "选择要还原的备份文件"; if (dlg.ShowDialog() == true) { // 读取备份文件 string backupJson = File.ReadAllText(dlg.FileName); // 反序列化备份数据 Settings backupSettings = JsonConvert.DeserializeObject(backupJson); if (backupSettings != null) { // 确认是否要还原 if (MessageBox.Show("确定要还原选择的备份文件吗?当前设置将被覆盖。", "确认还原", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) { // 备份当前设置,以防出错 string currentSettingsJson = JsonConvert.SerializeObject(Settings, Formatting.Indented); string tempBackupPath = Path.Combine(backupDir, $"Settings_Before_Restore_{DateTime.Now:yyyyMMdd_HHmmss}.json"); File.WriteAllText(tempBackupPath, currentSettingsJson); // 还原设置 Settings = backupSettings; // 保存还原后的设置到文件 SaveSettingsToFile(); // 重新加载设置到UI LoadSettings(); LogHelper.WriteLogToFile($"成功从备份还原设置: {dlg.FileName}"); MessageBox.Show("设置已成功还原,部分设置可能需要重启软件后生效。", "还原成功", MessageBoxButton.OK, MessageBoxImage.Information); } } else { MessageBox.Show("无法解析备份文件,文件可能已损坏", "还原失败", MessageBoxButton.OK, MessageBoxImage.Error); } } } catch (Exception ex) { LogHelper.WriteLogToFile($"还原设置备份时出错: {ex.Message}", LogHelper.LogType.Error); MessageBox.Show($"还原备份失败: {ex.Message}", "还原失败", MessageBoxButton.OK, MessageBoxImage.Error); } } private bool _isRefreshingConfigProfileList; private string _lastAppliedProfileName; private void RefreshConfigProfileList() { try { _isRefreshingConfigProfileList = true; try { var names = ConfigProfileManager.ListProfileNames(); } finally { _isRefreshingConfigProfileList = false; } } catch (Exception ex) { LogHelper.WriteLogToFile($"刷新配置方案列表失败: {ex.Message}", LogHelper.LogType.Error); } } private void ComboBoxConfigProfile_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded || _isRefreshingConfigProfileList) return; var name = ((sender as ComboBox)?.SelectedItem as ComboBoxItem)?.Content?.ToString(); if (string.IsNullOrEmpty(name)) return; try { if (ConfigProfileManager.ApplyProfile(name)) { _lastAppliedProfileName = name; ReloadSettingsFromFile(); ShowNotification($"已切换至方案「{name}」"); } } catch (Exception ex) { LogHelper.WriteLogToFile($"切换配置方案失败: {ex.Message}", LogHelper.LogType.Error); } } private async void BtnSaveAsConfigProfile_Click(object sender, RoutedEventArgs e) { if (!isLoaded) return; var input = new System.Windows.Controls.TextBox { MinWidth = 260, Padding = new Thickness(8, 6, 8, 6), Margin = new Thickness(0, 0, 0, 12) }; var label = new System.Windows.Controls.TextBlock { Text = "方案名称", Margin = new Thickness(0, 0, 0, 8) }; var content = new iNKORE.UI.WPF.Controls.SimpleStackPanel { Spacing = 6 }; content.Children.Add(label); content.Children.Add(input); var dialog = new iNKORE.UI.WPF.Modern.Controls.ContentDialog { Title = "另存为方案", Content = content, PrimaryButtonText = "保存", SecondaryButtonText = "取消", Owner = this }; var result = await dialog.ShowAsync(); if (result != iNKORE.UI.WPF.Modern.Controls.ContentDialogResult.Primary) return; var name = input.Text?.Trim(); if (string.IsNullOrEmpty(name)) { MessageBox.Show("请输入方案名称。", "另存为方案", MessageBoxButton.OK, MessageBoxImage.Information); return; } try { var json = JsonConvert.SerializeObject(Settings, Formatting.Indented); if (ConfigProfileManager.SaveAsProfile(name, json)) { _lastAppliedProfileName = name; RefreshConfigProfileList(); ShowNotification($"已另存为方案:{name}"); } else MessageBox.Show("保存失败,请查看日志。", "另存为方案", MessageBoxButton.OK, MessageBoxImage.Warning); } catch (Exception ex) { LogHelper.WriteLogToFile($"另存为方案失败: {ex.Message}", LogHelper.LogType.Error); MessageBox.Show($"保存失败: {ex.Message}", "另存为方案", MessageBoxButton.OK, MessageBoxImage.Error); } } private void BtnDeleteConfigProfile_Click(object sender, RoutedEventArgs e) { if (!isLoaded) return; try { RefreshConfigProfileList(); } catch { } } #endregion #region RandSettings private void ToggleSwitchDisplayRandWindowNamesInputBtn_OnToggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.DisplayRandWindowNamesInputBtn = ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn; SaveSettingsToFile(); } private void RandWindowOnceCloseLatencySlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.RandWindowOnceCloseLatency = RandWindowOnceCloseLatencySlider.Value; SaveSettingsToFile(); } private void RandWindowOnceMaxStudentsSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.RandWindowOnceMaxStudents = (int)RandWindowOnceMaxStudentsSlider.Value; SaveSettingsToFile(); } private void ToggleSwitchUseLegacyTimerUI_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.UseLegacyTimerUI = ToggleSwitchUseLegacyTimerUI.IsOn; if (ToggleSwitchUseLegacyTimerUI.IsOn) { ToggleSwitchUseNewStyleUI.IsOn = false; Settings.RandSettings.UseNewStyleUI = false; } SaveSettingsToFile(); } private void ToggleSwitchUseNewStyleUI_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.UseNewStyleUI = ToggleSwitchUseNewStyleUI.IsOn; if (ToggleSwitchUseNewStyleUI.IsOn) { ToggleSwitchUseLegacyTimerUI.IsOn = false; Settings.RandSettings.UseLegacyTimerUI = false; } SaveSettingsToFile(); } private void ToggleSwitchEnableOvertimeCountUp_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.EnableOvertimeCountUp = ToggleSwitchEnableOvertimeCountUp.IsOn; if (!ToggleSwitchEnableOvertimeCountUp.IsOn) { ToggleSwitchEnableOvertimeRedText.IsOn = false; Settings.RandSettings.EnableOvertimeRedText = false; } SaveSettingsToFile(); } private void ToggleSwitchEnableOvertimeRedText_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; if (ToggleSwitchEnableOvertimeRedText.IsOn && !ToggleSwitchEnableOvertimeCountUp.IsOn) { ToggleSwitchEnableOvertimeCountUp.IsOn = true; Settings.RandSettings.EnableOvertimeCountUp = true; } Settings.RandSettings.EnableOvertimeRedText = ToggleSwitchEnableOvertimeRedText.IsOn; SaveSettingsToFile(); } private void TimerVolumeSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.TimerVolume = TimerVolumeSlider.Value; SaveSettingsToFile(); } private void ToggleSwitchEnableProgressiveReminder_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.EnableProgressiveReminder = ToggleSwitchEnableProgressiveReminder.IsOn; SaveSettingsToFile(); } // 新点名UI设置事件处理 private void ToggleSwitchUseNewRollCallUI_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.UseNewRollCallUI = ToggleSwitchUseNewRollCallUI.IsOn; SaveSettingsToFile(); } private void ToggleSwitchEnableMLAvoidance_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.EnableMLAvoidance = ToggleSwitchEnableMLAvoidance.IsOn; SaveSettingsToFile(); } private void MLAvoidanceHistorySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.MLAvoidanceHistoryCount = (int)MLAvoidanceHistorySlider.Value; SaveSettingsToFile(); } private void MLAvoidanceWeightSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.MLAvoidanceWeight = MLAvoidanceWeightSlider.Value; SaveSettingsToFile(); } private void ProgressiveReminderVolumeSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.ProgressiveReminderVolume = ProgressiveReminderVolumeSlider.Value; SaveSettingsToFile(); } private void ButtonSelectCustomProgressiveReminderSound_Click(object sender, RoutedEventArgs e) { Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog { Title = "选择渐进提醒音频文件", Filter = "音频文件 (*.wav)|*.wav|所有文件 (*.*)|*.*", DefaultExt = "wav" }; if (openFileDialog.ShowDialog() == true) { Settings.RandSettings.ProgressiveReminderSoundPath = openFileDialog.FileName; SaveSettingsToFile(); } } private void ButtonResetProgressiveReminderSound_Click(object sender, RoutedEventArgs e) { Settings.RandSettings.ProgressiveReminderSoundPath = ""; SaveSettingsToFile(); } private void ButtonSelectCustomTimerSound_Click(object sender, RoutedEventArgs e) { Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog { Title = "选择计时器提醒铃声", Filter = "音频文件 (*.wav)|*.wav|所有文件 (*.*)|*.*", DefaultExt = "wav" }; if (openFileDialog.ShowDialog() == true) { Settings.RandSettings.CustomTimerSoundPath = openFileDialog.FileName; SaveSettingsToFile(); MessageBox.Show("自定义铃声设置成功!", "设置成功", MessageBoxButton.OK, MessageBoxImage.Information); } } private void ButtonResetTimerSound_Click(object sender, RoutedEventArgs e) { Settings.RandSettings.CustomTimerSoundPath = ""; SaveSettingsToFile(); MessageBox.Show("已重置为默认铃声!", "重置成功", MessageBoxButton.OK, MessageBoxImage.Information); } private void ToggleSwitchShowRandomAndSingleDraw_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; // 获取开关状态并保存到设置中 bool isToggled = ToggleSwitchShowRandomAndSingleDraw.IsOn; Settings.RandSettings.ShowRandomAndSingleDraw = isToggled; // 更新UI显示 BoardRandomDrawToolBtn.Visibility = isToggled ? Visibility.Visible : Visibility.Collapsed; BoardSingleDrawToolBtn.Visibility = isToggled ? Visibility.Visible : Visibility.Collapsed; // 保存设置到文件 SaveSettingsToFile(); } private void ToggleSwitchEnableQuickDraw_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; // 获取开关状态并保存到设置中 Settings.RandSettings.EnableQuickDraw = ToggleSwitchEnableQuickDraw.IsOn; // 保存设置到文件 SaveSettingsToFile(); // 根据设置状态显示或隐藏快抽悬浮按钮 ShowQuickDrawFloatingButton(); } private void ToggleSwitchExternalCaller_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; // 获取开关状态并保存到设置中 Settings.RandSettings.DirectCallCiRand = ToggleSwitchExternalCaller.IsOn; // 保存设置到文件 SaveSettingsToFile(); } private void ComboBoxExternalCallerType_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded) return; // 获取下拉框选择并保存到设置中 Settings.RandSettings.ExternalCallerType = ComboBoxExternalCallerType.SelectedIndex; // 保存设置到文件 SaveSettingsToFile(); } public void UpdateFloatingBarIcons() { string currentMode = GetCurrentSelectedMode(); bool isCursorSolid = currentMode == "cursor"; bool isPenSolid = currentMode == "pen" || currentMode == "color"; bool isCircleEraserSolid = currentMode == "eraser"; bool isStrokeEraserSolid = currentMode == "eraserByStrokes"; bool isLassoSolid = currentMode == "select"; if (Settings.Appearance.UseLegacyFloatingBarUI) { Cursor_Icon.Icon.Geometry = Geometry.Parse( isCursorSolid ? XamlGraphicsIconGeometries.LegacySolidCursorIcon : XamlGraphicsIconGeometries.LegacyLinedCursorIcon); Pen_Icon.Icon.Geometry = Geometry.Parse( isPenSolid ? XamlGraphicsIconGeometries.LegacySolidPenIcon : XamlGraphicsIconGeometries.LegacyLinedPenIcon); EraserByStrokes_Icon.Icon.Geometry = Geometry.Parse( isStrokeEraserSolid ? XamlGraphicsIconGeometries.LegacySolidEraserStrokeIcon : XamlGraphicsIconGeometries.LegacyLinedEraserStrokeIcon); Eraser_Icon.Icon.Geometry = Geometry.Parse( isCircleEraserSolid ? XamlGraphicsIconGeometries.LegacySolidEraserCircleIcon : XamlGraphicsIconGeometries.LegacyLinedEraserCircleIcon); SymbolIconSelect.Icon.Geometry = Geometry.Parse( isLassoSolid ? XamlGraphicsIconGeometries.LegacySolidLassoSelectIcon : XamlGraphicsIconGeometries.LegacyLinedLassoSelectIcon); } else { Cursor_Icon.Icon.Geometry = Geometry.Parse( isCursorSolid ? XamlGraphicsIconGeometries.SolidCursorIcon : XamlGraphicsIconGeometries.LinedCursorIcon); Pen_Icon.Icon.Geometry = Geometry.Parse( isPenSolid ? XamlGraphicsIconGeometries.SolidPenIcon : XamlGraphicsIconGeometries.LinedPenIcon); EraserByStrokes_Icon.Icon.Geometry = Geometry.Parse( isStrokeEraserSolid ? XamlGraphicsIconGeometries.SolidEraserStrokeIcon : XamlGraphicsIconGeometries.LinedEraserStrokeIcon); Eraser_Icon.Icon.Geometry = Geometry.Parse( isCircleEraserSolid ? XamlGraphicsIconGeometries.SolidEraserCircleIcon : XamlGraphicsIconGeometries.LinedEraserCircleIcon); SymbolIconSelect.Icon.Geometry = Geometry.Parse( isLassoSolid ? XamlGraphicsIconGeometries.SolidLassoSelectIcon : XamlGraphicsIconGeometries.LinedLassoSelectIcon); } } public string GetCorrectIcon(string iconType, bool isSolid = false) { if (Settings.Appearance.UseLegacyFloatingBarUI) { // 使用老版图标 switch (iconType) { case "cursor": return isSolid ? XamlGraphicsIconGeometries.LegacySolidCursorIcon : XamlGraphicsIconGeometries.LegacyLinedCursorIcon; case "pen": return isSolid ? XamlGraphicsIconGeometries.LegacySolidPenIcon : XamlGraphicsIconGeometries.LegacyLinedPenIcon; case "eraserStroke": return isSolid ? XamlGraphicsIconGeometries.LegacySolidEraserStrokeIcon : XamlGraphicsIconGeometries.LegacyLinedEraserStrokeIcon; case "eraserCircle": return isSolid ? XamlGraphicsIconGeometries.LegacySolidEraserCircleIcon : XamlGraphicsIconGeometries.LegacyLinedEraserCircleIcon; case "lassoSelect": return isSolid ? XamlGraphicsIconGeometries.LegacySolidLassoSelectIcon : XamlGraphicsIconGeometries.LegacyLinedLassoSelectIcon; } } else { // 使用新版图标 switch (iconType) { case "cursor": return isSolid ? XamlGraphicsIconGeometries.SolidCursorIcon : XamlGraphicsIconGeometries.LinedCursorIcon; case "pen": return isSolid ? XamlGraphicsIconGeometries.SolidPenIcon : XamlGraphicsIconGeometries.LinedPenIcon; case "eraserStroke": return isSolid ? XamlGraphicsIconGeometries.SolidEraserStrokeIcon : XamlGraphicsIconGeometries.LinedEraserStrokeIcon; case "eraserCircle": return isSolid ? XamlGraphicsIconGeometries.SolidEraserCircleIcon : XamlGraphicsIconGeometries.LinedEraserCircleIcon; case "lassoSelect": return isSolid ? XamlGraphicsIconGeometries.SolidLassoSelectIcon : XamlGraphicsIconGeometries.LinedLassoSelectIcon; } } return ""; } #endregion #region 浮动栏按钮显示控制 private void CheckBoxUseLegacyFloatingBarUI_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarIcons(); SaveSettingsToFile(); } private void CheckBoxUseLegacyFloatingBarUI_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarIcons(); SaveSettingsToFile(); } private void CheckBoxShowShapeButton_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowShapeButton_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowUndoButton_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowUndoButton_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowRedoButton_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowRedoButton_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowClearButton_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowClearButton_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowWhiteboardButton_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowWhiteboardButton_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowLassoSelectButton_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowLassoSelectButton_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowClearAndMouseButton_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowClearAndMouseButton_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowHideButton_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowHideButton_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowQuickColorPalette_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void CheckBoxShowQuickColorPalette_Unchecked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void ComboBoxQuickColorPaletteDisplayMode_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void ComboBoxEraserDisplayOption_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded) return; UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } private void UpdateFloatingBarButtonsVisibility() { // 根据设置更新浮动栏按钮的可见性 try { // 形状按钮 if (ShapeDrawFloatingBarBtn != null) ShapeDrawFloatingBarBtn.Visibility = Settings.Appearance.IsShowShapeButton ? Visibility.Visible : Visibility.Collapsed; // 撤销按钮 if (SymbolIconUndo != null) SymbolIconUndo.Visibility = Settings.Appearance.IsShowUndoButton ? Visibility.Visible : Visibility.Collapsed; // 重做按钮 if (SymbolIconRedo != null) SymbolIconRedo.Visibility = Settings.Appearance.IsShowRedoButton ? Visibility.Visible : Visibility.Collapsed; // 清空按钮 if (SymbolIconDelete != null) SymbolIconDelete.Visibility = Settings.Appearance.IsShowClearButton ? Visibility.Visible : Visibility.Collapsed; // 白板按钮 if (WhiteboardFloatingBarBtn != null) WhiteboardFloatingBarBtn.Visibility = Settings.Appearance.IsShowWhiteboardButton ? Visibility.Visible : Visibility.Collapsed; // 隐藏按钮 if (Fold_Icon != null) Fold_Icon.Visibility = Settings.Appearance.IsShowHideButton ? Visibility.Visible : Visibility.Collapsed; // 快捷调色盘 if (QuickColorPalettePanel != null && QuickColorPaletteSingleRowPanel != null) { bool shouldShow = Settings.Appearance.IsShowQuickColorPalette && inkCanvas.EditingMode == InkCanvasEditingMode.Ink; bool wasVisible = QuickColorPalettePanel.Visibility == Visibility.Visible || QuickColorPaletteSingleRowPanel.Visibility == Visibility.Visible; if (shouldShow) { // 根据显示模式选择显示哪个面板 if (Settings.Appearance.QuickColorPaletteDisplayMode == 0) { // 单行显示模式 QuickColorPalettePanel.Visibility = Visibility.Collapsed; QuickColorPaletteSingleRowPanel.Visibility = Visibility.Visible; } else { // 双行显示模式 QuickColorPalettePanel.Visibility = Visibility.Visible; QuickColorPaletteSingleRowPanel.Visibility = Visibility.Collapsed; } } else { QuickColorPalettePanel.Visibility = Visibility.Collapsed; QuickColorPaletteSingleRowPanel.Visibility = Visibility.Collapsed; } // 如果快捷调色盘的可见性发生变化,重新计算浮动栏位置 if (wasVisible != shouldShow && !isFloatingBarFolded) { if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) ViewboxFloatingBarMarginAnimation(60); { // 根据显示模式调整动画参数 if (Settings.Appearance.QuickColorPaletteDisplayMode == 0) { // 单行显示模式,动画参数较小 ViewboxFloatingBarMarginAnimation(60, true); } else { // 双行显示模式,动画参数较大 ViewboxFloatingBarMarginAnimation(100, true); } } } } // 套索选择按钮 if (SymbolIconSelect != null) SymbolIconSelect.Visibility = Settings.Appearance.IsShowLassoSelectButton ? Visibility.Visible : Visibility.Collapsed; // 清并鼠按钮 if (CursorWithDelFloatingBarBtn != null) CursorWithDelFloatingBarBtn.Visibility = Settings.Appearance.IsShowClearAndMouseButton ? Visibility.Visible : Visibility.Collapsed; // 橡皮按钮显示控制 if (Eraser_Icon != null && EraserByStrokes_Icon != null) { switch (Settings.Appearance.EraserDisplayOption) { case 0: // 两个都显示 Eraser_Icon.Visibility = Visibility.Visible; EraserByStrokes_Icon.Visibility = Visibility.Visible; break; case 1: // 仅显示面积擦 Eraser_Icon.Visibility = Visibility.Visible; EraserByStrokes_Icon.Visibility = Visibility.Collapsed; break; case 2: // 仅显示线擦 Eraser_Icon.Visibility = Visibility.Collapsed; EraserByStrokes_Icon.Visibility = Visibility.Visible; break; case 3: // 都不显示 Eraser_Icon.Visibility = Visibility.Collapsed; EraserByStrokes_Icon.Visibility = Visibility.Collapsed; break; } } // 在按钮可见性更新后,重新计算当前高光位置 // 延迟执行以确保UI更新完成 Dispatcher.BeginInvoke(new Action(async () => { try { // 等待UI完全更新 await Task.Delay(100); // 获取当前选中的模式并重新设置高光位置 string selectedToolMode = GetCurrentSelectedMode(); if (!string.IsNullOrEmpty(selectedToolMode)) { SetFloatingBarHighlightPosition(selectedToolMode); } // 重新计算浮动栏位置,因为按钮可见性变化会影响浮动栏宽度 if (currentMode == 0) // 只在屏幕模式下重新计算浮动栏位置 { if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) { ViewboxFloatingBarMarginAnimation(60); } else { ViewboxFloatingBarMarginAnimation(100, true); } } } catch (Exception ex) { LogHelper.WriteLogToFile($"重新计算高光位置和浮动栏位置失败: {ex.Message}", LogHelper.LogType.Error); } }), DispatcherPriority.Loaded); } catch (Exception ex) { LogHelper.WriteLogToFile($"更新浮动栏按钮可见性时出错: {ex.Message}", LogHelper.LogType.Error); } } #endregion /// /// 将当前内存中的 Settings 序列化为格式化的 JSON 并写入应用程序配置文件(位于 App.RootPath 下的 Configs 目录或根设置文件)。 /// /// /// 在写入前会确保目标目录/文件具有写入权限(使用 ProcessProtectionManager)。任何写入失败或异常都会被吞掉,调用方不会收到异常抛出。 /// public static void SaveSettingsToFile() => SettingsManager.SaveSettingsToFile(); private void SCManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e) { e.Handled = true; } private void HyperlinkSourceToICCRepository_Click(object sender, RoutedEventArgs e) { Process.Start("https://gitea.bliemhax.com/kriastans/InkCanvasForClass"); HideSubPanels(); } private void HyperlinkSourceToPresentRepository_Click(object sender, RoutedEventArgs e) { Process.Start("https://github.com/ChangSakura/Ink-Canvas"); HideSubPanels(); } private void HyperlinkSourceToOringinalRepository_Click(object sender, RoutedEventArgs e) { Process.Start("https://github.com/WXRIW/Ink-Canvas"); HideSubPanels(); } private void UpdatePackageArchitectureSelector_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; if (_isChangingUpdatePackageArchInternally) return; if (!(sender is RadioButton radioButton) || radioButton.Tag == null) return; var newArch = string.Equals(radioButton.Tag.ToString(), "X64", StringComparison.OrdinalIgnoreCase) ? UpdatePackageArchitecture.X64 : UpdatePackageArchitecture.X86; if (Settings.Startup.UpdatePackageArchitecture == newArch) return; Settings.Startup.UpdatePackageArchitecture = newArch; SaveSettingsToFile(); LogHelper.WriteLogToFile($"Settings | Update package architecture: {newArch}"); } // 自定义点名背景相关方法 public void UpdatePickNameBackgroundsInComboBox() { // 清除现有的自定义背景选项 if (ComboBoxPickNameBackground != null) { // 保留第一个默认选项 while (ComboBoxPickNameBackground.Items.Count > 1) { ComboBoxPickNameBackground.Items.RemoveAt(ComboBoxPickNameBackground.Items.Count - 1); } // 添加自定义背景选项 foreach (var background in Settings.RandSettings.CustomPickNameBackgrounds) { ComboBoxItem item = new ComboBoxItem(); item.Content = background.Name; item.FontFamily = new FontFamily("Microsoft YaHei UI"); ComboBoxPickNameBackground.Items.Add(item); } } } public void UpdatePickNameBackgroundDisplay() { // 此方法主要用于在外部窗口更改背景后更新UI if (ComboBoxPickNameBackground != null) { ComboBoxPickNameBackground.SelectedIndex = Settings.RandSettings.SelectedBackgroundIndex; } } private void ComboBoxPickNameBackground_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded) return; Settings.RandSettings.SelectedBackgroundIndex = ComboBoxPickNameBackground.SelectedIndex; SaveSettingsToFile(); } private void ButtonAddCustomBackground_Click(object sender, RoutedEventArgs e) { AddPickNameBackgroundWindow dialog = new AddPickNameBackgroundWindow(this); dialog.Owner = this; dialog.ShowDialog(); if (dialog.IsSuccess) { // 自动选中新添加的背景 ComboBoxPickNameBackground.SelectedIndex = ComboBoxPickNameBackground.Items.Count - 1; } } private void ButtonManageBackgrounds_Click(object sender, RoutedEventArgs e) { ManagePickNameBackgroundsWindow dialog = new ManagePickNameBackgroundsWindow(this); dialog.Owner = this; dialog.ShowDialog(); } private void ToggleSwitchEnableWppProcessKill_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchAutoFoldAfterPPTSlideShow_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchKeepFoldAfterSoftwareExit_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchAlwaysGoToFirstPageOnReenter_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchAutoEnterAnnotationAfterKillHite_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } private void ToggleSwitchEnablePalmEraser_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } #region 底部按钮水平位置控制 private void PPTButtonLBPositionValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); UpdatePPTUIManagerSettings(); SliderDelayAction.DebounceAction(2000, null, SaveSettingsToFile); UpdatePPTBtnPreview(); } private void PPTButtonRBPositionValueSlider_ValueChanged(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); UpdatePPTUIManagerSettings(); SliderDelayAction.DebounceAction(2000, null, SaveSettingsToFile); UpdatePPTBtnPreview(); } private void PPTBtnLBPlusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnLBMinusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnLBSyncBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnLBResetBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); Settings.PowerPointSettings.PPTLBButtonPosition = 0; SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnRBPlusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnRBMinusBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnRBSyncBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; UpdatePPTBtnSlidersStatus(); SaveSettingsToFile(); UpdatePPTBtnPreview(); } private void PPTBtnRBResetBtn_Clicked(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.PowerPointSettings.PPTRBButtonPosition = 0; SaveSettingsToFile(); UpdatePPTBtnPreview(); } #endregion private void ComboBoxPalmEraserSensitivity_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!isLoaded) return; SaveSettingsToFile(); } #region 文件关联管理 private void BtnUnregisterFileAssociation_Click(object sender, RoutedEventArgs e) { try { bool success = FileAssociationManager.UnregisterFileAssociation(); if (success) { ShowNotification("文件关联已取消"); } else { ShowNotification("取消文件关联失败"); } } catch (Exception ex) { LogHelper.WriteLogToFile($"取消文件关联时出错: {ex.Message}", LogHelper.LogType.Error); } } private void BtnCheckFileAssociation_Click(object sender, RoutedEventArgs e) { try { bool isRegistered = FileAssociationManager.IsFileAssociationRegistered(); if (isRegistered) { } else { } } catch (Exception ex) { LogHelper.WriteLogToFile($"检查文件关联状态时出错: {ex.Message}", LogHelper.LogType.Error); } } private void BtnRegisterFileAssociation_Click(object sender, RoutedEventArgs e) { try { bool success = FileAssociationManager.RegisterFileAssociation(); if (success) { ShowNotification("文件关联已注册"); } else { ShowNotification("注册文件关联失败"); } } catch (Exception ex) { LogHelper.WriteLogToFile($"注册文件关联时出错: {ex.Message}", LogHelper.LogType.Error); } } #endregion } }