diff --git a/Ink Canvas/App.xaml.cs b/Ink Canvas/App.xaml.cs index 2e4f8e12..795743fd 100644 --- a/Ink Canvas/App.xaml.cs +++ b/Ink Canvas/App.xaml.cs @@ -1,5 +1,6 @@ using Hardcodet.Wpf.TaskbarNotification; using Ink_Canvas.Helpers; +using Ink_Canvas.Windows; using iNKORE.UI.WPF.Modern.Controls; using Microsoft.Win32; using Newtonsoft.Json; @@ -14,12 +15,14 @@ using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Threading; +using System.Threading.Tasks; using System.Windows; using System.Windows.Forms; using System.Windows.Input; using System.Windows.Threading; using Application = System.Windows.Application; using MessageBox = System.Windows.MessageBox; +using SplashScreen = Ink_Canvas.Windows.SplashScreen; using Timer = System.Threading.Timer; namespace Ink_Canvas @@ -52,6 +55,9 @@ namespace Ink_Canvas private static string lastErrorMessage = string.Empty; // 新增:是否已初始化崩溃监听器 private static bool crashListenersInitialized; + // 新增:启动画面相关 + private static SplashScreen _splashScreen; + private static bool _isSplashScreenShown = false; public App() { @@ -390,6 +396,65 @@ namespace Ink_Canvas return $"{timeSpan.Seconds}秒"; } + public static void ShowSplashScreen() + { + if (_isSplashScreenShown) + { + LogHelper.WriteLogToFile("启动画面已经显示,跳过重复显示"); + return; + } + + try + { + LogHelper.WriteLogToFile("开始创建启动画面..."); + _splashScreen = new SplashScreen(); + LogHelper.WriteLogToFile("启动画面对象创建成功,准备显示..."); + _splashScreen.Show(); + _isSplashScreenShown = true; + LogHelper.WriteLogToFile("启动画面已显示"); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"显示启动画面失败: {ex.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"异常堆栈: {ex.StackTrace}", LogHelper.LogType.Error); + } + } + + // 新增:关闭启动画面 + public static void CloseSplashScreen() + { + if (!_isSplashScreenShown || _splashScreen == null) return; + + try + { + _splashScreen.CloseSplashScreen(); + _isSplashScreenShown = false; + LogHelper.WriteLogToFile("启动画面已关闭"); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"关闭启动画面失败: {ex.Message}", LogHelper.LogType.Error); + } + } + + // 新增:设置启动画面进度 + public static void SetSplashProgress(int progress) + { + if (_splashScreen != null) + { + _splashScreen.SetProgress(progress); + } + } + + // 新增:设置启动画面消息 + public static void SetSplashMessage(string message) + { + if (_splashScreen != null) + { + _splashScreen.SetLoadingMessage(message); + } + } + // 新增:记录崩溃日志 private static void WriteCrashLog(string message) { @@ -484,12 +549,20 @@ namespace Ink_Canvas private TaskbarIcon _taskbar; - void App_Startup(object sender, StartupEventArgs e) + async void App_Startup(object sender, StartupEventArgs e) { // 初始化应用启动时间 appStartTime = DateTime.Now; - /*if (!StoreHelper.IsStoreApp) */ + // 显示启动画面 + ShowSplashScreen(); + SetSplashMessage("正在启动 Ink Canvas..."); + SetSplashProgress(10); + + // 强制刷新UI,确保启动画面显示 + Application.Current.Dispatcher.Invoke(() => { }, DispatcherPriority.Render); + + System.Threading.Thread.Sleep(1000); RootPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version)); @@ -513,6 +586,9 @@ namespace Ink_Canvas } // 在应用启动时自动释放IACore相关DLL + SetSplashMessage("正在初始化组件..."); + SetSplashProgress(20); + await Task.Delay(500); try { IACoreDllExtractor.ExtractIACoreDlls(); @@ -523,6 +599,9 @@ namespace Ink_Canvas } // 记录应用启动(设备标识符) + SetSplashMessage("正在加载配置..."); + SetSplashProgress(40); + await Task.Delay(500); DeviceIdentifier.RecordAppLaunch(); LogHelper.WriteLogToFile($"App | 设备ID: {DeviceIdentifier.GetDeviceId()}"); LogHelper.WriteLogToFile($"App | 使用频率: {DeviceIdentifier.GetUsageFrequency()}"); @@ -750,8 +829,25 @@ namespace Ink_Canvas StartArgs = e.Args; // 在非更新模式下创建主窗口 + SetSplashMessage("正在初始化主界面..."); + SetSplashProgress(80); + await Task.Delay(500); var mainWindow = new MainWindow(); MainWindow = mainWindow; + + // 主窗口加载完成后关闭启动画面 + mainWindow.Loaded += (s, args) => + { + SetSplashMessage("启动完成!"); + SetSplashProgress(100); + + // 延迟关闭启动画面,让用户看到完成消息 + Task.Delay(500).ContinueWith(_ => + { + Dispatcher.Invoke(() => CloseSplashScreen()); + }); + }; + mainWindow.Show(); // 新增:注册.icstk文件关联 diff --git a/Ink Canvas/InkCanvasForClass.csproj b/Ink Canvas/InkCanvasForClass.csproj index 5ff02806..43b92160 100644 --- a/Ink Canvas/InkCanvasForClass.csproj +++ b/Ink Canvas/InkCanvasForClass.csproj @@ -575,6 +575,7 @@ + diff --git a/Ink Canvas/Resources/ICC Start.png b/Ink Canvas/Resources/ICC Start.png new file mode 100644 index 00000000..d21d0dc0 Binary files /dev/null and b/Ink Canvas/Resources/ICC Start.png differ diff --git a/Ink Canvas/Windows/SplashScreen.xaml b/Ink Canvas/Windows/SplashScreen.xaml new file mode 100644 index 00000000..e0ce5480 --- /dev/null +++ b/Ink Canvas/Windows/SplashScreen.xaml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ink Canvas/Windows/SplashScreen.xaml.cs b/Ink Canvas/Windows/SplashScreen.xaml.cs new file mode 100644 index 00000000..320b32ef --- /dev/null +++ b/Ink Canvas/Windows/SplashScreen.xaml.cs @@ -0,0 +1,134 @@ +using System; +using System.Reflection; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media.Animation; +using System.Windows.Threading; + +namespace Ink_Canvas.Windows +{ + /// + /// SplashScreen.xaml 的交互逻辑 + /// + public partial class SplashScreen : Window + { + private DispatcherTimer _timer; + private int _loadingStep = 0; + private readonly string[] _loadingMessages = { + "正在启动 Ink Canvas...", + "正在初始化组件...", + "正在加载配置...", + "正在准备界面...", + "启动完成!" + }; + + public SplashScreen() + { + InitializeComponent(); + InitializeSplashScreen(); + } + + private void InitializeSplashScreen() + { + // 设置窗口居中 + WindowStartupLocation = WindowStartupLocation.CenterScreen; + + // 设置版本号 + SetVersionText(); + + // 启动加载动画 + StartLoadingAnimation(); + } + + private void StartLoadingAnimation() + { + _timer = new DispatcherTimer + { + Interval = TimeSpan.FromMilliseconds(1200) + }; + _timer.Tick += Timer_Tick; + _timer.Start(); + } + + private void Timer_Tick(object sender, EventArgs e) + { + if (_loadingStep < _loadingMessages.Length) + { + LoadingText.Text = _loadingMessages[_loadingStep]; + _loadingStep++; + } + else + { + _timer.Stop(); + // 不要自动关闭启动画面,等待外部调用CloseSplashScreen + } + } + + public void CloseSplashScreen() + { + // 添加淡出动画 + var fadeOutAnimation = new DoubleAnimation + { + From = 1, + To = 0, + Duration = TimeSpan.FromMilliseconds(300), + EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn } + }; + + fadeOutAnimation.Completed += (s, e) => + { + this.Close(); + }; + + this.BeginAnimation(OpacityProperty, fadeOutAnimation); + } + + /// + /// 设置加载进度(0-100) + /// + /// 进度百分比 + public void SetProgress(int progress) + { + Dispatcher.Invoke(() => + { + LoadingProgress.IsIndeterminate = false; + LoadingProgress.Value = progress; + }); + } + + /// + /// 设置加载消息 + /// + /// 加载消息 + public void SetLoadingMessage(string message) + { + Dispatcher.Invoke(() => + { + LoadingText.Text = message; + }); + } + + /// + /// 设置版本号文本 + /// + private void SetVersionText() + { + try + { + var version = Assembly.GetExecutingAssembly().GetName().Version; + if (version != null) + { + VersionTextBlock.Text = $"v{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; + } + else + { + VersionTextBlock.Text = "v5.0.4.0"; + } + } + catch + { + VersionTextBlock.Text = "v5.0.4.0"; + } + } + } +} \ No newline at end of file diff --git a/Ink Canvas/obj/Debug/net472/InkCanvasForClass.csproj.AssemblyReference.cache b/Ink Canvas/obj/Debug/net472/InkCanvasForClass.csproj.AssemblyReference.cache index 57d842b8..c8c2dfbd 100644 Binary files a/Ink Canvas/obj/Debug/net472/InkCanvasForClass.csproj.AssemblyReference.cache and b/Ink Canvas/obj/Debug/net472/InkCanvasForClass.csproj.AssemblyReference.cache differ