From ac399773d04ecfc6f2f0f543e85318c2a32f08d8 Mon Sep 17 00:00:00 2001
From: CJKmkp <2564608840@qq.com>
Date: Fri, 1 May 2026 01:49:56 +0800
Subject: [PATCH] improve:OOBE
---
Ink Canvas/Windows/OobeWindow.xaml | 1045 +++++++++++--------------
Ink Canvas/Windows/OobeWindow.xaml.cs | 724 ++++++++---------
2 files changed, 792 insertions(+), 977 deletions(-)
diff --git a/Ink Canvas/Windows/OobeWindow.xaml b/Ink Canvas/Windows/OobeWindow.xaml
index eb2ad467..7161dc56 100644
--- a/Ink Canvas/Windows/OobeWindow.xaml
+++ b/Ink Canvas/Windows/OobeWindow.xaml
@@ -5,16 +5,17 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
+ xmlns:controls="clr-namespace:Ink_Canvas.Controls;assembly=InkCanvas.Controls"
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="欢迎使用 InkCanvasForClass"
- Height="480"
- Width="800"
- MinHeight="300"
- MinWidth="400"
+ Height="660"
+ Width="980"
+ MinHeight="460"
+ MinWidth="760"
WindowStartupLocation="CenterScreen"
ResizeMode="CanResize"
Topmost="True"
- Background="{DynamicResource SettingsPageBackground}"
Loaded="OobeWindow_OnLoaded"
ui:ThemeManager.IsThemeAware="True"
ui:TitleBar.ExtendViewIntoTitleBar="True"
@@ -23,607 +24,499 @@
ui:TitleBar.Height="48">
-
+
+
+
+
+
+
-
+ 4
+
+
+
+
+
-
-
+
+
+
+
-
+
-
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 隐私说明:本软件不会收集课堂内容、学生个人信息或可识别您的原始墨迹内容,详情可查看安装目录中的 privacy.txt。
-
-
-
- 启动与更新选项(对应 设置 → 启动)
-
-
-
-
-
-
-
-
-
-
- 画笔光标、压感、墨迹显示等可在 设置 → 画板和墨迹 中修改。
-
-
-
-
-
-
-
-
-
-
-
- 双指缩放、平移、旋转及手掌擦等可在 设置 → 手势操作 中修改。
-
-
-
-
-
-
-
-
-
-
-
-
- 手绘图形识别为标准形状等可在 设置 → 墨迹纠正 中修改。
-
-
-
-
-
-
-
-
-
- 主题、启动动画、托盘图标等均可在 设置 → 外观 中修改。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 具体快捷键可在 设置 → 快捷键设置 中配置。
-
-
-
-
-
-
-
-
-
- 发生未处理异常时的行为可在 设置 → 崩溃处理 中修改。
-
-
-
-
-
-
-
-
-
-
-
-
- 以下选项均可在 设置 → PPT 中修改,用于与 PowerPoint/WPS 放映联动。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 进入/退出特定软件时自动收纳、墨迹自动保存、悬浮窗拦截等可在 设置 → 自动化行为 中修改。
-
-
-
-
-
-
-
-
-
-
-
- 点名窗口样式与行为可在 设置 → 随机点名 中修改。
-
-
-
-
-
-
-
-
-
- 日志、特殊屏幕、窗口模式等可在 设置 → 高级选项 中修改。
-
-
-
-
-
-
-
-
-
- 清屏截图、按日期保存等可在 设置 → 截图和屏幕捕捉 中修改。
-
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
- 此向导仅在首次启动时出现;之后可在 设置 中按侧边栏分区修改对应选项。
-
+ Margin="0,0,16,0"
+ Style="{DynamicResource CaptionTextBlockStyle}"
+ Opacity="0.7"
+ Text="1 / 12" />
+ Click="BtnPreviousStep_Click">
+
+
+
+
+
+ Style="{DynamicResource AccentButtonStyle}"
+ Click="BtnConfirm_Click">
+
+
+
+
+
-
+
-
-
+
\ No newline at end of file
diff --git a/Ink Canvas/Windows/OobeWindow.xaml.cs b/Ink Canvas/Windows/OobeWindow.xaml.cs
index 42eca683..d3de118f 100644
--- a/Ink Canvas/Windows/OobeWindow.xaml.cs
+++ b/Ink Canvas/Windows/OobeWindow.xaml.cs
@@ -1,22 +1,27 @@
+using iNKORE.UI.WPF.Modern.Common.IconKeys;
using System;
using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
namespace Ink_Canvas.Windows
{
///
- /// 首次启动体验(OOBE)窗口,用于引导用户选择遥测与隐私设置。
+ /// 首次启动体验(OOBE)窗口,使用与设置窗口一致的卡片化 UI 引导用户完成初始配置。
+ /// 切换步骤时使用横向滑动 + 淡入,模仿 ClassIsland 的设置向导动画风格。
///
public partial class OobeWindow : Window
{
private readonly Settings _settings;
private int _currentStep = 0;
private const int MaxStepIndex = 11;
+ private const int StepCount = 12;
+
+ private FrameworkElement[] _stepPanels;
+ private static readonly TimeSpan SlideDuration = TimeSpan.FromMilliseconds(280);
+ private static readonly IEasingFunction SlideEase = new CubicEase { EasingMode = EasingMode.EaseOut };
- ///
- /// 初始化 OobeWindow,并使用指定的 Settings 填充初始状态与界面。
- ///
- /// 用于读取和写入用户首选项的 Settings 实例。
- /// 当 为 null 时抛出。
public OobeWindow(Settings settings)
{
if (settings == null) throw new ArgumentNullException(nameof(settings));
@@ -24,598 +29,515 @@ namespace Ink_Canvas.Windows
_settings = settings;
InitializeComponent();
- // 初始时设置为透明,等待加载完成后淡入
Opacity = 0;
+ _stepPanels = new FrameworkElement[]
+ {
+ StepTelemetryPanel,
+ StepCanvasPanel,
+ StepGesturesPanel,
+ StepInkRecognitionPanel,
+ StepAppearancePanel,
+ StepShortcutsPanel,
+ StepCrashActionPanel,
+ StepPptPanel,
+ StepAutomationPanel,
+ StepLuckyRandomPanel,
+ StepAdvancedPanel,
+ StepSnapshotPanel,
+ };
+
InitializeFromSettings();
- UpdateStepUI();
+ UpdateStepUI(animateDirection: 0, instant: true);
}
- ///
- /// 从当前 Settings 对象将相关首选项映射并回显到各个 OOBE 界面控件中,以反映用户已保存的配置状态。
- ///
- ///
- /// 对各个配置分组(外观、启动、托盘、PPT、画板、手势、墨迹纠正、快捷键、崩溃处理、自动化、随机点名、高级选项、截图等)分别进行读取并更新对应控件的选中/选项状态;在初始化每个分组时会捕获并忽略异常,避免单个分组的错误影响窗口启动流程。
- ///
+ #region Settings IO
+
private void InitializeFromSettings()
{
- // 根据当前设置回显遥测选项
- switch (_settings.Startup.TelemetryUploadLevel)
- {
- case TelemetryUploadLevel.Basic:
- RadioTelemetryBasic.IsChecked = true;
- break;
- case TelemetryUploadLevel.Extended:
- RadioTelemetryExtended.IsChecked = true;
- break;
- case TelemetryUploadLevel.None:
- default:
- RadioTelemetryNone.IsChecked = true;
- break;
- }
-
- // 主题与外观设置
- try
- {
- if (_settings.Appearance != null)
- {
- switch (_settings.Appearance.Theme)
- {
- case 0: // 浅色
- RadioThemeLight.IsChecked = true;
- break;
- case 1: // 深色
- RadioThemeDark.IsChecked = true;
- break;
- case 2: // 跟随系统
- default:
- RadioThemeFollowSystem.IsChecked = true;
- break;
- }
-
- CheckBoxEnableSplashScreen.IsChecked = _settings.Appearance.EnableSplashScreen;
- }
- }
- catch
- {
- // 忽略外观初始化异常,避免影响启动
- }
-
- // 启动行为设置
try
{
if (_settings.Startup != null)
{
- CheckBoxFoldAtStartup.IsChecked = _settings.Startup.IsFoldAtStartup;
- CheckBoxAutoUpdate.IsChecked = _settings.Startup.IsAutoUpdate;
+ ComboBoxTelemetryUploadLevel.SelectedIndex = (int)_settings.Startup.TelemetryUploadLevel;
+ CardFoldAtStartup.IsOn = _settings.Startup.IsFoldAtStartup;
+ CardAutoUpdate.IsOn = _settings.Startup.IsAutoUpdate;
+ ComboBoxCrashAction.SelectedIndex = _settings.Startup.CrashAction == 0 ? 0 : 1;
+ CheckBoxPrivacyAccepted.IsChecked = _settings.Startup.HasAcceptedTelemetryPrivacy;
}
}
- catch
- {
- // 忽略启动行为初始化异常
- }
+ catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 托盘与快速面板
- try
- {
- if (_settings.Appearance != null)
- {
- CheckBoxEnableTrayIcon.IsChecked = _settings.Appearance.EnableTrayIcon;
- CheckBoxShowQuickPanel.IsChecked = _settings.Appearance.IsShowQuickPanel;
- }
- }
- catch
- {
- // 忽略托盘/快速面板初始化异常
- }
-
- // PPT 联动
- try
- {
- if (_settings.PowerPointSettings != null)
- {
- CheckBoxPptSupport.IsChecked = _settings.PowerPointSettings.PowerPointSupport;
- CheckBoxPptAutoSaveStrokes.IsChecked = _settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint;
- CheckBoxPptAutoSaveScreenshots.IsChecked = _settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint;
- CheckBoxPptTimeCapsule.IsChecked = _settings.PowerPointSettings.EnablePPTTimeCapsule;
- }
- }
- catch
- {
- // 忽略 PPT 联动初始化异常
- }
-
- // 画板和墨迹
try
{
if (_settings.Canvas != null)
{
- CheckBoxShowCursor.IsChecked = _settings.Canvas.IsShowCursor;
- CheckBoxDisablePressure.IsChecked = _settings.Canvas.DisablePressure;
- CheckBoxHideStrokeWhenSelecting.IsChecked = _settings.Canvas.HideStrokeWhenSelecting;
+ CardShowCursor.IsOn = _settings.Canvas.IsShowCursor;
+ CardDisablePressure.IsOn = _settings.Canvas.DisablePressure;
+ CardHideStrokeWhenSelecting.IsOn = _settings.Canvas.HideStrokeWhenSelecting;
+ CardEnablePalmEraser.IsOn = _settings.Canvas.EnablePalmEraser;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 手势操作
try
{
if (_settings.Gesture != null)
{
- CheckBoxTwoFingerZoom.IsChecked = _settings.Gesture.IsEnableTwoFingerZoom;
- CheckBoxTwoFingerTranslate.IsChecked = _settings.Gesture.IsEnableTwoFingerTranslate;
- CheckBoxAutoSwitchTwoFingerGesture.IsChecked = _settings.Gesture.AutoSwitchTwoFingerGesture;
- CheckBoxEnablePalmEraser.IsChecked = _settings.Canvas != null && _settings.Canvas.EnablePalmEraser;
+ CardTwoFingerZoom.IsOn = _settings.Gesture.IsEnableTwoFingerZoom;
+ CardTwoFingerTranslate.IsOn = _settings.Gesture.IsEnableTwoFingerTranslate;
+ CardAutoSwitchTwoFingerGesture.IsOn = _settings.Gesture.AutoSwitchTwoFingerGesture;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 墨迹纠正
try
{
if (_settings.InkToShape != null)
{
- CheckBoxInkToShapeEnabled.IsChecked = _settings.InkToShape.IsInkToShapeEnabled;
+ CardInkToShapeEnabled.IsOn = _settings.InkToShape.IsInkToShapeEnabled;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 快捷键(外观)
try
{
if (_settings.Appearance != null)
{
- CheckBoxEnableHotkeysInMouseMode.IsChecked = _settings.Appearance.EnableHotkeysInMouseMode;
+ int themeIndex = _settings.Appearance.Theme;
+ if (themeIndex < 0 || themeIndex > 2) themeIndex = 2;
+ ComboBoxTheme.SelectedIndex = themeIndex;
+ CardEnableSplashScreen.IsOn = _settings.Appearance.EnableSplashScreen;
+ CardEnableTrayIcon.IsOn = _settings.Appearance.EnableTrayIcon;
+ CardShowQuickPanel.IsOn = _settings.Appearance.IsShowQuickPanel;
+ CardEnableHotkeysInMouseMode.IsOn = _settings.Appearance.EnableHotkeysInMouseMode;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 崩溃处理
try
{
- RadioCrashSilentRestart.IsChecked = _settings.Startup.CrashAction == 0;
- RadioCrashNoAction.IsChecked = _settings.Startup.CrashAction != 0;
+ if (_settings.PowerPointSettings != null)
+ {
+ CardPptSupport.IsOn = _settings.PowerPointSettings.PowerPointSupport;
+ CardPptAutoSaveStrokes.IsOn = _settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint;
+ CardPptAutoSaveScreenshots.IsOn = _settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint;
+ CardPptTimeCapsule.IsOn = _settings.PowerPointSettings.EnablePPTTimeCapsule;
+ }
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 自动化行为
try
{
if (_settings.Automation != null)
{
- CheckBoxAutoFoldInPPTSlideShow.IsChecked = _settings.Automation.IsAutoFoldInPPTSlideShow;
- CheckBoxEnableAutoSaveStrokes.IsChecked = _settings.Automation.IsEnableAutoSaveStrokes;
+ CardAutoFoldInPPTSlideShow.IsOn = _settings.Automation.IsAutoFoldInPPTSlideShow;
+ CardEnableAutoSaveStrokes.IsOn = _settings.Automation.IsEnableAutoSaveStrokes;
if (_settings.Automation.FloatingWindowInterceptor != null)
{
- CheckBoxFloatingWindowInterceptorEnabled.IsChecked = _settings.Automation.FloatingWindowInterceptor.IsEnabled;
+ CardFloatingWindowInterceptor.IsOn = _settings.Automation.FloatingWindowInterceptor.IsEnabled;
}
+ CardAutoSaveStrokesAtClear.IsOn = _settings.Automation.IsAutoSaveStrokesAtClear;
+ CardSaveScreenshotsInDateFolders.IsOn = _settings.Automation.IsSaveScreenshotsInDateFolders;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 随机点名
try
{
if (_settings.RandSettings != null)
{
- CheckBoxShowRandomAndSingleDraw.IsChecked = _settings.RandSettings.ShowRandomAndSingleDraw;
+ CardShowRandomAndSingleDraw.IsOn = _settings.RandSettings.ShowRandomAndSingleDraw;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 高级选项
try
{
if (_settings.Advanced != null)
{
- CheckBoxIsLogEnabled.IsChecked = _settings.Advanced.IsLogEnabled;
- }
- }
- catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
-
- // 截图(自动化中的截图相关)
- try
- {
- if (_settings.Automation != null)
- {
- CheckBoxAutoSaveStrokesAtClear.IsChecked = _settings.Automation.IsAutoSaveStrokesAtClear;
- CheckBoxSaveScreenshotsInDateFolders.IsChecked = _settings.Automation.IsSaveScreenshotsInDateFolders;
+ CardIsLogEnabled.IsOn = _settings.Advanced.IsLogEnabled;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
}
- ///
- /// 将当前界面上用户的选择写回到 Settings 对象并标记已接受遥测隐私说明。
- ///
- ///
- /// 更新的设置包括:启动时的遥测级别、主题与启动外观、启动行为、托盘/快速面板、PowerPoint 联动、画板与墨迹选项、手势设置、墨迹纠正、鼠标模式快捷键、崩溃处理策略、自动化相关设置、随机点名设置以及高级日志选项;操作中对各子配置块采用防护性写回(局部异常被忽略)。方法结束时会将 HasAcceptedTelemetryPrivacy 置为 true。
- ///
private void ApplySelection()
{
- // 将当前遥测选项写回到设置
- if (RadioTelemetryBasic.IsChecked == true)
- {
- _settings.Startup.TelemetryUploadLevel = TelemetryUploadLevel.Basic;
- }
- else if (RadioTelemetryExtended.IsChecked == true)
- {
- _settings.Startup.TelemetryUploadLevel = TelemetryUploadLevel.Extended;
- }
- else
- {
- _settings.Startup.TelemetryUploadLevel = TelemetryUploadLevel.None;
- }
-
- // 写回主题与外观设置
- try
- {
- if (_settings.Appearance != null)
- {
- if (RadioThemeLight.IsChecked == true)
- {
- _settings.Appearance.Theme = 0;
- }
- else if (RadioThemeDark.IsChecked == true)
- {
- _settings.Appearance.Theme = 1;
- }
- else
- {
- // 默认视为跟随系统
- _settings.Appearance.Theme = 2;
- }
-
- _settings.Appearance.EnableSplashScreen = CheckBoxEnableSplashScreen.IsChecked == true;
- }
- }
- catch
- {
- // 忽略外观写回异常
- }
-
- // 写回启动行为设置
try
{
if (_settings.Startup != null)
{
- _settings.Startup.IsFoldAtStartup = CheckBoxFoldAtStartup.IsChecked == true;
- _settings.Startup.IsAutoUpdate = CheckBoxAutoUpdate.IsChecked == true;
+ int level = ComboBoxTelemetryUploadLevel.SelectedIndex;
+ if (level < 0) level = 0;
+ _settings.Startup.TelemetryUploadLevel = (TelemetryUploadLevel)level;
+ _settings.Startup.IsFoldAtStartup = CardFoldAtStartup.IsOn;
+ _settings.Startup.IsAutoUpdate = CardAutoUpdate.IsOn;
+ _settings.Startup.CrashAction = ComboBoxCrashAction.SelectedIndex == 1 ? 1 : 0;
+ _settings.Startup.HasAcceptedTelemetryPrivacy = CheckBoxPrivacyAccepted.IsChecked == true;
}
}
- catch
- {
- // 忽略启动行为写回异常
- }
+ catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 写回托盘与快速面板设置
- try
- {
- if (_settings.Appearance != null)
- {
- _settings.Appearance.EnableTrayIcon = CheckBoxEnableTrayIcon.IsChecked == true;
- _settings.Appearance.IsShowQuickPanel = CheckBoxShowQuickPanel.IsChecked == true;
- }
- }
- catch
- {
- // 忽略托盘/快速面板写回异常
- }
-
- // 写回 PPT 联动设置
- try
- {
- if (_settings.PowerPointSettings != null)
- {
- _settings.PowerPointSettings.PowerPointSupport = CheckBoxPptSupport.IsChecked == true;
- _settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint = CheckBoxPptAutoSaveStrokes.IsChecked == true;
- _settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint = CheckBoxPptAutoSaveScreenshots.IsChecked == true;
- _settings.PowerPointSettings.EnablePPTTimeCapsule = CheckBoxPptTimeCapsule.IsChecked == true;
- }
- }
- catch
- {
- // 忽略 PPT 联动写回异常
- }
-
- // 写回画板和墨迹
try
{
if (_settings.Canvas != null)
{
- _settings.Canvas.IsShowCursor = CheckBoxShowCursor.IsChecked == true;
- _settings.Canvas.DisablePressure = CheckBoxDisablePressure.IsChecked == true;
- _settings.Canvas.HideStrokeWhenSelecting = CheckBoxHideStrokeWhenSelecting.IsChecked == true;
- _settings.Canvas.EnablePalmEraser = CheckBoxEnablePalmEraser.IsChecked == true;
+ _settings.Canvas.IsShowCursor = CardShowCursor.IsOn;
+ _settings.Canvas.DisablePressure = CardDisablePressure.IsOn;
+ _settings.Canvas.HideStrokeWhenSelecting = CardHideStrokeWhenSelecting.IsOn;
+ _settings.Canvas.EnablePalmEraser = CardEnablePalmEraser.IsOn;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 写回手势操作
try
{
if (_settings.Gesture != null)
{
- _settings.Gesture.IsEnableTwoFingerZoom = CheckBoxTwoFingerZoom.IsChecked == true;
- _settings.Gesture.IsEnableTwoFingerTranslate = CheckBoxTwoFingerTranslate.IsChecked == true;
- _settings.Gesture.AutoSwitchTwoFingerGesture = CheckBoxAutoSwitchTwoFingerGesture.IsChecked == true;
+ _settings.Gesture.IsEnableTwoFingerZoom = CardTwoFingerZoom.IsOn;
+ _settings.Gesture.IsEnableTwoFingerTranslate = CardTwoFingerTranslate.IsOn;
+ _settings.Gesture.AutoSwitchTwoFingerGesture = CardAutoSwitchTwoFingerGesture.IsOn;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 写回墨迹纠正
try
{
if (_settings.InkToShape != null)
{
- _settings.InkToShape.IsInkToShapeEnabled = CheckBoxInkToShapeEnabled.IsChecked == true;
+ _settings.InkToShape.IsInkToShapeEnabled = CardInkToShapeEnabled.IsOn;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 写回快捷键(外观)
try
{
if (_settings.Appearance != null)
{
- _settings.Appearance.EnableHotkeysInMouseMode = CheckBoxEnableHotkeysInMouseMode.IsChecked == true;
+ int themeIndex = ComboBoxTheme.SelectedIndex;
+ if (themeIndex < 0) themeIndex = 2;
+ _settings.Appearance.Theme = themeIndex;
+ _settings.Appearance.EnableSplashScreen = CardEnableSplashScreen.IsOn;
+ _settings.Appearance.EnableTrayIcon = CardEnableTrayIcon.IsOn;
+ _settings.Appearance.IsShowQuickPanel = CardShowQuickPanel.IsOn;
+ _settings.Appearance.EnableHotkeysInMouseMode = CardEnableHotkeysInMouseMode.IsOn;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 写回崩溃处理(0=静默重启,1=无操作)
try
{
- _settings.Startup.CrashAction = RadioCrashNoAction.IsChecked == true ? 1 : 0;
+ if (_settings.PowerPointSettings != null)
+ {
+ _settings.PowerPointSettings.PowerPointSupport = CardPptSupport.IsOn;
+ _settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint = CardPptAutoSaveStrokes.IsOn;
+ _settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint = CardPptAutoSaveScreenshots.IsOn;
+ _settings.PowerPointSettings.EnablePPTTimeCapsule = CardPptTimeCapsule.IsOn;
+ }
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 写回自动化行为
try
{
if (_settings.Automation != null)
{
- _settings.Automation.IsAutoFoldInPPTSlideShow = CheckBoxAutoFoldInPPTSlideShow.IsChecked == true;
- _settings.Automation.IsEnableAutoSaveStrokes = CheckBoxEnableAutoSaveStrokes.IsChecked == true;
- _settings.Automation.IsAutoSaveStrokesAtClear = CheckBoxAutoSaveStrokesAtClear.IsChecked == true;
- _settings.Automation.IsSaveScreenshotsInDateFolders = CheckBoxSaveScreenshotsInDateFolders.IsChecked == true;
+ _settings.Automation.IsAutoFoldInPPTSlideShow = CardAutoFoldInPPTSlideShow.IsOn;
+ _settings.Automation.IsEnableAutoSaveStrokes = CardEnableAutoSaveStrokes.IsOn;
+ _settings.Automation.IsAutoSaveStrokesAtClear = CardAutoSaveStrokesAtClear.IsOn;
+ _settings.Automation.IsSaveScreenshotsInDateFolders = CardSaveScreenshotsInDateFolders.IsOn;
if (_settings.Automation.FloatingWindowInterceptor != null)
{
- _settings.Automation.FloatingWindowInterceptor.IsEnabled = CheckBoxFloatingWindowInterceptorEnabled.IsChecked == true;
+ _settings.Automation.FloatingWindowInterceptor.IsEnabled = CardFloatingWindowInterceptor.IsOn;
}
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 写回随机点名
try
{
if (_settings.RandSettings != null)
{
- _settings.RandSettings.ShowRandomAndSingleDraw = CheckBoxShowRandomAndSingleDraw.IsChecked == true;
+ _settings.RandSettings.ShowRandomAndSingleDraw = CardShowRandomAndSingleDraw.IsOn;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
- // 写回高级选项
try
{
if (_settings.Advanced != null)
{
- _settings.Advanced.IsLogEnabled = CheckBoxIsLogEnabled.IsChecked == true;
+ _settings.Advanced.IsLogEnabled = CardIsLogEnabled.IsOn;
}
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
-
- // 标记用户已经阅读并确认过隐私说明
- _settings.Startup.HasAcceptedTelemetryPrivacy = true;
}
- ///
- /// 处理“确认/下一步”按钮的点击:在未到最后一步时前进到下一步,若已是最后一步则应用当前选择并关闭窗口。
- ///
- /// 触发事件的源对象。
- /// 路由事件参数。
+ #endregion
+
+ #region Navigation
+
private void BtnConfirm_Click(object sender, RoutedEventArgs e)
{
- // 如果还没到最后一步,则进入下一步
- if (_currentStep < MaxStepIndex)
+ if (_currentStep == 0 && CheckBoxPrivacyAccepted.IsChecked != true)
{
- _currentStep++;
- UpdateStepUI();
+ MessageBox.Show(this,
+ "请先勾选\"我已阅读并同意《隐私协议》\"后再继续。",
+ "需要同意隐私协议",
+ MessageBoxButton.OK,
+ MessageBoxImage.Information);
+ return;
+ }
+
+ if (_currentStep < MaxStepIndex)
+ {
+ _currentStep++;
+ UpdateStepUI(animateDirection: 1);
return;
}
- // 最后一步:应用选择并关闭窗口
ApplySelection();
DialogResult = true;
Close();
}
- ///
- /// 导航到上一步骤;若已处于第一步(索引为 0)则不做任何操作。
- ///
- /// 触发此事件的源对象。
- /// 事件的路由参数。
private void BtnPreviousStep_Click(object sender, RoutedEventArgs e)
{
if (_currentStep <= 0) return;
_currentStep--;
- UpdateStepUI();
+ UpdateStepUI(animateDirection: -1);
}
- ///
- /// 在窗口加载时对窗口不透明度执行淡入动画以显示窗口。
- ///
- ///
- /// 使用约 220 毫秒的缓出三次方缓动实现淡入;如果动画失败,方法会立即将窗口不透明度设为 1 作为回退。
- ///
+ private void CheckBoxPrivacyAccepted_Changed(object sender, RoutedEventArgs e)
+ {
+ UpdateConfirmEnabled();
+ }
+
+ private bool _privacyDialogShown;
+
+ private void HyperlinkPrivacy_Click(object sender, RoutedEventArgs e)
+ {
+ if (_privacyDialogShown) return;
+ _privacyDialogShown = true;
+ try
+ {
+ var dialog = new PrivacyAgreementWindow { Owner = this };
+ bool? result = dialog.ShowDialog();
+ if (result == true && dialog.UserAccepted)
+ {
+ CheckBoxPrivacyAccepted.IsChecked = true;
+ }
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine(ex);
+ }
+ }
+
+ private void UpdateConfirmEnabled()
+ {
+ if (BtnConfirm == null || CheckBoxPrivacyAccepted == null) return;
+ BtnConfirm.IsEnabled = _currentStep != 0 || CheckBoxPrivacyAccepted.IsChecked == true;
+ }
+
+ #endregion
+
private void OobeWindow_OnLoaded(object sender, RoutedEventArgs e)
{
try
{
- var animation = new System.Windows.Media.Animation.DoubleAnimation
+ var animation = new DoubleAnimation
{
From = 0,
To = 1,
- Duration = TimeSpan.FromMilliseconds(220),
- EasingFunction = new System.Windows.Media.Animation.CubicEase
- {
- EasingMode = System.Windows.Media.Animation.EasingMode.EaseOut
- }
+ Duration = TimeSpan.FromMilliseconds(260),
+ EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
};
-
BeginAnimation(OpacityProperty, animation);
}
catch
{
- // 动画失败时直接显示
Opacity = 1;
}
}
-
-
- ///
- /// 根据当前步骤索引更新向导界面:显示对应步骤面板,播放切换动画,并刷新步骤指示、标题、子标题和按钮文本/可见性。
- ///
- ///
- /// 若更新过程中出现异常会被捕获并忽略以避免中断主流程。
- ///
- private void UpdateStepUI()
+ private void UpdateStepUI(int animateDirection, bool instant = false)
{
try
{
- StepTelemetryPanel.Visibility = _currentStep == 0 ? Visibility.Visible : Visibility.Collapsed;
- StepCanvasPanel.Visibility = _currentStep == 1 ? Visibility.Visible : Visibility.Collapsed;
- StepGesturesPanel.Visibility = _currentStep == 2 ? Visibility.Visible : Visibility.Collapsed;
- StepInkRecognitionPanel.Visibility = _currentStep == 3 ? Visibility.Visible : Visibility.Collapsed;
- StepAppearancePanel.Visibility = _currentStep == 4 ? Visibility.Visible : Visibility.Collapsed;
- StepShortcutsPanel.Visibility = _currentStep == 5 ? Visibility.Visible : Visibility.Collapsed;
- StepCrashActionPanel.Visibility = _currentStep == 6 ? Visibility.Visible : Visibility.Collapsed;
- StepPptPanel.Visibility = _currentStep == 7 ? Visibility.Visible : Visibility.Collapsed;
- StepAutomationPanel.Visibility = _currentStep == 8 ? Visibility.Visible : Visibility.Collapsed;
- StepLuckyRandomPanel.Visibility = _currentStep == 9 ? Visibility.Visible : Visibility.Collapsed;
- StepAdvancedPanel.Visibility = _currentStep == 10 ? Visibility.Visible : Visibility.Collapsed;
- StepSnapshotPanel.Visibility = _currentStep == 11 ? Visibility.Visible : Visibility.Collapsed;
-
- FrameworkElement activePanel = null;
- if (_currentStep == 0) activePanel = StepTelemetryPanel;
- else if (_currentStep == 1) activePanel = StepCanvasPanel;
- else if (_currentStep == 2) activePanel = StepGesturesPanel;
- else if (_currentStep == 3) activePanel = StepInkRecognitionPanel;
- else if (_currentStep == 4) activePanel = StepAppearancePanel;
- else if (_currentStep == 5) activePanel = StepShortcutsPanel;
- else if (_currentStep == 6) activePanel = StepCrashActionPanel;
- else if (_currentStep == 7) activePanel = StepPptPanel;
- else if (_currentStep == 8) activePanel = StepAutomationPanel;
- else if (_currentStep == 9) activePanel = StepLuckyRandomPanel;
- else if (_currentStep == 10) activePanel = StepAdvancedPanel;
- else if (_currentStep == 11) activePanel = StepSnapshotPanel;
-
- if (activePanel != null)
+ for (int i = 0; i < _stepPanels.Length; i++)
{
- activePanel.Opacity = 0;
-
- var transform = activePanel.RenderTransform as System.Windows.Media.TranslateTransform;
- if (transform == null)
- {
- transform = new System.Windows.Media.TranslateTransform(0, 12);
- activePanel.RenderTransform = transform;
- }
- else
- {
- transform.Y = 12;
- }
-
- var fade = new System.Windows.Media.Animation.DoubleAnimation
- {
- From = 0,
- To = 1,
- Duration = TimeSpan.FromMilliseconds(200),
- EasingFunction = new System.Windows.Media.Animation.CubicEase
- {
- EasingMode = System.Windows.Media.Animation.EasingMode.EaseOut
- }
- };
-
- var slide = new System.Windows.Media.Animation.DoubleAnimation
- {
- From = 12,
- To = 0,
- Duration = TimeSpan.FromMilliseconds(200),
- EasingFunction = new System.Windows.Media.Animation.CubicEase
- {
- EasingMode = System.Windows.Media.Animation.EasingMode.EaseOut
- }
- };
-
- activePanel.BeginAnimation(OpacityProperty, fade);
- transform.BeginAnimation(System.Windows.Media.TranslateTransform.YProperty, slide);
+ _stepPanels[i].Visibility = i == _currentStep ? Visibility.Visible : Visibility.Collapsed;
}
- StepIndicatorText.Text = $"步骤 {_currentStep + 1} / 12";
-
+ StepIndicatorText.Text = $"步骤 {_currentStep + 1} / {StepCount}";
+ FooterStepText.Text = $"{_currentStep + 1} / {StepCount}";
BtnPreviousStep.Visibility = _currentStep > 0 ? Visibility.Visible : Visibility.Collapsed;
- switch (_currentStep)
- {
- case 0:
- StepTitleText.Text = "启动时行为";
- StepSubtitleText.Text = "遥测、自动更新与启动行为,对应 设置 → 启动时行为、高级 → 遥测。";
- break;
- case 1:
- StepTitleText.Text = "画板和墨迹";
- StepSubtitleText.Text = "画笔光标、压感、墨迹显示,对应 设置 → 画板和墨迹。";
- break;
- case 2:
- StepTitleText.Text = "手势操作";
- StepSubtitleText.Text = "双指缩放/平移、手掌擦等,对应 设置 → 手势操作。";
- break;
- case 3:
- StepTitleText.Text = "墨迹纠正";
- StepSubtitleText.Text = "手绘图形识别为标准形状,对应 设置 → 墨迹纠正。";
- break;
- case 4:
- StepTitleText.Text = "个性化设置";
- StepSubtitleText.Text = "主题、启动动画、托盘与快速工具栏,对应 设置 → 个性化设置。";
- break;
- case 5:
- StepTitleText.Text = "快捷键设置";
- StepSubtitleText.Text = "鼠标模式下全局快捷键,对应 设置 → 快捷键设置。";
- break;
- case 6:
- StepTitleText.Text = "崩溃处理";
- StepSubtitleText.Text = "未处理异常时的行为,对应 设置 → 崩溃处理。";
- break;
- case 7:
- StepTitleText.Text = "PowerPoint 支持";
- StepSubtitleText.Text = "放映联动与墨迹保存等,对应 设置 → PowerPoint 支持。";
- break;
- case 8:
- StepTitleText.Text = "自动化行为";
- StepSubtitleText.Text = "自动收纳、墨迹自动保存等,对应 设置 → 自动化行为。";
- break;
- case 9:
- StepTitleText.Text = "随机点名";
- StepSubtitleText.Text = "点名窗口选项,对应 设置 → 随机点名。";
- break;
- case 10:
- StepTitleText.Text = "高级选项";
- StepSubtitleText.Text = "日志、特殊屏幕等,对应 设置 → 高级选项。";
- break;
- case 11:
- StepTitleText.Text = "截图和屏幕捕捉";
- StepSubtitleText.Text = "清屏截图、按日期保存等,对应 设置 → 截图和屏幕捕捉。";
- break;
- }
+ ApplyStepMeta(_currentStep);
- BtnConfirm.Content = _currentStep == MaxStepIndex ? "保存并开始使用" : "下一步";
+ BtnConfirmText.Text = _currentStep == MaxStepIndex ? "保存并开始使用" : "下一步";
+ BtnConfirmIcon.Icon = _currentStep == MaxStepIndex
+ ? SegoeFluentIcons.Accept
+ : SegoeFluentIcons.ChevronRight;
+
+ UpdateConfirmEnabled();
+
+ if (StepScrollViewer != null) StepScrollViewer.ScrollToTop();
+
+ AnimateProgress(instant);
+
+ if (!instant && animateDirection != 0)
+ {
+ AnimateStepSlide(animateDirection);
+ }
+ else
+ {
+ StepHostTransform.X = 0;
+ StepHost.Opacity = 1;
+ }
}
- catch
+ catch (Exception ex)
{
- // 忽略 UI 更新异常,避免影响主流程
+ System.Diagnostics.Debug.WriteLine(ex);
}
}
+
+ private void ApplyStepMeta(int step)
+ {
+ string title; string subtitle; FontIconData icon;
+ switch (step)
+ {
+ case 0:
+ title = "启动时行为";
+ subtitle = "遥测、自动更新与启动行为,对应 设置 → 启动、隐私。";
+ icon = SegoeFluentIcons.Shield;
+ break;
+ case 1:
+ title = "画板与墨迹";
+ subtitle = "画笔光标、压感、墨迹显示,对应 设置 → 画板。";
+ icon = SegoeFluentIcons.Edit;
+ break;
+ case 2:
+ title = "手势操作";
+ subtitle = "双指缩放/平移、手掌擦等,对应 设置 → 画板。";
+ icon = SegoeFluentIcons.TouchPointer;
+ break;
+ case 3:
+ title = "墨迹纠正";
+ subtitle = "手绘图形识别为标准形状,对应 设置 → 墨迹纠正。";
+ icon = SegoeFluentIcons.Draw;
+ break;
+ case 4:
+ title = "个性化设置";
+ subtitle = "主题、启动动画、托盘与快速面板,对应 设置 → 个性化。";
+ icon = SegoeFluentIcons.Personalize;
+ break;
+ case 5:
+ title = "快捷键";
+ subtitle = "鼠标模式下的全局快捷键,对应 设置 → 个性化。";
+ icon = SegoeFluentIcons.PenWorkspace;
+ break;
+ case 6:
+ title = "崩溃处理";
+ subtitle = "未处理异常时的行为,对应 设置 → 启动。";
+ icon = SegoeFluentIcons.Warning;
+ break;
+ case 7:
+ title = "PowerPoint 联动";
+ subtitle = "放映联动与墨迹保存,对应 设置 → PowerPoint。";
+ icon = SegoeFluentIcons.Slideshow;
+ break;
+ case 8:
+ title = "自动化行为";
+ subtitle = "自动收纳、墨迹自动保存等,对应 设置 → 自动化。";
+ icon = SegoeFluentIcons.Sync;
+ break;
+ case 9:
+ title = "随机点名";
+ subtitle = "点名窗口选项,对应 设置 → 随机点名。";
+ icon = SegoeFluentIcons.People;
+ break;
+ case 10:
+ title = "高级选项";
+ subtitle = "日志等,对应 设置 → 高级。";
+ icon = SegoeFluentIcons.Settings;
+ break;
+ case 11:
+ title = "截图和屏幕捕捉";
+ subtitle = "清屏截图、按日期保存等,对应 设置 → 自动化。";
+ icon = SegoeFluentIcons.Camera;
+ break;
+ default:
+ title = string.Empty; subtitle = string.Empty; icon = SegoeFluentIcons.Home;
+ break;
+ }
+
+ StepTitleText.Text = title;
+ StepSubtitleText.Text = subtitle;
+ StepIcon.Icon = icon;
+ }
+
+ private void AnimateProgress(bool instant)
+ {
+ try
+ {
+ double total = ActualWidth > 0 ? ActualWidth : Width;
+ double trackWidth = Math.Max(0, Math.Min(420, total - 56 * 2 - 320));
+ double progress = (_currentStep + 1) / (double)StepCount;
+ double targetWidth = trackWidth * progress;
+
+ if (instant)
+ {
+ ProgressFill.Width = targetWidth;
+ return;
+ }
+
+ var anim = new DoubleAnimation
+ {
+ To = targetWidth,
+ Duration = TimeSpan.FromMilliseconds(320),
+ EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
+ };
+ ProgressFill.BeginAnimation(WidthProperty, anim);
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine(ex);
+ }
+ }
+
+ private void AnimateStepSlide(int direction)
+ {
+ // direction: 1 = 前进 (新内容从右滑入), -1 = 后退 (从左滑入)
+ double from = direction > 0 ? 36 : -36;
+
+ StepHostTransform.X = from;
+ StepHost.Opacity = 0;
+
+ var slide = new DoubleAnimation
+ {
+ From = from,
+ To = 0,
+ Duration = SlideDuration,
+ EasingFunction = SlideEase
+ };
+ var fade = new DoubleAnimation
+ {
+ From = 0,
+ To = 1,
+ Duration = SlideDuration,
+ EasingFunction = SlideEase
+ };
+
+ StepHostTransform.BeginAnimation(TranslateTransform.XProperty, slide);
+ StepHost.BeginAnimation(OpacityProperty, fade);
+ }
+
+ protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
+ {
+ base.OnRenderSizeChanged(sizeInfo);
+ AnimateProgress(instant: true);
+ }
}
-}
+}
\ No newline at end of file