From b21a15376dbd2d274e59c58ae98e44ea46900e48 Mon Sep 17 00:00:00 2001
From: unknown <2564608840@qq.com>
Date: Wed, 16 Jul 2025 13:35:17 +0800
Subject: [PATCH] =?UTF-8?q?add:=E6=8F=92=E4=BB=B6=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../BuiltIn/SuperLauncher/LauncherButton.cs | 276 ++++
.../BuiltIn/SuperLauncher/LauncherModels.cs | 303 ++++
.../LauncherSettingsControl.xaml | 87 +
.../LauncherSettingsControl.xaml.cs | 395 +++++
.../BuiltIn/SuperLauncher/LauncherWindow.xaml | 91 +
.../SuperLauncher/LauncherWindow.xaml.cs | 460 ++++++
.../Plugins/BuiltIn/SuperLauncherPlugin.cs | 589 +++++++
Ink Canvas/Helpers/Plugins/IPlugin.cs | 68 +
Ink Canvas/Helpers/Plugins/PluginBase.cs | 144 ++
Ink Canvas/Helpers/Plugins/PluginManager.cs | 1462 +++++++++++++++++
Ink Canvas/Helpers/Plugins/PluginTemplate.cs | 276 ++++
Ink Canvas/MainWindow.xaml | 95 +-
Ink Canvas/MainWindow.xaml.cs | 64 +
Ink Canvas/Windows/PluginSettingsWindow.xaml | 148 ++
.../Windows/PluginSettingsWindow.xaml.cs | 487 ++++++
15 files changed, 4872 insertions(+), 73 deletions(-)
create mode 100644 Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherButton.cs
create mode 100644 Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherModels.cs
create mode 100644 Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml
create mode 100644 Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml.cs
create mode 100644 Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherWindow.xaml
create mode 100644 Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherWindow.xaml.cs
create mode 100644 Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncherPlugin.cs
create mode 100644 Ink Canvas/Helpers/Plugins/IPlugin.cs
create mode 100644 Ink Canvas/Helpers/Plugins/PluginBase.cs
create mode 100644 Ink Canvas/Helpers/Plugins/PluginManager.cs
create mode 100644 Ink Canvas/Helpers/Plugins/PluginTemplate.cs
create mode 100644 Ink Canvas/Windows/PluginSettingsWindow.xaml
create mode 100644 Ink Canvas/Windows/PluginSettingsWindow.xaml.cs
diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherButton.cs b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherButton.cs
new file mode 100644
index 00000000..b8a5ea29
--- /dev/null
+++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherButton.cs
@@ -0,0 +1,276 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Shapes;
+using iNKORE.UI.WPF.Modern.Controls;
+
+namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
+{
+ ///
+ /// 启动台按钮控件
+ ///
+ public class LauncherButton
+ {
+ ///
+ /// 父插件
+ ///
+ private readonly SuperLauncherPlugin _plugin;
+
+ ///
+ /// 实际按钮控件
+ ///
+ private readonly SimpleStackPanel _panel;
+
+ ///
+ /// 获取按钮UI元素
+ ///
+ public UIElement Element => _panel;
+
+ ///
+ /// 构造函数
+ ///
+ /// 父插件
+ public LauncherButton(SuperLauncherPlugin plugin)
+ {
+ try
+ {
+ _plugin = plugin;
+ LogHelper.WriteLogToFile("开始创建启动台按钮", LogHelper.LogType.Info);
+
+ // 创建SimpleStackPanel
+ _panel = new SimpleStackPanel
+ {
+ Name = "Launcher_Icon",
+ Orientation = Orientation.Vertical,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ Width = 28,
+ Margin = new Thickness(0, -2, 0, 0),
+ Background = Brushes.Transparent
+ };
+
+ LogHelper.WriteLogToFile("创建SimpleStackPanel完成", LogHelper.LogType.Info);
+
+ // 添加图标
+ var image = CreateIconImage();
+ _panel.Children.Add(image);
+
+ // 添加文本
+ TextBlock textBlock = new TextBlock
+ {
+ Text = "启动台",
+ Foreground = Brushes.Black,
+ FontSize = 8,
+ Margin = new Thickness(0, 1, 0, 0),
+ TextAlignment = TextAlignment.Center
+ };
+ _panel.Children.Add(textBlock);
+
+ // 设置鼠标事件
+ _panel.MouseDown += Panel_MouseDown;
+ _panel.MouseUp += Panel_MouseUp;
+ _panel.MouseLeave += Panel_MouseLeave;
+
+ // 右键菜单支持
+ _panel.ContextMenu = CreateContextMenu();
+
+ // 设置工具提示
+ _panel.ToolTip = "启动台";
+
+ LogHelper.WriteLogToFile("启动台按钮创建完成", LogHelper.LogType.Info);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"创建启动台按钮时出错: {ex.Message}", LogHelper.LogType.Error);
+ LogHelper.NewLog(ex);
+ }
+ }
+
+ ///
+ /// 创建右键菜单
+ ///
+ private ContextMenu CreateContextMenu()
+ {
+ try
+ {
+ // 创建菜单
+ ContextMenu menu = new ContextMenu();
+
+ // 创建位置切换菜单项
+ MenuItem positionMenuItem = new MenuItem();
+ positionMenuItem.Header = _plugin.Config.ButtonPosition == LauncherButtonPosition.Left ?
+ "移至右侧" : "移至左侧";
+ positionMenuItem.Click += (s, e) =>
+ {
+ // 切换位置
+ _plugin.Config.ButtonPosition = _plugin.Config.ButtonPosition == LauncherButtonPosition.Left ?
+ LauncherButtonPosition.Right : LauncherButtonPosition.Left;
+
+ // 更新按钮位置
+ _plugin.UpdateButtonPosition();
+
+ // 保存配置
+ _plugin.SaveConfig();
+
+ LogHelper.WriteLogToFile($"通过右键菜单切换启动台按钮位置为: {_plugin.Config.ButtonPosition}",
+ LogHelper.LogType.Info);
+ };
+ menu.Items.Add(positionMenuItem);
+
+ // 添加设置菜单项
+ MenuItem settingsMenuItem = new MenuItem();
+ settingsMenuItem.Header = "打开设置";
+ settingsMenuItem.Click += (s, e) =>
+ {
+ // 打开插件设置窗口
+ var mainWindow = Application.Current.MainWindow;
+ if (mainWindow != null)
+ {
+ try
+ {
+ // 使用反射调用主窗口的ShowPluginSettings方法
+ var method = mainWindow.GetType().GetMethod("ShowPluginSettings");
+ if (method != null)
+ {
+ method.Invoke(mainWindow, null);
+ LogHelper.WriteLogToFile("已打开插件设置窗口", LogHelper.LogType.Info);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"打开插件设置窗口失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+ };
+ menu.Items.Add(settingsMenuItem);
+
+ return menu;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"创建右键菜单时出错: {ex.Message}", LogHelper.LogType.Error);
+ return null;
+ }
+ }
+
+ ///
+ /// 获取实际的UI元素
+ ///
+ [Obsolete("使用Element属性代替")]
+ public UIElement GetUIElement()
+ {
+ return _panel;
+ }
+
+ ///
+ /// 创建图标图像
+ ///
+ private Image CreateIconImage()
+ {
+ try
+ {
+ // 创建图像
+ Image image = new Image
+ {
+ Height = 17,
+ Margin = new Thickness(0, 3, 0, 0)
+ };
+
+ // 设置位图缩放模式
+ RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.HighQuality);
+
+ // 创建绘图图像
+ DrawingImage drawingImage = new DrawingImage();
+ DrawingGroup drawingGroup = new DrawingGroup();
+ drawingGroup.ClipGeometry = Geometry.Parse("M0,0 V24 H24 V0 H0 Z");
+
+ // 使用提供的应用网格图标
+ GeometryDrawing geometryDrawing = new GeometryDrawing
+ {
+ Brush = new SolidColorBrush(Color.FromRgb(0x1B, 0x1B, 0x1B)),
+ Geometry = Geometry.Parse("F0 M24,24z M0,0z M4.41721,4.29873C4.35178,4.29873,4.29873,4.35178,4.29873,4.41721L4.29873,9.15646C4.29873,9.22189,4.35178,9.27494,4.41721,9.27494L9.15646,9.27494C9.22189,9.27494,9.27494,9.22189,9.27494,9.15646L9.27494,4.41721C9.27494,4.35178,9.22189,4.29873,9.15646,4.29873L4.41721,4.29873z M2.64,4.41721C2.64,3.43569,3.43569,2.64,4.41721,2.64L9.15646,2.64C10.138,2.64,10.9337,3.43569,10.9337,4.41721L10.9337,9.15646C10.9337,10.138,10.138,10.9337,9.15646,10.9337L4.41721,10.9337C3.43569,10.9337,2.64,10.138,2.64,9.15646L2.64,4.41721z M14.8435,4.29873C14.7781,4.29873,14.7251,4.35178,14.7251,4.41721L14.7251,9.15646C14.7251,9.22189,14.7781,9.27494,14.8435,9.27494L19.5828,9.27494C19.6482,9.27494,19.7013,9.22189,19.7013,9.15646L19.7013,4.41721C19.7013,4.35178,19.6482,4.29873,19.5828,4.29873L14.8435,4.29873z M13.0663,4.41721C13.0663,3.43569,13.862,2.64,14.8435,2.64L19.5828,2.64C20.5643,2.64,21.36,3.43569,21.36,4.41721L21.36,9.15646C21.36,10.138,20.5643,10.9337,19.5828,10.9337L14.8435,10.9337C13.862,10.9337,13.0663,10.138,13.0663,9.15646L13.0663,4.41721z M14.8435,14.7251C14.7781,14.7251,14.7251,14.7781,14.7251,14.8435L14.7251,19.5828C14.7251,19.6482,14.7781,19.7013,14.8435,19.7013L19.5828,19.7013C19.6482,19.7013,19.7013,19.6482,19.7013,19.5828L19.7013,14.8435C19.7013,14.7781,19.6482,14.7251,19.5828,14.7251L14.8435,14.7251z M13.0663,14.8435C13.0663,13.862,13.862,13.0663,14.8435,13.0663L19.5828,13.0663C20.5643,13.0663,21.36,13.862,21.36,14.8435L21.36,19.5828C21.36,20.5643,20.5643,21.36,19.5828,21.36L14.8435,21.36C13.862,21.36,13.0663,20.5643,13.0663,19.5828L13.0663,14.8435z M4.41721,14.7251C4.35178,14.7251,4.29873,14.7781,4.29873,14.8435L4.29873,19.5828C4.29873,19.6482,4.35178,19.7013,4.41721,19.7013L9.15646,19.7013C9.22189,19.7013,9.27494,19.6482,9.27494,19.5828L9.27494,14.8435C9.27494,14.7781,9.22189,14.7251,9.15646,14.7251L4.41721,14.7251z M2.64,14.8435C2.64,13.862,3.43569,13.0663,4.41721,13.0663L9.15646,13.0663C10.138,13.0663,10.9337,13.862,10.9337,14.8435L10.9337,19.5828C10.9337,20.5643,10.138,21.36,9.15646,21.36L4.41721,21.36C3.43569,21.36,2.64,20.5643,2.64,19.5828L2.64,14.8435z")
+ };
+
+ drawingGroup.Children.Add(geometryDrawing);
+
+ // 设置图像源
+ drawingImage.Drawing = drawingGroup;
+ image.Source = drawingImage;
+
+ return image;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"创建图标图像时出错: {ex.Message}", LogHelper.LogType.Error);
+ LogHelper.NewLog(ex);
+
+ // 返回一个空图像
+ return new Image();
+ }
+ }
+
+ ///
+ /// 鼠标按下事件
+ ///
+ private void Panel_MouseDown(object sender, MouseButtonEventArgs e)
+ {
+ try
+ {
+ // 提供反馈
+ _panel.Background = new SolidColorBrush(Color.FromArgb(40, 0, 0, 0));
+ LogHelper.WriteLogToFile("启动台按钮鼠标按下", LogHelper.LogType.Info);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"启动台按钮鼠标按下事件出错: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ ///
+ /// 鼠标抬起事件
+ ///
+ private void Panel_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+ try
+ {
+ // 只有左键点击才显示启动台窗口
+ if (e.ChangedButton != MouseButton.Left)
+ {
+ return;
+ }
+
+ // 恢复背景
+ _panel.Background = Brushes.Transparent;
+ LogHelper.WriteLogToFile("启动台按钮鼠标抬起,准备显示启动台窗口", LogHelper.LogType.Info);
+
+ // 获取按钮在屏幕上的位置
+ Point buttonPosition = _panel.PointToScreen(new Point(_panel.ActualWidth / 2, 0));
+
+ // 显示启动台窗口
+ _plugin.ShowLauncherWindow(buttonPosition);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"启动台按钮鼠标抬起事件出错: {ex.Message}", LogHelper.LogType.Error);
+ LogHelper.NewLog(ex);
+ }
+ }
+
+ ///
+ /// 鼠标离开事件
+ ///
+ private void Panel_MouseLeave(object sender, MouseEventArgs e)
+ {
+ try
+ {
+ // 恢复背景
+ _panel.Background = Brushes.Transparent;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"启动台按钮鼠标离开事件出错: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherModels.cs b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherModels.cs
new file mode 100644
index 00000000..9749f8dc
--- /dev/null
+++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherModels.cs
@@ -0,0 +1,303 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Windows;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using Microsoft.Win32;
+
+namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
+{
+ ///
+ /// 启动台按钮位置
+ ///
+ public enum LauncherButtonPosition
+ {
+ ///
+ /// 左侧
+ ///
+ Left,
+
+ ///
+ /// 右侧
+ ///
+ Right
+ }
+
+ ///
+ /// 启动台配置
+ ///
+ public class LauncherConfig
+ {
+ ///
+ /// 启动台按钮位置
+ ///
+ public LauncherButtonPosition ButtonPosition { get; set; } = LauncherButtonPosition.Right;
+
+ ///
+ /// 启动台应用程序列表
+ ///
+ public List Items { get; set; } = new List();
+ }
+
+ ///
+ /// 启动台应用项
+ ///
+ public class LauncherItem
+ {
+ ///
+ /// 应用程序名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 应用程序路径
+ ///
+ public string Path { get; set; }
+
+ ///
+ /// 是否可见
+ ///
+ public bool IsVisible { get; set; } = true;
+
+ ///
+ /// 在启动台中的位置(0-39)
+ ///
+ public int Position { get; set; } = -1;
+
+ ///
+ /// 是否已固定位置
+ ///
+ public bool IsPositionFixed { get; set; } = false;
+
+ ///
+ /// 图标缓存
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ private ImageSource _iconCache;
+
+ ///
+ /// 获取应用程序图标
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ public ImageSource Icon
+ {
+ get
+ {
+ if (_iconCache != null)
+ {
+ return _iconCache;
+ }
+
+ try
+ {
+ if (File.Exists(Path))
+ {
+ // 从文件中获取图标
+ Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(Path);
+ if (icon != null)
+ {
+ _iconCache = Imaging.CreateBitmapSourceFromHIcon(
+ icon.Handle,
+ Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions());
+
+ icon.Dispose();
+ return _iconCache;
+ }
+ }
+ else
+ {
+ // 从注册表中获取文件类型关联图标
+ string extension = System.IO.Path.GetExtension(Path);
+ if (!string.IsNullOrEmpty(extension))
+ {
+ string fileType = Registry.ClassesRoot.OpenSubKey(extension)?.GetValue(string.Empty) as string;
+ if (!string.IsNullOrEmpty(fileType))
+ {
+ string iconPath = Registry.ClassesRoot.OpenSubKey(fileType + "\\DefaultIcon")?.GetValue(string.Empty) as string;
+ if (!string.IsNullOrEmpty(iconPath))
+ {
+ string[] parts = iconPath.Split(',');
+ string iconFile = parts[0].Trim('"');
+ int iconIndex = parts.Length > 1 ? Convert.ToInt32(parts[1]) : 0;
+
+ if (File.Exists(iconFile))
+ {
+ Icon icon = IconExtractor.Extract(iconFile, iconIndex, true);
+ if (icon != null)
+ {
+ _iconCache = Imaging.CreateBitmapSourceFromHIcon(
+ icon.Handle,
+ Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions());
+
+ icon.Dispose();
+ return _iconCache;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"获取应用图标时出错: {ex.Message}", LogHelper.LogType.Error);
+ }
+
+ // 返回默认图标
+ return GetDefaultIcon();
+ }
+ }
+
+ ///
+ /// 获取默认图标
+ ///
+ private ImageSource GetDefaultIcon()
+ {
+ try
+ {
+ // 对于资源管理器,使用特定图标
+ if (Path.EndsWith("explorer.exe", StringComparison.OrdinalIgnoreCase))
+ {
+ string explorerIconPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "Icons-Fluent", "ic_fluent_folder_24_regular.png");
+ if (File.Exists(explorerIconPath))
+ {
+ Uri uri = new Uri(explorerIconPath);
+ BitmapImage image = new BitmapImage(uri);
+ _iconCache = image;
+ return _iconCache;
+ }
+ }
+
+ // 返回一个简单的默认图标
+ string iconPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "Icons-png", "icc.png");
+ if (File.Exists(iconPath))
+ {
+ Uri uri = new Uri(iconPath);
+ BitmapImage image = new BitmapImage(uri);
+ _iconCache = image;
+ return _iconCache;
+ }
+
+ // 如果还是没有找到,尝试使用应用程序图标
+ string appIconPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "Icons-Fluent", "ic_fluent_apps_24_regular.png");
+ if (File.Exists(appIconPath))
+ {
+ Uri uri = new Uri(appIconPath);
+ BitmapImage image = new BitmapImage(uri);
+ _iconCache = image;
+ return _iconCache;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"获取默认图标时出错: {ex.Message}", LogHelper.LogType.Error);
+ }
+
+ return null;
+ }
+
+ ///
+ /// 启动应用程序
+ ///
+ public void Launch()
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(Path))
+ {
+ LogHelper.WriteLogToFile("无法启动应用程序:路径为空", LogHelper.LogType.Error);
+ return;
+ }
+
+ // 检查文件是否存在
+ if (!System.IO.File.Exists(Path) && !Path.Contains(":\\"))
+ {
+ // 可能是系统命令,如explorer.exe
+ System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo
+ {
+ FileName = Path,
+ UseShellExecute = true
+ };
+ System.Diagnostics.Process.Start(psi);
+ }
+ else
+ {
+ // 使用Process.Start启动应用程序
+ System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo
+ {
+ FileName = Path,
+ UseShellExecute = true
+ };
+ System.Diagnostics.Process.Start(psi);
+ }
+
+ LogHelper.WriteLogToFile($"已启动应用程序: {Path}", LogHelper.LogType.Info);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"启动应用程序时出错: {ex.Message}", LogHelper.LogType.Error);
+ MessageBox.Show($"启动应用程序时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+ }
+
+ ///
+ /// 图标提取工具类
+ ///
+ public static class IconExtractor
+ {
+ ///
+ /// 从文件中提取图标
+ ///
+ /// 文件路径
+ /// 图标索引
+ /// 是否提取大图标
+ /// 提取的图标
+ public static Icon Extract(string file, int index, bool largeIcon)
+ {
+ try
+ {
+ IntPtr large;
+ IntPtr small;
+ ExtractIconEx(file, index, out large, out small, 1);
+
+ try
+ {
+ return Icon.FromHandle(largeIcon ? large : small);
+ }
+ catch
+ {
+ return null;
+ }
+ finally
+ {
+ if (large != IntPtr.Zero)
+ DestroyIcon(large);
+
+ if (small != IntPtr.Zero)
+ DestroyIcon(small);
+ }
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ [System.Runtime.InteropServices.DllImport("Shell32.dll", EntryPoint = "ExtractIconEx")]
+ private static extern int ExtractIconEx(
+ [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] string lpszFile,
+ int nIconIndex,
+ out IntPtr phiconLarge,
+ out IntPtr phiconSmall,
+ int nIcons);
+
+ [System.Runtime.InteropServices.DllImport("User32.dll")]
+ private static extern int DestroyIcon(IntPtr hIcon);
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml
new file mode 100644
index 00000000..63deeaad
--- /dev/null
+++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml.cs b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml.cs
new file mode 100644
index 00000000..07b79c92
--- /dev/null
+++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml.cs
@@ -0,0 +1,395 @@
+using Microsoft.Win32;
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using Ink_Canvas.Windows;
+
+namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
+{
+ ///
+ /// LauncherSettingsControl.xaml 的交互逻辑
+ ///
+ public partial class LauncherSettingsControl : UserControl
+ {
+ ///
+ /// 父插件
+ ///
+ private readonly SuperLauncherPlugin _plugin;
+
+ ///
+ /// 构造函数
+ ///
+ /// 父插件
+ public LauncherSettingsControl(SuperLauncherPlugin plugin)
+ {
+ InitializeComponent();
+
+ _plugin = plugin;
+
+ // 设置按钮位置
+ RbtnLeft.IsChecked = _plugin.Config.ButtonPosition == LauncherButtonPosition.Left;
+ RbtnRight.IsChecked = _plugin.Config.ButtonPosition == LauncherButtonPosition.Right;
+
+ // 绑定应用列表
+ DgApps.ItemsSource = _plugin.LauncherItems;
+
+ // 初始化按钮状态
+ UpdateButtonStates();
+ }
+
+ ///
+ /// 更新按钮状态
+ ///
+ private void UpdateButtonStates()
+ {
+ bool hasSelection = DgApps.SelectedItem != null;
+ BtnEdit.IsEnabled = hasSelection;
+ BtnDelete.IsEnabled = hasSelection;
+ }
+
+ ///
+ /// 位置单选按钮选择事件
+ ///
+ private void RbtnPosition_Checked(object sender, RoutedEventArgs e)
+ {
+ if (!IsLoaded) return;
+
+ LauncherButtonPosition oldPosition = _plugin.Config.ButtonPosition;
+
+ if (sender == RbtnLeft)
+ {
+ _plugin.Config.ButtonPosition = LauncherButtonPosition.Left;
+ }
+ else if (sender == RbtnRight)
+ {
+ _plugin.Config.ButtonPosition = LauncherButtonPosition.Right;
+ }
+
+ // 如果位置发生变化,更新按钮位置
+ if (oldPosition != _plugin.Config.ButtonPosition)
+ {
+ try
+ {
+ // 更新按钮位置
+ _plugin.UpdateButtonPosition();
+
+ // 保存配置
+ _plugin.SaveConfig();
+
+ LogHelper.WriteLogToFile($"启动台按钮位置已更改为: {_plugin.Config.ButtonPosition}", LogHelper.LogType.Info);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"更新启动台按钮位置时出错: {ex.Message}", LogHelper.LogType.Error);
+ MessageBox.Show($"更新启动台按钮位置时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+ }
+
+ ///
+ /// 添加应用按钮点击事件
+ ///
+ private void BtnAdd_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ // 弹出文件选择对话框
+ OpenFileDialog dialog = new OpenFileDialog
+ {
+ Title = "选择应用程序",
+ Filter = "应用程序 (*.exe)|*.exe|所有文件 (*.*)|*.*",
+ Multiselect = false
+ };
+
+ if (dialog.ShowDialog() == true)
+ {
+ // 创建新的启动项
+ LauncherItem item = new LauncherItem
+ {
+ Name = System.IO.Path.GetFileNameWithoutExtension(dialog.FileName),
+ Path = dialog.FileName,
+ IsVisible = true,
+ Position = -1 // 让插件管理器分配位置
+ };
+
+ // 显示编辑对话框
+ EditLauncherItem(item, true);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"添加启动项时出错: {ex.Message}", LogHelper.LogType.Error);
+ MessageBox.Show($"添加启动项时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ ///
+ /// 编辑应用按钮点击事件
+ ///
+ private void BtnEdit_Click(object sender, RoutedEventArgs e)
+ {
+ if (DgApps.SelectedItem is LauncherItem item)
+ {
+ EditLauncherItem(item, false);
+ }
+ }
+
+ ///
+ /// 删除应用按钮点击事件
+ ///
+ private void BtnDelete_Click(object sender, RoutedEventArgs e)
+ {
+ if (DgApps.SelectedItem is LauncherItem item)
+ {
+ // 确认删除
+ MessageBoxResult result = MessageBox.Show(
+ $"确定要删除 {item.Name} 吗?",
+ "删除确认",
+ MessageBoxButton.YesNo,
+ MessageBoxImage.Question);
+
+ if (result == MessageBoxResult.Yes)
+ {
+ // 从集合中移除
+ _plugin.LauncherItems.Remove(item);
+
+ // 保存配置
+ _plugin.SaveConfig();
+ }
+ }
+ }
+
+ ///
+ /// 保存设置按钮点击事件
+ ///
+ private void BtnSave_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ // 保存配置
+ _plugin.SaveConfig();
+
+ // 如果插件已启用,重新加载启动台按钮
+ if (_plugin.IsEnabled)
+ {
+ _plugin.Disable();
+ _plugin.Enable();
+ }
+ else
+ {
+ // 如果插件未启用,则启用它
+ _plugin.Enable();
+
+ // 通知PluginSettingsWindow刷新插件列表
+ var window = Window.GetWindow(this);
+ if (window is PluginSettingsWindow pluginSettingsWindow)
+ {
+ // 触发刷新
+ pluginSettingsWindow.RefreshPluginList();
+ }
+ }
+
+ MessageBox.Show("设置已保存并应用!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"保存设置时出错: {ex.Message}", LogHelper.LogType.Error);
+ MessageBox.Show($"保存设置时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ ///
+ /// 应用项选择变更事件
+ ///
+ private void DgApps_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ UpdateButtonStates();
+ }
+
+ ///
+ /// 编辑启动项
+ ///
+ /// 启动项
+ /// 是否为新建
+ private void EditLauncherItem(LauncherItem item, bool isNew)
+ {
+ // 创建简单的编辑窗口
+ Window editWindow = new Window
+ {
+ Title = isNew ? "添加应用" : "编辑应用",
+ Width = 400,
+ Height = 200,
+ WindowStartupLocation = WindowStartupLocation.CenterScreen,
+ ResizeMode = ResizeMode.NoResize
+ };
+
+ // 创建编辑表单
+ Grid grid = new Grid
+ {
+ Margin = new Thickness(20)
+ };
+
+ grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
+ grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
+ grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
+
+ grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(80) });
+ grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
+
+ // 名称输入框
+ TextBlock nameLabel = new TextBlock
+ {
+ Text = "名称:",
+ VerticalAlignment = VerticalAlignment.Center
+ };
+ TextBox nameTextBox = new TextBox
+ {
+ Text = item.Name,
+ Margin = new Thickness(0, 5, 0, 5)
+ };
+
+ Grid.SetRow(nameLabel, 0);
+ Grid.SetColumn(nameLabel, 0);
+ Grid.SetRow(nameTextBox, 0);
+ Grid.SetColumn(nameTextBox, 1);
+
+ grid.Children.Add(nameLabel);
+ grid.Children.Add(nameTextBox);
+
+ // 路径输入框
+ TextBlock pathLabel = new TextBlock
+ {
+ Text = "路径:",
+ VerticalAlignment = VerticalAlignment.Center
+ };
+ Grid pathGrid = new Grid();
+ pathGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
+ pathGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength() });
+
+ TextBox pathTextBox = new TextBox
+ {
+ Text = item.Path,
+ Margin = new Thickness(0, 5, 5, 5)
+ };
+ Button browseButton = new Button
+ {
+ Content = "浏览",
+ Padding = new Thickness(5, 0, 5, 0),
+ Margin = new Thickness(0, 5, 0, 5)
+ };
+
+ browseButton.Click += (s, e) =>
+ {
+ OpenFileDialog dialog = new OpenFileDialog
+ {
+ Title = "选择应用程序",
+ Filter = "应用程序 (*.exe)|*.exe|所有文件 (*.*)|*.*",
+ Multiselect = false,
+ FileName = pathTextBox.Text
+ };
+
+ if (dialog.ShowDialog() == true)
+ {
+ pathTextBox.Text = dialog.FileName;
+ }
+ };
+
+ Grid.SetColumn(pathTextBox, 0);
+ Grid.SetColumn(browseButton, 1);
+ pathGrid.Children.Add(pathTextBox);
+ pathGrid.Children.Add(browseButton);
+
+ Grid.SetRow(pathLabel, 1);
+ Grid.SetColumn(pathLabel, 0);
+ Grid.SetRow(pathGrid, 1);
+ Grid.SetColumn(pathGrid, 1);
+
+ grid.Children.Add(pathLabel);
+ grid.Children.Add(pathGrid);
+
+ // 确认和取消按钮
+ StackPanel buttonPanel = new StackPanel
+ {
+ Orientation = Orientation.Horizontal,
+ HorizontalAlignment = HorizontalAlignment.Right,
+ Margin = new Thickness(0, 10, 0, 0)
+ };
+
+ Button okButton = new Button
+ {
+ Content = "确定",
+ Padding = new Thickness(15, 5, 15, 5),
+ Margin = new Thickness(0, 0, 10, 0),
+ IsDefault = true
+ };
+
+ Button cancelButton = new Button
+ {
+ Content = "取消",
+ Padding = new Thickness(15, 5, 15, 5),
+ IsCancel = true
+ };
+
+ okButton.Click += (s, e) =>
+ {
+ // 验证输入
+ if (string.IsNullOrWhiteSpace(nameTextBox.Text))
+ {
+ MessageBox.Show("请输入应用名称!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(pathTextBox.Text))
+ {
+ MessageBox.Show("请输入应用路径!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
+ return;
+ }
+
+ // 更新项目
+ item.Name = nameTextBox.Text;
+ item.Path = pathTextBox.Text;
+
+ // 如果是新建,添加到集合
+ if (isNew)
+ {
+ _plugin.AddLauncherItem(item);
+ }
+ else
+ {
+ // 触发属性变更通知,刷新DataGrid
+ if (DgApps.ItemsSource is ICollectionView view)
+ {
+ view.Refresh();
+ }
+
+ // 保存配置
+ _plugin.SaveConfig();
+ }
+
+ editWindow.DialogResult = true;
+ editWindow.Close();
+ };
+
+ cancelButton.Click += (s, e) =>
+ {
+ editWindow.DialogResult = false;
+ editWindow.Close();
+ };
+
+ buttonPanel.Children.Add(okButton);
+ buttonPanel.Children.Add(cancelButton);
+
+ Grid.SetRow(buttonPanel, 2);
+ Grid.SetColumnSpan(buttonPanel, 2);
+
+ grid.Children.Add(buttonPanel);
+
+ // 设置窗口内容
+ editWindow.Content = grid;
+
+ // 显示窗口
+ editWindow.ShowDialog();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherWindow.xaml b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherWindow.xaml
new file mode 100644
index 00000000..b6463afe
--- /dev/null
+++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherWindow.xaml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherWindow.xaml.cs b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherWindow.xaml.cs
new file mode 100644
index 00000000..4045a5fb
--- /dev/null
+++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherWindow.xaml.cs
@@ -0,0 +1,460 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
+{
+ ///
+ /// LauncherWindow.xaml 的交互逻辑
+ ///
+ public partial class LauncherWindow : Window
+ {
+ ///
+ /// 父插件
+ ///
+ private readonly SuperLauncherPlugin _plugin;
+
+ ///
+ /// 是否处于固定模式
+ ///
+ private bool _isFixMode = false;
+
+ ///
+ /// 应用项按钮列表
+ ///
+ private readonly Dictionary