Files
community/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherWindow.xaml.cs
T

466 lines
16 KiB
C#
Raw Normal View History

2025-07-16 13:35:17 +08:00
using System;
using System.Collections.Generic;
2025-07-28 14:40:44 +08:00
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
2025-07-16 13:35:17 +08:00
using System.Linq;
2025-07-28 14:40:44 +08:00
using System.Threading;
using System.Threading.Tasks;
2025-07-16 13:35:17 +08:00
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
2025-07-28 14:40:44 +08:00
using System.Windows.Threading;
2025-07-16 13:35:17 +08:00
namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher
{
/// <summary>
/// LauncherWindow.xaml 的交互逻辑
/// </summary>
public partial class LauncherWindow : Window
{
/// <summary>
/// 父插件
/// </summary>
private readonly SuperLauncherPlugin _plugin;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 是否处于固定模式
/// </summary>
2025-07-28 14:40:44 +08:00
private bool _isFixMode;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 应用项按钮列表
/// </summary>
private readonly Dictionary<Button, LauncherItem> _appButtons = new Dictionary<Button, LauncherItem>();
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 拖拽中的按钮
/// </summary>
private Button _draggingButton;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 拖拽开始位置
/// </summary>
private Point _dragStartPoint;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 构造函数
/// </summary>
public LauncherWindow(SuperLauncherPlugin plugin)
{
InitializeComponent();
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
_plugin = plugin;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 加载应用项
LoadLauncherItems();
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 添加鼠标按下事件(用于拖动窗口)
2025-07-28 14:40:44 +08:00
MouseDown += (s, e) =>
2025-07-16 13:35:17 +08:00
{
if (e.ChangedButton == MouseButton.Left && e.ButtonState == MouseButtonState.Pressed)
{
2025-07-28 14:40:44 +08:00
DragMove();
2025-07-16 13:35:17 +08:00
}
};
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 根据应用数量调整窗口大小
AdjustWindowSize();
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 加载启动台应用项
/// </summary>
private void LoadLauncherItems()
{
// 清空现有应用项
AppPanel.Children.Clear();
_appButtons.Clear();
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 获取显示的应用项
var visibleItems = _plugin.LauncherItems
.Where(item => item.IsVisible)
.OrderBy(item => item.Position)
.ToList();
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
foreach (var item in visibleItems)
{
// 创建应用按钮
Button appButton = new Button
{
Style = (Style)FindResource("LauncherItemStyle"),
DataContext = item,
Tag = item.Position
};
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 添加点击事件
appButton.Click += AppButton_Click;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 在固定模式下,添加拖拽事件
appButton.PreviewMouseDown += AppButton_PreviewMouseDown;
appButton.PreviewMouseMove += AppButton_PreviewMouseMove;
appButton.PreviewMouseUp += AppButton_PreviewMouseUp;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 记录按钮和项目的对应关系
_appButtons.Add(appButton, item);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 添加到面板
AppPanel.Children.Add(appButton);
}
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 根据应用数量调整窗口大小
/// </summary>
private void AdjustWindowSize()
{
try
{
// 每行最多显示4个应用
const int appsPerRow = 4;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 计算行数
int visibleCount = _appButtons.Count;
int rowCount = (int)Math.Ceiling(visibleCount / (double)appsPerRow);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 设置窗口宽度(每个应用90像素宽 = 80 + 5*2
Width = Math.Min(appsPerRow * 90 + 40, 400); // 最大宽度400
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 设置窗口高度(每个应用90像素高 = 80 + 5*2
Height = Math.Min(rowCount * 90 + 60, 600); // 最大高度600,标题栏40 + 边距20
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"调整启动台窗口大小时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 应用按钮点击事件
/// </summary>
private void AppButton_Click(object sender, RoutedEventArgs e)
{
try
{
if (_isFixMode) return; // 在固定模式下,不响应点击事件
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
if (sender is Button button && _appButtons.TryGetValue(button, out LauncherItem item))
{
// 获取应用路径和名称,用于后续启动
string appPath = item.Path;
string appName = item.Name;
2025-08-03 16:46:33 +08:00
2025-07-28 14:40:44 +08:00
LogHelper.WriteLogToFile($"点击启动应用: {appName}, 路径: {appPath}");
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 首先标记窗口正在关闭
IsClosing = true;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 创建一个应用启动任务
2025-07-28 14:40:44 +08:00
var launchTask = new Task(() =>
2025-07-16 13:35:17 +08:00
{
try
{
// 等待一段时间,确保窗口关闭流程已经开始
2025-07-28 14:40:44 +08:00
Thread.Sleep(200);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 使用UI线程启动应用
2025-08-03 16:46:33 +08:00
Application.Current.Dispatcher.Invoke(() =>
2025-07-16 13:35:17 +08:00
{
try
{
// 检查应用路径是否存在
2025-07-28 14:40:44 +08:00
if (File.Exists(appPath) || !appPath.Contains(":\\"))
2025-07-16 13:35:17 +08:00
{
// 创建进程启动信息
2025-07-28 14:40:44 +08:00
var psi = new ProcessStartInfo
2025-08-03 16:46:33 +08:00
{
FileName = appPath,
2025-07-16 13:35:17 +08:00
UseShellExecute = true,
2025-08-03 16:46:33 +08:00
};
2025-07-16 13:35:17 +08:00
// 启动应用程序
2025-07-28 14:40:44 +08:00
var process = Process.Start(psi);
LogHelper.WriteLogToFile($"应用程序 {appName} 已启动");
2025-07-16 13:35:17 +08:00
}
else
{
LogHelper.WriteLogToFile($"应用路径不存在: {appPath}", LogHelper.LogType.Error);
MessageBox.Show($"找不到应用程序: {appPath}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"启动应用程序失败: {ex.Message}", LogHelper.LogType.Error);
MessageBox.Show($"启动应用程序失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"应用启动任务出错: {ex.Message}", LogHelper.LogType.Error);
}
});
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 关闭窗口
try
{
Dispatcher.BeginInvoke(new Action(() =>
{
try { Close(); } catch { }
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 启动应用程序任务
launchTask.Start();
2025-07-28 14:40:44 +08:00
}), DispatcherPriority.Background);
2025-07-16 13:35:17 +08:00
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"关闭窗口或启动任务时出错: {ex.Message}", LogHelper.LogType.Error);
// 如果无法通过UI关闭窗口,直接启动任务
launchTask.Start();
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"应用按钮点击事件出错: {ex.Message}", LogHelper.LogType.Error);
try { IsClosing = true; Close(); } catch { }
}
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
#region
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 应用按钮鼠标按下事件
/// </summary>
private void AppButton_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (!_isFixMode) return;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
if (e.ChangedButton == MouseButton.Left && sender is Button button)
{
_draggingButton = button;
_dragStartPoint = e.GetPosition(AppPanel);
button.CaptureMouse();
button.Opacity = 0.7;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 阻止事件冒泡,以避免触发按钮点击
e.Handled = true;
}
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 应用按钮鼠标移动事件
/// </summary>
private void AppButton_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (!_isFixMode || _draggingButton == null) return;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
if (e.LeftButton == MouseButtonState.Pressed)
{
Point currentPosition = e.GetPosition(AppPanel);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 移动按钮
System.Windows.Controls.Canvas.SetLeft(_draggingButton, currentPosition.X - _draggingButton.ActualWidth / 2);
System.Windows.Controls.Canvas.SetTop(_draggingButton, currentPosition.Y - _draggingButton.ActualHeight / 2);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 将按钮移到最上层
Panel.SetZIndex(_draggingButton, 100);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 阻止事件冒泡
e.Handled = true;
}
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 应用按钮鼠标释放事件
/// </summary>
private void AppButton_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (!_isFixMode || _draggingButton == null) return;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 释放鼠标捕获
_draggingButton.ReleaseMouseCapture();
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 计算新位置
Point releasePoint = e.GetPosition(AppPanel);
int newPosition = CalculateGridPosition(releasePoint);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 获取当前项目
LauncherItem currentItem = _appButtons[_draggingButton];
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 重新排序
ReorderItems(currentItem, newPosition);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 重新加载应用项
LoadLauncherItems();
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 保存配置
_plugin.SaveConfig();
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 清除拖拽状态
_draggingButton.Opacity = 1;
Panel.SetZIndex(_draggingButton, 0);
_draggingButton = null;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 阻止事件冒泡
e.Handled = true;
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 计算网格位置
/// </summary>
private int CalculateGridPosition(Point point)
{
// 计算行和列
int columnCount = 4; // 每行最多4个应用
int columnWidth = 90; // 应用宽度(包括边距)
int rowHeight = 90; // 应用高度(包括边距)
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
int column = (int)(point.X / columnWidth);
int row = (int)(point.Y / rowHeight);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 确保在有效范围内
column = Math.Max(0, Math.Min(column, columnCount - 1));
row = Math.Max(0, row);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 计算位置索引
return row * columnCount + column;
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 重新排序应用项
/// </summary>
private void ReorderItems(LauncherItem item, int newPosition)
{
try
{
// 设置项目为固定位置
item.IsPositionFixed = true;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 如果位置相同,无需调整
if (item.Position == newPosition)
{
return;
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 获取所有可见项目
var visibleItems = _plugin.LauncherItems
.Where(i => i.IsVisible)
.OrderBy(i => i.Position)
.ToList();
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 移除当前项目
visibleItems.Remove(item);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 查找插入位置
int insertIndex = 0;
for (int i = 0; i < visibleItems.Count; i++)
{
if (visibleItems[i].Position >= newPosition)
{
insertIndex = i;
break;
}
insertIndex = i + 1;
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 插入项目
visibleItems.Insert(insertIndex, item);
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 重新分配位置
for (int i = 0; i < visibleItems.Count; i++)
{
visibleItems[i].Position = i;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"重新排序应用项时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
#endregion
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
#region
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 窗口失去焦点事件
/// </summary>
private void Window_Deactivated(object sender, EventArgs e)
{
try
{
// 只有在非固定模式、窗口已加载、未处于关闭状态且IsLoaded=true时关闭窗口
if (!_isFixMode && IsLoaded && !IsClosing)
{
// 标记为正在关闭
IsClosing = true;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 使用Dispatcher.BeginInvoke而不是直接调用Close,避免冲突
Dispatcher.BeginInvoke(new Action(() =>
{
try
{
// 再次检查窗口状态
if (IsLoaded && !IsClosing)
2025-08-03 16:46:33 +08:00
{
Close();
2025-07-16 13:35:17 +08:00
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"延迟关闭窗口时出错: {ex.Message}", LogHelper.LogType.Error);
}
2025-07-28 14:40:44 +08:00
}), DispatcherPriority.Background);
2025-07-16 13:35:17 +08:00
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"窗口失去焦点关闭时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 窗口是否正在关闭
/// </summary>
2025-07-28 14:40:44 +08:00
private bool IsClosing { get; set; }
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 重写OnClosing方法,标记窗口正在关闭
/// </summary>
2025-07-28 14:40:44 +08:00
protected override void OnClosing(CancelEventArgs e)
2025-07-16 13:35:17 +08:00
{
IsClosing = true;
base.OnClosing(e);
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 关闭按钮点击事件
/// </summary>
private void BtnClose_Click(object sender, RoutedEventArgs e)
{
Close();
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
/// <summary>
/// 固定模式按钮点击事件
/// </summary>
private void BtnFixMode_Click(object sender, RoutedEventArgs e)
{
// 切换固定模式
_isFixMode = !_isFixMode;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 更新固定模式按钮图标颜色
FixModeIcon.Fill = _isFixMode ? Brushes.Yellow : Brushes.White;
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
// 显示提示
if (_isFixMode)
{
MessageBox.Show("已进入固定模式,您可以拖动应用图标调整位置。", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
2025-08-03 16:46:33 +08:00
2025-07-16 13:35:17 +08:00
#endregion
}
2025-08-03 16:46:33 +08:00
}