ToolBox/MainForm.cs

2810 lines
113 KiB
C#
Raw Normal View History

2025-03-12 14:06:44 +08:00
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Linq;
2025-03-12 15:18:23 +08:00
using System.Runtime.InteropServices; // 添加P/Invoke支持
using System.Drawing.Drawing2D; // 添加GDI+支持
using System.Drawing.Imaging; // 添加图像处理支持
using Microsoft.Win32;
using System.Diagnostics; // 添加Registry访问支持
2025-03-12 14:06:44 +08:00
namespace QuickLauncher
{
public partial class MainForm : Form
{
2025-03-12 15:18:23 +08:00
// Windows 11 UI相关
private bool isDarkMode = false;
private Color accentColor = Color.FromArgb(0, 120, 212); // Windows默认蓝色
private readonly Color lightBackColor = Color.FromArgb(243, 243, 243);
private readonly Color darkBackColor = Color.FromArgb(32, 32, 32);
private readonly Color lightTextColor = Color.FromArgb(0, 0, 0);
private readonly Color darkTextColor = Color.FromArgb(255, 255, 255);
private readonly int cornerRadius = 8; // Windows 11圆角半径
// P/Invoke用于实现Windows 11 Mica效果
[DllImport("dwmapi.dll")]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
// DWM属性常量
private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
private const int DWMWA_MICA_EFFECT = 1029;
// 添加圆角支持的类
private class RoundedPanel : Panel
{
private int _cornerRadius = 8;
2025-03-12 15:18:23 +08:00
public int CornerRadius
{
get { return _cornerRadius; }
set { _cornerRadius = value; Invalidate(); }
}
2025-03-12 15:18:23 +08:00
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// 设置高质量绘图模式
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
2025-03-12 15:18:23 +08:00
// 创建圆角路径
using (GraphicsPath path = new GraphicsPath())
{
path.AddArc(0, 0, CornerRadius, CornerRadius, 180, 90);
path.AddArc(Width - CornerRadius, 0, CornerRadius, CornerRadius, 270, 90);
path.AddArc(Width - CornerRadius, Height - CornerRadius, CornerRadius, CornerRadius, 0, 90);
path.AddArc(0, Height - CornerRadius, CornerRadius, CornerRadius, 90, 90);
path.CloseAllFigures();
2025-03-12 15:18:23 +08:00
this.Region = new Region(path);
}
}
}
2025-03-12 15:18:23 +08:00
// 添加圆角按钮支持的类
private class RoundedButton : Button
{
private int _cornerRadius = 8;
2025-03-12 15:18:23 +08:00
public int CornerRadius
{
get { return _cornerRadius; }
set { _cornerRadius = value; Invalidate(); }
}
2025-03-12 15:18:23 +08:00
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// 设置高质量绘图模式
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
2025-03-12 15:18:23 +08:00
// 创建圆角路径
using (GraphicsPath path = new GraphicsPath())
{
path.AddArc(0, 0, CornerRadius, CornerRadius, 180, 90);
path.AddArc(Width - CornerRadius, 0, CornerRadius, CornerRadius, 270, 90);
path.AddArc(Width - CornerRadius, Height - CornerRadius, CornerRadius, CornerRadius, 0, 90);
path.AddArc(0, Height - CornerRadius, CornerRadius, CornerRadius, 90, 90);
path.CloseAllFigures();
2025-03-12 15:18:23 +08:00
this.Region = new Region(path);
}
}
}
// 原有的字段
2025-03-12 14:06:44 +08:00
private Dictionary<string, List<ShortcutItem>> categories;
private string dataFilePath = "shortcuts.json";
private string settingsFilePath = "settings.json";
private const int CATEGORY_BUTTON_HEIGHT = 40;
private string currentCategory = "";
private ContextMenuStrip categoryContextMenu;
private ContextMenuStrip shortcutsPanelContextMenu;
private ContextMenuStrip shortcutItemContextMenu;
private int iconSize = 48; // 默认图标大小
private const int MIN_ICON_SIZE = 24; // 最小图标大小
private const int MAX_ICON_SIZE = 256; // 增加最大图标大小到256
private const int ICON_SIZE_STEP = 16; // 增加每次缩放的步长
2025-03-12 15:18:23 +08:00
// 左侧面板调整相关
private bool isResizing = false;
2025-03-17 23:34:35 +08:00
private int resizingStartX = 5;
private int initialPanelWidth = 5;
2025-03-12 15:18:23 +08:00
private const int MIN_PANEL_WIDTH = 200;
private const int MAX_PANEL_WIDTH = 500;
private Panel resizeHandle;
2025-03-12 14:06:44 +08:00
// 用于保存设置的类
private class AppSettings
{
public string LastSelectedCategory { get; set; } = "";
public string SortMode { get; set; } = "Name"; // Name, DateAdded
public int IconSize { get; set; } = 48; // 保存图标大小
2025-03-12 15:18:23 +08:00
public int LeftPanelWidth { get; set; } = 300; // 左侧面板宽度
public bool EnableAutoDocking { get; set; } = false; // 启用自动停靠
public Point FloatingIconPosition { get; set; } = new Point(0, 0); // 浮动图标位置
public bool ShowFloatingIconOnStartup { get; set; } = false; // 启动时不显示浮动图标
public string FloatingIconPath { get; set; } = ""; // 浮动按钮图标路径
2025-03-12 14:06:44 +08:00
}
private AppSettings settings = new AppSettings();
// 添加浮动图标相关代码
private NotifyIcon notifyIcon;
private Form floatingIcon;
private bool isFloatingIconVisible = false;
// 修改ResizeHandle相关代码添加鼠标光标
private void InitializeResizeHandle()
{
// 创建调整大小的控件
resizeHandle = new Panel
{
Width = 5,
Dock = DockStyle.Right,
BackColor = Color.Transparent,
Cursor = Cursors.SizeWE // 设置为水平调整大小的光标
};
// 添加事件处理
resizeHandle.MouseDown += ResizeHandle_MouseDown;
resizeHandle.MouseMove += ResizeHandle_MouseMove;
resizeHandle.MouseUp += ResizeHandle_MouseUp;
2025-03-17 23:34:35 +08:00
resizeHandle.MouseEnter += (s, e) => resizeHandle.Cursor = Cursors.SizeWE;
resizeHandle.MouseLeave += (s, e) =>
{
if (!isResizing)
{
resizeHandle.Cursor = Cursors.SizeWE;
}
};
// 添加到左侧面板
leftPanel.Controls.Add(resizeHandle);
resizeHandle.BringToFront();
}
// 修改停靠方法,改进停靠行为
private bool isDocked = false;
private FormBorderStyle originalBorderStyle;
private Size originalSize;
private Point originalLocation;
private FormWindowState originalWindowState;
private const int DOCK_THRESHOLD = 10; // 停靠阈值
private void DockToScreenEdge()
{
// 检查是否启用自动停靠
if (!settings.EnableAutoDocking)
return;
Screen currentScreen = Screen.FromControl(this);
Rectangle screenBounds = currentScreen.WorkingArea;
bool shouldDock = false;
DockStyle dockPosition = DockStyle.None;
// 检查左边缘
if (Math.Abs(this.Left - screenBounds.Left) <= DOCK_THRESHOLD)
{
shouldDock = true;
dockPosition = DockStyle.Left;
}
// 检查右边缘
else if (Math.Abs(screenBounds.Right - (this.Left + this.Width)) <= DOCK_THRESHOLD)
{
shouldDock = true;
dockPosition = DockStyle.Right;
}
// 如果应该停靠但尚未停靠
if (shouldDock && !isDocked)
{
// 保存原始状态
originalBorderStyle = this.FormBorderStyle;
originalSize = this.Size;
originalLocation = this.Location;
originalWindowState = this.WindowState;
// 应用停靠样式
ApplyDockStyle(dockPosition, screenBounds);
isDocked = true;
}
// 如果不应该停靠但当前已停靠
else if (!shouldDock && isDocked)
{
// 恢复原始状态
this.FormBorderStyle = originalBorderStyle;
this.Size = originalSize;
this.Location = originalLocation;
this.WindowState = originalWindowState;
isDocked = false;
}
}
private void ApplyDockStyle(DockStyle dockPosition, Rectangle screenBounds)
{
// 设置为无边框样式
this.FormBorderStyle = FormBorderStyle.SizableToolWindow;
// 根据停靠位置调整窗体
if (dockPosition == DockStyle.Left)
{
this.Location = new Point(screenBounds.Left, screenBounds.Top);
this.Size = new Size(Math.Min(this.Width, screenBounds.Width / 4), screenBounds.Height);
}
else if (dockPosition == DockStyle.Right)
{
this.Location = new Point(screenBounds.Right - Math.Min(this.Width, screenBounds.Width / 4), screenBounds.Top);
this.Size = new Size(Math.Min(this.Width, screenBounds.Width / 4), screenBounds.Height);
}
// 设置窗体始终置顶
this.TopMost = true;
}
2025-03-12 14:06:44 +08:00
public MainForm()
{
InitializeComponent();
2025-03-12 14:06:44 +08:00
// 配置工具提示 - 调整为更合适的值
toolTip1 = new ToolTip();
toolTip1.AutoPopDelay = 5000;
toolTip1.InitialDelay = 200; // 稍微增加初始延迟
toolTip1.ReshowDelay = 200; // 稍微增加重新显示延迟
toolTip1.ShowAlways = true;
toolTip1.UseFading = true;
toolTip1.IsBalloon = false; // 使用标准样式
// 移除最小化按钮,保留最大化按钮
this.MinimizeBox = false;
2025-03-12 15:18:23 +08:00
// 初始化数据和UI
InitializeUI();
2025-03-12 15:18:23 +08:00
// 应用Windows 11风格
ApplyWin11Style();
2025-03-12 14:06:44 +08:00
SetupContextMenus();
SetupEventHandlers();
// 初始化浮动图标必须在LoadSettings之前
InitializeNotifyIcon();
// 加载设置
2025-03-12 14:06:44 +08:00
LoadSettings();
2025-03-12 14:06:44 +08:00
LoadData();
SelectDefaultCategory();
2025-03-12 15:18:23 +08:00
// 监听系统主题变化
SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
// 初始化调整大小的控件
InitializeResizeHandle();
// 确保主窗口显示,浮动图标隐藏
this.Show();
this.Activate();
if (floatingIcon != null)
{
HideFloatingIcon();
}
2025-03-12 15:18:23 +08:00
}
private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
if (e.Category == UserPreferenceCategory.General)
{
// 在UI线程中更新主题
if (this.InvokeRequired)
{
this.Invoke(new Action(() => UpdateTheme()));
}
else
{
UpdateTheme();
}
}
}
private void UpdateTheme()
{
// 更新深色模式状态
isDarkMode = IsSystemUsingSysemDarkTheme();
2025-03-12 15:18:23 +08:00
// 重新应用Windows 11风格
ApplyWin11Style();
}
// 应用Windows 11风格
private void ApplyWin11Style()
{
// 检测系统主题
isDarkMode = IsSystemUsingSysemDarkTheme();
2025-03-12 15:18:23 +08:00
// 应用Mica效果
if (Environment.OSVersion.Version.Build >= 22000) // Windows 11
{
try
{
// 应用深色/浅色模式
int darkMode = isDarkMode ? 1 : 0;
DwmSetWindowAttribute(this.Handle, DWMWA_USE_IMMERSIVE_DARK_MODE, ref darkMode, sizeof(int));
2025-03-12 15:18:23 +08:00
// 应用Mica效果
int micaEffect = 1;
DwmSetWindowAttribute(this.Handle, DWMWA_MICA_EFFECT, ref micaEffect, sizeof(int));
}
catch (Exception)
{
// 如果不支持,则使用备用方案
this.BackColor = isDarkMode ? darkBackColor : lightBackColor;
}
}
else
{
// 在Windows 10上使用备用方案
this.BackColor = isDarkMode ? darkBackColor : lightBackColor;
}
2025-03-12 15:18:23 +08:00
// 应用主题颜色
ApplyThemeColors();
}
2025-03-12 15:18:23 +08:00
// 检测系统是否使用深色主题
private bool IsSystemUsingSysemDarkTheme()
{
try
{
using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"))
{
if (key != null)
{
var value = key.GetValue("AppsUseLightTheme");
if (value != null && value is int)
{
return (int)value == 0;
}
}
}
}
catch { }
2025-03-12 15:18:23 +08:00
return false;
}
2025-03-12 15:18:23 +08:00
// 应用主题颜色
private void ApplyThemeColors()
{
// 设置主窗体颜色
this.ForeColor = isDarkMode ? darkTextColor : lightTextColor;
2025-03-12 15:18:23 +08:00
// 设置左侧面板颜色
leftPanel.BackColor = isDarkMode ? Color.FromArgb(40, 40, 40) : Color.FromArgb(243, 243, 243);
2025-03-12 15:18:23 +08:00
// 设置右侧面板颜色
rightPanel.BackColor = isDarkMode ? Color.FromArgb(32, 32, 32) : Color.FromArgb(250, 250, 250);
2025-03-12 15:18:23 +08:00
// 设置工具面板颜色
toolPanel.BackColor = isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(230, 230, 230);
2025-03-12 15:18:23 +08:00
// 设置快捷方式面板颜色
shortcutsPanel.BackColor = isDarkMode ? Color.FromArgb(32, 32, 32) : Color.FromArgb(250, 250, 250);
// 设置分类文字颜色
categoryLabel.ForeColor = isDarkMode ? Color.FromArgb(255, 255, 255) : Color.FromArgb(0, 0, 0);
2025-03-12 15:18:23 +08:00
// 设置添加按钮颜色
addButton.BackColor = accentColor;
addButton.ForeColor = Color.White;
addButton.FlatAppearance.BorderSize = 0;
2025-03-12 15:18:23 +08:00
// 设置菜单颜色
menuStrip.BackColor = isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(230, 230, 230);
menuStrip.ForeColor = isDarkMode ? darkTextColor : lightTextColor;
2025-03-12 15:18:23 +08:00
// 设置菜单项颜色
foreach (ToolStripMenuItem item in menuStrip.Items)
{
item.ForeColor = isDarkMode ? Color.White : Color.Black;
2025-03-12 15:18:23 +08:00
// 设置下拉菜单项颜色
foreach (ToolStripItem dropItem in item.DropDownItems)
{
if (dropItem is ToolStripMenuItem menuItem)
{
menuItem.ForeColor = isDarkMode ? Color.White : Color.Black;
}
}
}
2025-03-12 15:18:23 +08:00
// 设置菜单渲染器
menuStrip.Renderer = new ModernMenuRenderer(isDarkMode);
2025-03-12 15:18:23 +08:00
// 刷新分类列表和当前分类的快捷方式仅当categories已初始化时
if (categories != null)
{
RefreshCategoryList();
if (!string.IsNullOrEmpty(currentCategory))
{
ShowCategoryItems(currentCategory);
}
}
2025-03-12 14:06:44 +08:00
}
// 设置上下文菜单
private void SetupContextMenus()
{
// 分类右键菜单
categoryContextMenu = new ContextMenuStrip();
categoryContextMenu.Items.Add("添加新分类", null, (s, e) => AddCategory_Click(s, e));
categoryContextMenu.Items.Add("删除当前分类", null, (s, e) => DeleteCategory_Click(s, e));
categoryContextMenu.Items.Add("重命名分类", null, (s, e) => RenameCategory_Click(s, e));
2025-03-12 15:18:23 +08:00
// 应用主题颜色
categoryContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
2025-03-12 14:06:44 +08:00
// 右侧面板右键菜单
shortcutsPanelContextMenu = new ContextMenuStrip();
shortcutsPanelContextMenu.Items.Add("添加程序", null, (s, e) => AddButton_Click(s, e));
shortcutsPanelContextMenu.Items.Add("-"); // 分隔线
shortcutsPanelContextMenu.Items.Add("按名称排序", null, (s, e) => SortShortcuts("Name"));
shortcutsPanelContextMenu.Items.Add("按添加时间排序", null, (s, e) => SortShortcuts("DateAdded"));
shortcutsPanelContextMenu.Items.Add("按使用频率排序", null, (s, e) => SortShortcuts("UsageCount"));
shortcutsPanelContextMenu.Items.Add("-"); // 分隔线
2025-03-12 14:06:44 +08:00
// 添加图标大小调整菜单,增加更多选项
var sizeMenu = new ToolStripMenuItem("图标大小");
sizeMenu.DropDownItems.Add("超小图标 (24px)", null, (s, e) => { ResizeIcons(24); });
sizeMenu.DropDownItems.Add("小图标 (48px)", null, (s, e) => { ResizeIcons(48); });
sizeMenu.DropDownItems.Add("中图标 (64px)", null, (s, e) => { ResizeIcons(64); });
sizeMenu.DropDownItems.Add("大图标 (96px)", null, (s, e) => { ResizeIcons(96); });
sizeMenu.DropDownItems.Add("较大图标 (128px)", null, (s, e) => { ResizeIcons(128); });
sizeMenu.DropDownItems.Add("超大图标 (192px)", null, (s, e) => { ResizeIcons(192); });
sizeMenu.DropDownItems.Add("巨大图标 (256px)", null, (s, e) => { ResizeIcons(256); });
shortcutsPanelContextMenu.Items.Add(sizeMenu);
2025-03-12 15:18:23 +08:00
// 添加主题切换选项
shortcutsPanelContextMenu.Items.Add("-"); // 分隔线
var themeMenu = new ToolStripMenuItem("主题设置");
themeMenu.DropDownItems.Add("浅色主题", null, (s, e) => { ChangeTheme(false); });
themeMenu.DropDownItems.Add("深色主题", null, (s, e) => { ChangeTheme(true); });
themeMenu.DropDownItems.Add("跟随系统", null, (s, e) => { FollowSystemTheme(); });
shortcutsPanelContextMenu.Items.Add(themeMenu);
2025-03-12 15:18:23 +08:00
// 应用主题颜色
shortcutsPanelContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
2025-03-12 14:06:44 +08:00
// 快捷方式项目右键菜单
shortcutItemContextMenu = new ContextMenuStrip();
shortcutItemContextMenu.Items.Add("启动", null, (s, e) =>
2025-03-12 14:06:44 +08:00
{
if (shortcutItemContextMenu.Tag is ShortcutItem item)
2025-03-12 14:06:44 +08:00
{
LaunchApplication(item.Path);
}
});
shortcutItemContextMenu.Items.Add("删除", null, (s, e) =>
2025-03-12 14:06:44 +08:00
{
if (shortcutItemContextMenu.Tag is ShortcutItem item)
2025-03-12 14:06:44 +08:00
{
DeleteShortcut(item);
}
});
shortcutItemContextMenu.Items.Add("重命名", null, (s, e) =>
2025-03-12 14:06:44 +08:00
{
if (shortcutItemContextMenu.Tag is ShortcutItem item)
2025-03-12 14:06:44 +08:00
{
RenameShortcut(item);
}
});
shortcutItemContextMenu.Items.Add("属性", null, (s, e) =>
2025-03-12 14:06:44 +08:00
{
if (shortcutItemContextMenu.Tag is ShortcutItem item)
2025-03-12 14:06:44 +08:00
{
ShowShortcutProperties(item);
}
});
shortcutItemContextMenu.Items.Add("打开程序目录", null, (s, e) =>
{
if (shortcutItemContextMenu.Tag is ShortcutItem item)
{
OpenProgramDirectory(item.Path);
}
});
2025-03-12 15:18:23 +08:00
// 应用主题颜色
shortcutItemContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
}
2025-03-12 15:18:23 +08:00
// 切换主题
private void ChangeTheme(bool darkMode)
{
isDarkMode = darkMode;
ApplyThemeColors();
2025-03-12 15:18:23 +08:00
// 更新上下文菜单渲染器
categoryContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
shortcutsPanelContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
shortcutItemContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
}
2025-03-12 15:18:23 +08:00
// 跟随系统主题
private void FollowSystemTheme()
{
isDarkMode = IsSystemUsingSysemDarkTheme();
ApplyThemeColors();
2025-03-12 15:18:23 +08:00
// 更新上下文菜单渲染器
categoryContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
shortcutsPanelContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
shortcutItemContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
}
2025-03-12 15:18:23 +08:00
// 现代菜单渲染器
private class ModernMenuRenderer : ToolStripProfessionalRenderer
{
private bool _isDarkMode;
2025-03-12 15:18:23 +08:00
public ModernMenuRenderer(bool isDarkMode) : base(new ModernColorTable(isDarkMode))
{
_isDarkMode = isDarkMode;
}
2025-03-12 15:18:23 +08:00
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
if (e.Item.Selected)
{
// 选中项背景
Rectangle rect = new Rectangle(2, 0, e.Item.Width - 4, e.Item.Height);
Color highlightColor = _isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(210, 230, 250);
using (SolidBrush brush = new SolidBrush(highlightColor))
{
e.Graphics.FillRoundedRectangle(brush, rect, 4);
}
}
else
{
// 普通项背景
Color backColor = _isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(250, 250, 250);
using (SolidBrush brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Item.ContentRectangle);
}
}
}
2025-03-12 15:18:23 +08:00
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
{
// 菜单背景
Color backColor = _isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(250, 250, 250);
using (SolidBrush brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.AffectedBounds);
}
}
2025-03-12 15:18:23 +08:00
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
// 菜单文本颜色
e.TextColor = _isDarkMode ? Color.FromArgb(240, 240, 240) : Color.FromArgb(20, 20, 20);
base.OnRenderItemText(e);
}
2025-03-12 15:18:23 +08:00
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
{
// 分隔线颜色
Color lineColor = _isDarkMode ? Color.FromArgb(80, 80, 80) : Color.FromArgb(200, 200, 200);
int y = e.Item.Height / 2;
using (Pen pen = new Pen(lineColor))
{
e.Graphics.DrawLine(pen, 4, y, e.Item.Width - 4, y);
}
}
}
2025-03-12 15:18:23 +08:00
// 现代菜单颜色表
private class ModernColorTable : ProfessionalColorTable
{
private bool _isDarkMode;
2025-03-12 15:18:23 +08:00
public ModernColorTable(bool isDarkMode)
{
_isDarkMode = isDarkMode;
}
2025-03-12 15:18:23 +08:00
// 菜单项
public override Color MenuItemSelected => _isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(210, 230, 250);
public override Color MenuItemBorder => Color.Transparent;
2025-03-12 15:18:23 +08:00
// 菜单栏
public override Color MenuBorder => Color.Transparent;
public override Color MenuItemSelectedGradientBegin => _isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(210, 230, 250);
public override Color MenuItemSelectedGradientEnd => _isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(210, 230, 250);
public override Color MenuItemPressedGradientBegin => _isDarkMode ? Color.FromArgb(80, 80, 80) : Color.FromArgb(190, 210, 240);
public override Color MenuItemPressedGradientEnd => _isDarkMode ? Color.FromArgb(80, 80, 80) : Color.FromArgb(190, 210, 240);
2025-03-12 15:18:23 +08:00
// 工具栏
public override Color ToolStripDropDownBackground => _isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(250, 250, 250);
public override Color ImageMarginGradientBegin => _isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(250, 250, 250);
public override Color ImageMarginGradientMiddle => _isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(250, 250, 250);
public override Color ImageMarginGradientEnd => _isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(250, 250, 250);
2025-03-12 14:06:44 +08:00
}
// 调整图标大小
private void ResizeIcons(int newSize)
{
if (newSize >= MIN_ICON_SIZE && newSize <= MAX_ICON_SIZE)
{
iconSize = newSize;
settings.IconSize = iconSize;
SaveSettings();
2025-03-12 14:06:44 +08:00
if (!string.IsNullOrEmpty(currentCategory))
{
ShowCategoryItems(currentCategory);
}
}
}
// 处理鼠标滚轮事件
private void ShortcutsPanel_MouseWheel(object sender, MouseEventArgs e)
{
// 检查Ctrl键是否按下
if (ModifierKeys == Keys.Control)
{
// 向上滚动,放大图标
if (e.Delta > 0)
{
ResizeIcons(iconSize + ICON_SIZE_STEP);
}
// 向下滚动,缩小图标
else if (e.Delta < 0)
{
ResizeIcons(iconSize - ICON_SIZE_STEP);
}
}
}
// 重命名分类
private void RenameCategory_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(currentCategory))
{
MessageBox.Show("请先选择要重命名的分类", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (var dialog = new Form())
{
dialog.Text = "重命名分类";
dialog.Size = new Size(350, 150);
dialog.StartPosition = FormStartPosition.CenterParent;
dialog.FormBorderStyle = FormBorderStyle.FixedDialog;
dialog.MaximizeBox = false;
dialog.MinimizeBox = false;
var label = new Label() { Text = "新名称:", Location = new Point(10, 20) };
var textBox = new TextBox() { Text = currentCategory, Location = new Point(120, 17), Width = 180 };
2025-03-12 15:44:35 +08:00
var button = new RoundedButton() { Text = "确定", DialogResult = DialogResult.OK, Location = new Point(110, 60), CornerRadius = cornerRadius, BackColor = accentColor, ForeColor = Color.White };
2025-03-12 14:06:44 +08:00
dialog.Controls.AddRange(new Control[] { label, textBox, button });
dialog.AcceptButton = button;
if (dialog.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace(textBox.Text))
{
string newName = textBox.Text.Trim();
if (newName != currentCategory && !categories.ContainsKey(newName))
{
var items = categories[currentCategory];
categories.Remove(currentCategory);
categories[newName] = items;
2025-03-12 14:06:44 +08:00
string oldCategory = currentCategory;
currentCategory = newName;
2025-03-12 14:06:44 +08:00
SaveData();
RefreshCategoryList();
ShowCategoryItems(currentCategory);
}
else if (categories.ContainsKey(newName) && newName != currentCategory)
{
MessageBox.Show("该分类名称已存在", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
}
// 排序快捷方式
private void SortShortcuts(string sortMode)
{
if (string.IsNullOrEmpty(currentCategory) || !categories.ContainsKey(currentCategory))
return;
settings.SortMode = sortMode;
SaveSettings();
switch (sortMode)
{
case "Name":
categories[currentCategory] = categories[currentCategory].OrderBy(s => s.Name).ToList();
break;
case "DateAdded":
categories[currentCategory] = categories[currentCategory].OrderByDescending(s => s.DateAdded).ToList();
break;
case "UsageCount":
categories[currentCategory] = categories[currentCategory].OrderByDescending(s => s.UsageCount).ToList();
break;
}
SaveData();
ShowCategoryItems(currentCategory);
}
// 删除快捷方式
private void DeleteShortcut(ShortcutItem item)
{
if (string.IsNullOrEmpty(currentCategory) || !categories.ContainsKey(currentCategory))
return;
if (MessageBox.Show($"确定要删除 '{item.Name}' 吗?", "确认删除",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
categories[currentCategory].Remove(item);
SaveData();
ShowCategoryItems(currentCategory);
}
}
// 重命名快捷方式
private void RenameShortcut(ShortcutItem item)
{
using (var dialog = new Form())
{
dialog.Text = "重命名快捷方式";
dialog.Size = new Size(350, 150);
dialog.StartPosition = FormStartPosition.CenterParent;
dialog.FormBorderStyle = FormBorderStyle.FixedDialog;
dialog.MaximizeBox = false;
dialog.MinimizeBox = false;
var label = new Label() { Text = "新名称:", Location = new Point(10, 20) };
var textBox = new TextBox() { Text = item.Name, Location = new Point(120, 17), Width = 180 };
2025-03-12 15:44:35 +08:00
var button = new RoundedButton() { Text = "确定", DialogResult = DialogResult.OK, Location = new Point(110, 60), CornerRadius = cornerRadius, BackColor = accentColor, ForeColor = Color.White };
2025-03-12 14:06:44 +08:00
dialog.Controls.AddRange(new Control[] { label, textBox, button });
dialog.AcceptButton = button;
if (dialog.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace(textBox.Text))
{
item.Name = textBox.Text.Trim();
SaveData();
ShowCategoryItems(currentCategory);
}
}
}
// 显示快捷方式属性
private void ShowShortcutProperties(ShortcutItem item)
{
using (var dialog = new Form())
{
dialog.Text = "快捷方式属性";
dialog.Size = new Size(400, 300);
dialog.StartPosition = FormStartPosition.CenterParent;
dialog.FormBorderStyle = FormBorderStyle.FixedDialog;
dialog.MaximizeBox = false;
dialog.MinimizeBox = false;
// 使用当前图标大小显示图标
var icon = new PictureBox
{
Size = new Size(Math.Min(64, iconSize), Math.Min(64, iconSize)), // 限制属性对话框中的图标大小
Location = new Point(20, 20),
Image = item.Icon ?? SystemIcons.Application.ToBitmap(),
SizeMode = PictureBoxSizeMode.StretchImage
};
var nameLabel = new Label() { Text = "名称:", Location = new Point(20, 80), AutoSize = true };
var nameValue = new Label() { Text = item.Name, Location = new Point(120, 80), AutoSize = true };
var pathLabel = new Label() { Text = "路径:", Location = new Point(20, 110), AutoSize = true };
var pathValue = new Label() { Text = item.Path, Location = new Point(120, 110), Width = 250, AutoEllipsis = true };
var dateLabel = new Label() { Text = "添加日期:", Location = new Point(20, 140), AutoSize = true };
var dateValue = new Label() { Text = item.DateAdded.ToString(), Location = new Point(120, 140), AutoSize = true };
var usageLabel = new Label() { Text = "使用次数:", Location = new Point(20, 170), AutoSize = true };
var usageValue = new Label() { Text = item.UsageCount.ToString(), Location = new Point(120, 170), AutoSize = true };
2025-03-12 15:44:35 +08:00
var button = new RoundedButton() { Text = "确定", DialogResult = DialogResult.OK, Location = new Point(150, 220), CornerRadius = cornerRadius, BackColor = accentColor, ForeColor = Color.White };
2025-03-12 14:06:44 +08:00
dialog.Controls.AddRange(new Control[] { icon, nameLabel, nameValue, pathLabel, pathValue,
2025-03-12 14:06:44 +08:00
dateLabel, dateValue, usageLabel, usageValue, button });
dialog.AcceptButton = button;
dialog.ShowDialog();
}
}
// 打开程序目录
private void OpenProgramDirectory(string programPath)
{
try
{
if (File.Exists(programPath))
{
// 使用explorer.exe /select, 来打开文件所在目录并高亮显示该文件
Process.Start("explorer.exe", $"/select,\"{programPath}\"");
}
else
{
MessageBox.Show("文件不存在,无法打开所在目录", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception ex)
{
MessageBox.Show($"打开程序目录时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
2025-03-12 14:06:44 +08:00
// 选择默认分类
private void SelectDefaultCategory()
{
// 如果没有分类,不做任何操作
if (categories.Count == 0)
return;
// 尝试选择上次选择的分类
if (!string.IsNullOrEmpty(settings.LastSelectedCategory) &&
2025-03-12 14:06:44 +08:00
categories.ContainsKey(settings.LastSelectedCategory))
{
currentCategory = settings.LastSelectedCategory;
ShowCategoryItems(currentCategory);
return;
}
// 如果没有上次选择的分类或该分类不存在,选择第一个分类
currentCategory = categories.Keys.First();
ShowCategoryItems(currentCategory);
}
// 保存设置
private void SaveSettings()
{
try
{
settings.LastSelectedCategory = currentCategory;
settings.IconSize = iconSize;
2025-03-12 15:18:23 +08:00
settings.LeftPanelWidth = leftPanel.Width;
// 添加null检查
if (floatingIcon != null)
{
settings.FloatingIconPosition = floatingIcon.Location;
// 不要在这里设置FloatingIconPath它应该只在ChangeFloatingIconImage方法中设置
}
2025-03-12 14:06:44 +08:00
var options = new JsonSerializerOptions
{
WriteIndented = true
};
var data = JsonSerializer.Serialize(settings, options);
File.WriteAllText(settingsFilePath, data);
}
catch (Exception ex)
{
MessageBox.Show($"保存设置失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// 加载设置
private void LoadSettings()
{
if (File.Exists(settingsFilePath))
{
try
{
var json = File.ReadAllText(settingsFilePath);
settings = JsonSerializer.Deserialize<AppSettings>(json) ?? new AppSettings();
iconSize = settings.IconSize; // 加载保存的图标大小
2025-03-12 15:18:23 +08:00
leftPanel.Width = settings.LeftPanelWidth;
// 确保floatingIcon已初始化
if (floatingIcon != null)
{
floatingIcon.Location = settings.FloatingIconPosition;
// 不要在这里设置Visible属性让ShowFloatingIcon方法来控制
}
2025-03-12 14:06:44 +08:00
}
catch
{
settings = new AppSettings();
}
}
}
private void SetupEventHandlers()
{
// 清除所有事件处理器 - 移除不存在的引用
addButton.Click -= AddButton_Click;
this.FormClosing -= MainForm_FormClosing;
shortcutsPanel.MouseWheel -= ShortcutsPanel_MouseWheel;
// 只为shortcutsPanel添加拖放支持
shortcutsPanel.AllowDrop = true;
shortcutsPanel.DragEnter += ShortcutsPanel_DragEnter;
shortcutsPanel.DragDrop += ShortcutsPanel_DragDrop;
2025-03-12 14:06:44 +08:00
// 添加鼠标滚轮事件处理
shortcutsPanel.MouseWheel += ShortcutsPanel_MouseWheel;
2025-03-12 14:06:44 +08:00
// 为shortcutsPanel添加鼠标移动事件用于处理空白区域的工具提示
shortcutsPanel.MouseMove += ShortcutsPanel_MouseMove;
// 为shortcutsPanel添加右键菜单
shortcutsPanel.ContextMenuStrip = shortcutsPanelContextMenu;
// 绑定添加程序按钮事件
addButton.Click += AddButton_Click;
// 绑定窗体关闭事件,保存当前选择的分类
this.FormClosing += MainForm_FormClosing;
}
// 添加缺失的事件处理方法
private void ShortcutsPanel_DragEnter(object sender, DragEventArgs e)
{
Console.WriteLine("DragEnter triggered");
if (e.Data.GetDataPresent(DataFormats.FileDrop) && !string.IsNullOrEmpty(currentCategory))
{
e.Effect = DragDropEffects.Copy;
}
else
{
e.Effect = DragDropEffects.None;
}
}
2025-03-12 14:06:44 +08:00
private void ShortcutsPanel_DragDrop(object sender, DragEventArgs e)
{
Console.WriteLine("DragDrop triggered");
if (string.IsNullOrEmpty(currentCategory))
{
MessageBox.Show("请先选择一个分类", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
bool addedAny = false;
foreach (string file in files)
{
if (File.Exists(file))
{
AddNewShortcut(file, currentCategory);
addedAny = true;
}
}
if (!addedAny)
{
MessageBox.Show("没有找到有效的文件", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
SaveSettings();
}
private void InitializeUI()
{
2025-03-12 15:18:23 +08:00
// 初始化数据
2025-03-12 14:06:44 +08:00
categories = new Dictionary<string, List<ShortcutItem>>();
2025-03-12 15:18:23 +08:00
// 设置窗体样式
this.FormBorderStyle = FormBorderStyle.Sizable;
this.MinimumSize = new Size(800, 600);
2025-03-12 15:18:23 +08:00
// 设置控件样式
addButton.FlatStyle = FlatStyle.Flat;
addButton.FlatAppearance.BorderSize = 0;
addButton.BackColor = accentColor;
addButton.ForeColor = Color.White;
addButton.Font = new Font("Microsoft YaHei UI", 10, FontStyle.Regular);
2025-03-12 15:18:23 +08:00
// 设置分类标签样式
categoryLabel.Font = new Font("Microsoft YaHei UI", 11);
categoryLabel.ForeColor = isDarkMode ? Color.FromArgb(0, 0, 0) : Color.FromArgb(255, 255, 255);
2025-03-12 15:18:23 +08:00
// 刷新分类列表
2025-03-12 14:06:44 +08:00
RefreshCategoryList();
}
2025-03-12 15:18:23 +08:00
// 调整手柄鼠标按下事件
private void ResizeHandle_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
isResizing = true;
resizingStartX = e.X;
initialPanelWidth = leftPanel.Width;
2025-03-12 15:18:23 +08:00
// 捕获鼠标
resizeHandle.Capture = true;
2025-03-17 23:34:35 +08:00
// 设置鼠标光标
this.Cursor = Cursors.SizeWE;
resizeHandle.Cursor = Cursors.SizeWE;
2025-03-12 15:18:23 +08:00
}
}
2025-03-12 15:18:23 +08:00
// 调整手柄鼠标移动事件
private void ResizeHandle_MouseMove(object sender, MouseEventArgs e)
{
if (isResizing)
{
// 计算新宽度
int newWidth = initialPanelWidth + (e.X - resizingStartX);
2025-03-12 15:18:23 +08:00
// 限制宽度范围
if (newWidth < MIN_PANEL_WIDTH)
newWidth = MIN_PANEL_WIDTH;
else if (newWidth > MAX_PANEL_WIDTH)
newWidth = MAX_PANEL_WIDTH;
2025-03-12 15:18:23 +08:00
// 设置新宽度
leftPanel.Width = newWidth;
2025-03-12 15:18:23 +08:00
// 刷新布局
this.PerformLayout();
}
}
2025-03-12 15:18:23 +08:00
// 调整手柄鼠标释放事件
private void ResizeHandle_MouseUp(object sender, MouseEventArgs e)
{
if (isResizing)
{
2025-03-17 23:34:35 +08:00
// 先保存设置
settings.LeftPanelWidth = leftPanel.Width;
SaveSettings();
// 在鼠标释放后刷新一次分类列表
RefreshCategoryList();
2025-03-17 23:34:35 +08:00
// 重置调整状态
isResizing = false;
// 恢复默认鼠标光标
this.Cursor = Cursors.Default;
// 最后释放鼠标捕获
2025-03-12 15:18:23 +08:00
resizeHandle.Capture = false;
2025-03-17 23:34:35 +08:00
// 确保调整手柄保持正确的光标
resizeHandle.Cursor = Cursors.SizeWE;
}
}
2025-03-17 23:34:35 +08:00
// 添加窗体鼠标移动事件处理
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
// 如果正在调整大小,确保鼠标光标保持为调整大小状态
if (isResizing)
{
this.Cursor = Cursors.SizeWE;
resizeHandle.Cursor = Cursors.SizeWE;
2025-03-12 15:18:23 +08:00
}
}
2025-03-12 14:06:44 +08:00
private void AddCategory_Click(object sender, EventArgs e)
{
using (var dialog = new Form())
{
dialog.Text = "添加新分类";
dialog.Size = new Size(350, 200);
2025-03-12 14:06:44 +08:00
dialog.StartPosition = FormStartPosition.CenterParent;
dialog.FormBorderStyle = FormBorderStyle.FixedDialog;
dialog.MaximizeBox = false;
dialog.MinimizeBox = false;
dialog.BackColor = isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(240, 240, 240);
2025-03-12 15:18:23 +08:00
dialog.ForeColor = isDarkMode ? Color.White : Color.Black;
2025-03-12 14:06:44 +08:00
// 应用Windows 11深色/浅色模式到标题栏
if (Environment.OSVersion.Version.Build >= 22000)
{
int darkMode = isDarkMode ? 1 : 0;
DwmSetWindowAttribute(dialog.Handle, DWMWA_USE_IMMERSIVE_DARK_MODE, ref darkMode, sizeof(int));
}
var label = new Label()
{
Text = "分类名称:",
2025-03-12 15:18:23 +08:00
Location = new Point(10, 20),
ForeColor = isDarkMode ? Color.White : Color.Black,
AutoSize = true
2025-03-12 15:18:23 +08:00
};
var textBox = new TextBox()
{
Location = new Point(120, 17),
2025-03-12 15:18:23 +08:00
Width = 180,
BackColor = isDarkMode ? Color.FromArgb(60, 60, 60) : Color.White,
ForeColor = isDarkMode ? Color.White : Color.Black,
BorderStyle = BorderStyle.FixedSingle
2025-03-12 15:18:23 +08:00
};
var button = new RoundedButton()
{
Text = "确定",
DialogResult = DialogResult.OK,
2025-03-12 15:18:23 +08:00
Location = new Point(110, 60),
Width = 100,
Height = 30,
2025-03-12 15:44:35 +08:00
BackColor = accentColor,
ForeColor = Color.White,
2025-03-12 15:18:23 +08:00
CornerRadius = cornerRadius
};
2025-03-12 14:06:44 +08:00
dialog.Controls.AddRange(new Control[] { label, textBox, button });
dialog.AcceptButton = button;
// 确保在显示对话框之前应用主题
dialog.HandleCreated += (s, ev) =>
{
if (Environment.OSVersion.Version.Build >= 22000)
{
int darkMode = isDarkMode ? 1 : 0;
DwmSetWindowAttribute(dialog.Handle, DWMWA_USE_IMMERSIVE_DARK_MODE, ref darkMode, sizeof(int));
}
};
2025-03-12 14:06:44 +08:00
if (dialog.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace(textBox.Text))
{
string newCategory = textBox.Text.Trim();
if (!categories.ContainsKey(newCategory))
{
categories[newCategory] = new List<ShortcutItem>();
SaveData();
RefreshCategoryList();
2025-03-12 14:06:44 +08:00
// 自动选择新创建的分类
SwitchCategory(newCategory);
2025-03-12 14:06:44 +08:00
}
}
}
}
private void DeleteCategory_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(currentCategory))
{
MessageBox.Show("请先选择要删除的分类", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (MessageBox.Show($"确定要删除分类 '{currentCategory}' 吗?", "确认删除",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
categories.Remove(currentCategory);
SaveData();
RefreshCategoryList();
shortcutsPanel.Controls.Clear();
currentCategory = "";
2025-03-12 14:06:44 +08:00
// 删除分类后,选择新的默认分类
if (categories.Count > 0)
{
currentCategory = categories.Keys.First();
ShowCategoryItems(currentCategory);
}
}
}
private void RefreshCategoryList()
{
2025-03-12 15:18:23 +08:00
// 如果categories为空直接返回
if (categories == null)
return;
2025-03-17 23:34:35 +08:00
// 保存resizeHandle的引用
Panel savedResizeHandle = resizeHandle;
// 清除所有控件但保留resizeHandle
2025-03-12 14:06:44 +08:00
leftPanel.Controls.Clear();
2025-03-17 23:34:35 +08:00
// 重新添加resizeHandle
if (savedResizeHandle != null)
{
leftPanel.Controls.Add(savedResizeHandle);
savedResizeHandle.BringToFront();
}
2025-03-12 14:06:44 +08:00
int buttonY = 10;
foreach (var category in categories.Keys)
{
2025-03-12 15:18:23 +08:00
var categoryPanel = new RoundedPanel
2025-03-12 14:06:44 +08:00
{
Width = leftPanel.Width - 5,
Height = CATEGORY_BUTTON_HEIGHT,
2025-03-12 15:18:23 +08:00
Location = new Point(0, buttonY),
CornerRadius = cornerRadius
2025-03-12 14:06:44 +08:00
};
2025-03-12 15:18:23 +08:00
var btn = new RoundedButton
2025-03-12 14:06:44 +08:00
{
Text = category,
Width = leftPanel.Width - 20,
Height = CATEGORY_BUTTON_HEIGHT,
Location = new Point(10, 0),
FlatStyle = FlatStyle.Flat,
BackColor = category == currentCategory ?
accentColor :
2025-03-12 15:18:23 +08:00
(isDarkMode ? Color.FromArgb(60, 60, 60) : Color.FromArgb(230, 230, 230)),
ForeColor = category == currentCategory ?
Color.White :
2025-03-12 15:18:23 +08:00
(isDarkMode ? Color.FromArgb(240, 240, 240) : Color.FromArgb(20, 20, 20)),
Tag = category,
CornerRadius = cornerRadius,
FlatAppearance = { BorderSize = 0 }
2025-03-12 14:06:44 +08:00
};
// 移除旧的事件处理器
btn.Click -= null;
btn.Click += (s, e) =>
2025-03-12 14:06:44 +08:00
{
currentCategory = category;
foreach (Control panel in leftPanel.Controls)
{
if (panel is RoundedPanel && panel.Controls.Count > 0)
{
var button = panel.Controls[0] as RoundedButton;
if (button != null)
{
string btnCategory = button.Tag as string;
button.BackColor = btnCategory == category ?
accentColor :
(isDarkMode ? Color.FromArgb(60, 60, 60) : Color.FromArgb(230, 230, 230));
button.ForeColor = btnCategory == category ?
Color.White :
(isDarkMode ? Color.FromArgb(240, 240, 240) : Color.FromArgb(20, 20, 20));
}
}
}
2025-03-12 14:06:44 +08:00
ShowCategoryItems(category);
};
// 添加右键菜单
btn.ContextMenuStrip = categoryContextMenu;
categoryPanel.Controls.Add(btn);
categoryPanel.AllowDrop = true;
// 移除旧的事件处理器
categoryPanel.DragEnter -= null;
categoryPanel.DragDrop -= null;
categoryPanel.DragEnter += (s, e) =>
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
};
categoryPanel.DragDrop += (s, e) =>
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (string file in files)
{
if (File.Exists(file))
{
AddNewShortcut(file, category);
}
}
};
leftPanel.Controls.Add(categoryPanel);
buttonY += CATEGORY_BUTTON_HEIGHT + 5;
}
}
private void ShowCategoryItems(string category)
{
shortcutsPanel.Controls.Clear();
if (categories.ContainsKey(category))
{
// 更新顶部分类标签
categoryLabel.Text = $"当前分类: {category}";
// 根据设置的排序模式排序
List<ShortcutItem> sortedItems = categories[category];
switch (settings.SortMode)
{
case "Name":
sortedItems = sortedItems.OrderBy(s => s.Name).ToList();
break;
case "DateAdded":
sortedItems = sortedItems.OrderByDescending(s => s.DateAdded).ToList();
break;
case "UsageCount":
sortedItems = sortedItems.OrderByDescending(s => s.UsageCount).ToList();
break;
}
foreach (var item in sortedItems)
{
AddShortcutControl(item, category);
}
}
}
private void AddShortcutControl(ShortcutItem item, string category)
{
// 根据当前图标大小调整面板大小
int panelWidth = Math.Max(80, iconSize + 10);
int panelHeight = iconSize + 60;
2025-03-12 15:18:23 +08:00
var panel = new RoundedPanel
2025-03-12 14:06:44 +08:00
{
Width = panelWidth,
Height = panelHeight,
Margin = new Padding(5),
Tag = item,
2025-03-12 15:18:23 +08:00
BackColor = isDarkMode ? Color.FromArgb(50, 50, 50) : Color.FromArgb(245, 245, 245),
CornerRadius = cornerRadius
2025-03-12 14:06:44 +08:00
};
var icon = new PictureBox
{
Size = new Size(iconSize, iconSize),
Location = new Point((panel.Width - iconSize) / 2, 5),
2025-03-12 15:44:35 +08:00
Image = GetItemIcon(item),
SizeMode = PictureBoxSizeMode.Zoom,
2025-03-12 14:06:44 +08:00
Tag = item,
2025-03-12 15:44:35 +08:00
Cursor = Cursors.Hand
2025-03-12 14:06:44 +08:00
};
// 创建一个新的文本框控件实例
var label = new TextBox();
// 计算文本所需的高度
// TextRenderer.MeasureText: 测量指定文本在给定条件下需要的尺寸
// item.Name: 要显示的文本内容
// new Font(): 创建微软雅黑8号字体
// new Size(panel.Width, 0): 指定宽度限制,高度不限
// TextFormatFlags.WordBreak: 允许在单词间换行
// TextFormatFlags.TextBoxControl: 使用文本框的文本渲染规则
// .Height + 10: 获取计算出的高度并额外添加10像素的边距
2025-03-12 22:27:37 +08:00
var textHeight = TextRenderer.MeasureText(item.Name, new Font("Microsoft YaHei", 8), new Size(panel.Width, 0), TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl).Height + 10;
2025-03-12 22:27:37 +08:00
label.Text = item.Name; // 设置显示的文本内容
label.AutoSize = false; // 禁用自动尺寸调整
label.TextAlign = HorizontalAlignment.Center; // 文本水平居中对齐
label.MinimumSize = new Size(panel.Width, 30); // 设置最小尺寸
label.MaximumSize = new Size(panelWidth, 0); // 设置最大宽度,高度不限
2025-03-12 22:27:37 +08:00
label.Location = new Point(0, iconSize + 20); // 设置位置在图标下方10像素
label.Tag = item; // 存储关联的数据项
label.Cursor = Cursors.Hand; // 鼠标悬停时显示手型光标
label.ForeColor = isDarkMode ? Color.FromArgb(240, 240, 240) : Color.FromArgb(20, 20, 20); // 根据暗/亮模式设置文字颜色
label.Padding = new Padding(0); // 设置内边距为2像素
label.Font = new Font("Microsoft YaHei", 8); // 设置字体为微软雅黑8号
label.Multiline = true; // 启用多行显示
label.ReadOnly = true; // 设置为只读,防止编辑
label.BorderStyle = BorderStyle.None; // 移除边框
2025-03-12 22:27:37 +08:00
label.BackColor = panel.BackColor; // 背景色与面板一致
label.Height = textHeight; // 应用计算出的高度
// 将图标和文本框添加到面板中
panel.Controls.Add(icon); // 添加图标控件
panel.Controls.Add(label); // 添加文本框控件
2025-03-12 14:06:44 +08:00
// 设置右键菜单
panel.ContextMenuStrip = shortcutItemContextMenu;
icon.ContextMenuStrip = shortcutItemContextMenu;
label.ContextMenuStrip = shortcutItemContextMenu;
// 为右键菜单项设置Tag
//foreach (ToolStripItem menuItem in shortcutItemContextMenu.Items)
//{
// if (menuItem is ToolStripMenuItem)
// {
// menuItem.Tag = item;
// }
//}
// 添加鼠标右键点击事件,在显示菜单前绑定当前选中的 ShortcutItem
EventHandler rightClickHandler = (s, e) =>
2025-03-12 14:06:44 +08:00
{
if (s is Control control && control.Parent is RoundedPanel panel && panel.Tag is ShortcutItem item)
2025-03-12 14:06:44 +08:00
{
shortcutItemContextMenu.Tag = item; // 绑定当前选中的快捷方式
2025-03-12 14:06:44 +08:00
}
};
// 绑定到所有相关控件
panel.MouseDown += (s, e) => { if (e.Button == MouseButtons.Right) rightClickHandler(s, e); };
icon.MouseDown += (s, e) => { if (e.Button == MouseButtons.Right) rightClickHandler(s, e); };
label.MouseDown += (s, e) => { if (e.Button == MouseButtons.Right) rightClickHandler(s, e); };
2025-03-12 15:44:35 +08:00
// 双击事件 - 启动应用程序或预览图片
EventHandler doubleClickHandler = (s, e) =>
2025-03-12 15:44:35 +08:00
{
if (IsImageFile(item.Path))
{
ShowImagePreview(item.Path);
}
else
{
LaunchApplication(item.Path); // 启动应用程序
2025-03-12 15:44:35 +08:00
}
};
panel.DoubleClick += doubleClickHandler;
icon.DoubleClick += doubleClickHandler;
label.DoubleClick += doubleClickHandler;
2025-03-12 14:06:44 +08:00
// 添加鼠标悬停效果
panel.MouseEnter += Panel_MouseEnter;
panel.MouseLeave += Panel_MouseLeave;
icon.MouseEnter += Panel_MouseEnter;
icon.MouseLeave += Panel_MouseLeave;
label.MouseEnter += Panel_MouseEnter;
label.MouseLeave += Panel_MouseLeave;
2025-03-12 14:06:44 +08:00
// 添加鼠标点击效果
panel.MouseDown += Panel_MouseDown;
panel.MouseUp += Panel_MouseUp;
icon.MouseDown += Panel_MouseDown;
icon.MouseUp += Panel_MouseUp;
label.MouseDown += Panel_MouseDown;
label.MouseUp += Panel_MouseUp;
2025-03-12 15:44:35 +08:00
// 设置工具提示
string tipText = GetTooltipText(item);
2025-03-12 14:06:44 +08:00
toolTip1.SetToolTip(panel, tipText);
toolTip1.SetToolTip(icon, tipText);
toolTip1.SetToolTip(label, tipText);
2025-03-12 14:06:44 +08:00
shortcutsPanel.Controls.Add(panel);
}
2025-03-12 15:44:35 +08:00
private Image GetItemIcon(ShortcutItem item)
{
if (IsImageFile(item.Path))
{
try
{
// 为图片文件创建缩略图
using (var img = Image.FromFile(item.Path))
{
return new Bitmap(img, new Size(iconSize, iconSize));
}
}
catch
{
return item.Icon ?? SystemIcons.Application.ToBitmap();
}
}
return item.Icon ?? SystemIcons.Application.ToBitmap();
}
private bool IsImageFile(string path)
{
string ext = Path.GetExtension(path).ToLower();
return new[] { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".ico" }.Contains(ext);
}
private string GetTooltipText(ShortcutItem item)
{
string type = IsImageFile(item.Path) ? "图片文件" : "应用程序";
return $"名称: {item.Name}\n类型: {type}\n路径: {item.Path}\n" +
$"添加时间: {item.DateAdded:yyyy-MM-dd}\n使用次数: {item.UsageCount}";
}
private void ShowImagePreview(string imagePath)
{
try
{
using (var previewForm = new Form())
{
previewForm.Text = Path.GetFileName(imagePath);
previewForm.StartPosition = FormStartPosition.CenterScreen;
previewForm.BackColor = isDarkMode ? Color.FromArgb(32, 32, 32) : Color.FromArgb(243, 243, 243);
previewForm.WindowState = FormWindowState.Normal;
var pictureBox = new PictureBox
{
Dock = DockStyle.Fill,
SizeMode = PictureBoxSizeMode.Zoom,
Image = Image.FromFile(imagePath)
};
// 设置窗体大小为屏幕大小的80%
var screen = Screen.FromControl(this);
previewForm.Size = new Size(
(int)(screen.WorkingArea.Width * 0.8),
(int)(screen.WorkingArea.Height * 0.8)
);
// 添加ESC键关闭功能
previewForm.KeyPreview = true;
previewForm.KeyDown += (s, e) =>
2025-03-12 15:44:35 +08:00
{
if (e.KeyCode == Keys.Escape)
previewForm.Close();
};
// 添加鼠标滚轮缩放
pictureBox.MouseWheel += (s, e) =>
{
if (ModifierKeys == Keys.Control)
{
float zoom = e.Delta > 0 ? 1.1f : 0.9f;
pictureBox.Size = new Size(
(int)(pictureBox.Size.Width * zoom),
(int)(pictureBox.Size.Height * zoom)
);
}
};
var item = categories[currentCategory].FirstOrDefault(i => i.Path == imagePath);
if (item != null)
{
item.UsageCount++;
item.LastUsed = DateTime.Now;
SaveData();
}
2025-03-12 15:44:35 +08:00
previewForm.Controls.Add(pictureBox);
previewForm.ShowDialog();
}
}
catch (Exception ex)
{
MessageBox.Show($"无法预览图片: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
2025-03-12 14:06:44 +08:00
// 鼠标进入面板时的效果
private void Panel_MouseEnter(object sender, EventArgs e)
{
2025-03-12 15:18:23 +08:00
if (sender is Control control && control.Parent is RoundedPanel panel)
2025-03-12 14:06:44 +08:00
{
2025-03-12 15:18:23 +08:00
// 应用悬停效果
panel.BackColor = isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(230, 230, 230);
2025-03-12 15:18:23 +08:00
// 显示工具提示
if (panel.Tag is ShortcutItem item)
2025-03-12 14:06:44 +08:00
{
2025-03-12 15:18:23 +08:00
toolTip1.SetToolTip(panel, $"名称: {item.Name}\n路径: {item.Path}\n添加时间: {item.DateAdded.ToString("yyyy-MM-dd")}\n使用次数: {item.UsageCount}");
toolTip1.SetToolTip(control, $"名称: {item.Name}\n路径: {item.Path}\n添加时间: {item.DateAdded.ToString("yyyy-MM-dd")}\n使用次数: {item.UsageCount}");
2025-03-12 14:06:44 +08:00
}
}
2025-03-12 15:18:23 +08:00
else if (sender is RoundedPanel directPanel && directPanel.Tag is ShortcutItem directItem)
{
// 直接是面板的情况
directPanel.BackColor = isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(230, 230, 230);
toolTip1.SetToolTip(directPanel, $"名称: {directItem.Name}\n路径: {directItem.Path}\n添加时间: {directItem.DateAdded.ToString("yyyy-MM-dd")}\n使用次数: {directItem.UsageCount}");
}
2025-03-12 14:06:44 +08:00
}
// 鼠标离开面板时的效果
private void Panel_MouseLeave(object sender, EventArgs e)
{
2025-03-12 15:18:23 +08:00
if (sender is Control control && control.Parent is RoundedPanel panel)
2025-03-12 14:06:44 +08:00
{
2025-03-12 15:18:23 +08:00
// 恢复正常颜色
panel.BackColor = isDarkMode ? Color.FromArgb(50, 50, 50) : Color.FromArgb(245, 245, 245);
}
else if (sender is RoundedPanel directPanel)
{
// 直接是面板的情况
directPanel.BackColor = isDarkMode ? Color.FromArgb(50, 50, 50) : Color.FromArgb(245, 245, 245);
2025-03-12 14:06:44 +08:00
}
}
// 鼠标按下时的效果
private void Panel_MouseDown(object sender, MouseEventArgs e)
{
2025-03-12 15:18:23 +08:00
if (sender is Control control && control.Parent is RoundedPanel panel)
2025-03-12 14:06:44 +08:00
{
2025-03-12 15:18:23 +08:00
// 应用按下效果
panel.BackColor = isDarkMode ? Color.FromArgb(90, 90, 90) : Color.FromArgb(210, 210, 210);
}
else if (sender is RoundedPanel directPanel)
{
// 直接是面板的情况
directPanel.BackColor = isDarkMode ? Color.FromArgb(90, 90, 90) : Color.FromArgb(210, 210, 210);
2025-03-12 14:06:44 +08:00
}
}
// 鼠标释放时的效果
private void Panel_MouseUp(object sender, MouseEventArgs e)
{
2025-03-12 15:18:23 +08:00
if (sender is Control control && control.Parent is RoundedPanel panel)
2025-03-12 14:06:44 +08:00
{
2025-03-12 15:18:23 +08:00
// 恢复悬停颜色
panel.BackColor = isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(230, 230, 230);
}
else if (sender is RoundedPanel directPanel)
{
// 直接是面板的情况
directPanel.BackColor = isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(230, 230, 230);
2025-03-12 14:06:44 +08:00
}
}
// 添加面板鼠标移动事件处理
private void ShortcutsPanel_MouseMove(object sender, MouseEventArgs e)
{
// 获取鼠标位置下的控件
Control control = shortcutsPanel.GetChildAtPoint(e.Location);
2025-03-12 14:06:44 +08:00
// 如果鼠标不在任何子控件上,则隐藏工具提示
if (control == null)
{
toolTip1.RemoveAll();
}
}
// 添加工具提示组件
private ToolTip toolTip1 = new ToolTip();
private void AddButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(currentCategory))
{
MessageBox.Show("请先选择一个分类", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (OpenFileDialog dialog = new OpenFileDialog())
{
dialog.Filter = "应用程序|*.exe|所有文件|*.*";
if (dialog.ShowDialog() == DialogResult.OK)
{
AddNewShortcut(dialog.FileName, currentCategory);
}
}
}
private void AddNewShortcut(string filePath, string category)
{
// 放宽文件类型限制,允许任何文件类型
var item = new ShortcutItem
{
Name = Path.GetFileNameWithoutExtension(filePath),
Path = filePath,
DateAdded = DateTime.Now,
UsageCount = 0
};
item.LoadIcon();
categories[category].Add(item);
SaveData();
if (category == currentCategory)
{
ShowCategoryItems(category);
}
}
// 启动应用程序
2025-03-12 14:06:44 +08:00
private void LaunchApplication(string path)
{
try
{
// 查找并更新使用次数
if (!string.IsNullOrEmpty(currentCategory) && categories.ContainsKey(currentCategory))
{
var item = categories[currentCategory].FirstOrDefault(i => i.Path == path);
if (item != null)
{
item.UsageCount++;
item.LastUsed = DateTime.Now;
SaveData();
}
}
var startInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = path,
UseShellExecute = true
};
System.Diagnostics.Process.Start(startInfo);
}
catch (Exception ex)
{
MessageBox.Show($"启动程序失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void SaveData()
{
try
{
var options = new JsonSerializerOptions
{
WriteIndented = true
};
var data = JsonSerializer.Serialize(categories, options);
File.WriteAllText(dataFilePath, data);
}
catch (Exception ex)
{
MessageBox.Show($"保存配置失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadData()
{
if (File.Exists(dataFilePath))
{
try
{
var json = File.ReadAllText(dataFilePath);
categories = JsonSerializer.Deserialize<Dictionary<string, List<ShortcutItem>>>(json);
2025-03-12 14:06:44 +08:00
// 加载所有图标
foreach (var category in categories.Values)
{
foreach (var item in category)
{
item.LoadIcon();
}
}
2025-03-12 14:06:44 +08:00
RefreshCategoryList();
// 如果有上次选择的分类,则选择它
if (!string.IsNullOrEmpty(settings.LastSelectedCategory) && categories.ContainsKey(settings.LastSelectedCategory))
{
SwitchCategory(settings.LastSelectedCategory);
}
// 否则选择第一个分类
else if (categories.Count > 0)
{
SwitchCategory(categories.Keys.First());
}
2025-03-12 14:06:44 +08:00
}
catch (Exception ex)
{
MessageBox.Show($"加载配置失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
categories = new Dictionary<string, List<ShortcutItem>>();
}
}
else
{
// 如果没有数据文件,创建一个默认分类
categories = new Dictionary<string, List<ShortcutItem>>();
categories["默认分类"] = new List<ShortcutItem>();
SaveData();
RefreshCategoryList();
SwitchCategory("默认分类");
}
}
private void SwitchCategory(string category)
{
currentCategory = category;
RefreshCategoryList();
ShowCategoryItems(category);
SaveSettings(); // 保存当前选择的分类
}
private void button1_Click(object sender, EventArgs e)
{
isDarkMode = !isDarkMode; // 切换主题状态
ApplyTheme(isDarkMode);
}
private void ApplyTheme(bool darkMode)
{
if (darkMode)
{
ChangeTheme(true);
2025-03-12 14:06:44 +08:00
}
else
ChangeTheme(false);
2025-03-12 14:06:44 +08:00
}
2025-03-12 22:27:37 +08:00
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
Form1 form1 = new Form1();
form1.StartPosition = FormStartPosition.CenterParent;
form1.ShowDialog(this);
}
// 初始化通知图标和浮动图标
private void InitializeNotifyIcon()
{
try
{
// 创建通知区域图标
notifyIcon = new NotifyIcon
{
Icon = this.Icon,
Text = "工具箱",
Visible = true
};
// 创建右键菜单
ContextMenuStrip contextMenu = new ContextMenuStrip();
contextMenu.Items.Add("显示主窗口", null, (s, e) => { ShowMainWindowAndHideIcon(); });
contextMenu.Items.Add("-");
contextMenu.Items.Add("添加新快捷方式", null, (s, e) => { ShowMainWindowAndAddShortcut(); });
contextMenu.Items.Add("打开最近使用的项目", null, (s, e) => { ShowRecentItemsMenu(); });
contextMenu.Items.Add("-");
// 添加浮动图标控制选项
var floatingIconMenu = new ToolStripMenuItem("浮动图标");
floatingIconMenu.DropDownItems.Add("显示浮动图标", null, (s, e) => { ShowFloatingIcon(); });
floatingIconMenu.DropDownItems.Add("隐藏浮动图标", null, (s, e) => { HideFloatingIcon(); });
contextMenu.Items.Add(floatingIconMenu);
contextMenu.Items.Add("设置", null, (s, e) => { ShowSettingsDialog(); });
contextMenu.Items.Add("-");
contextMenu.Items.Add("退出", null, (s, e) => { ExitApplication(); });
// 应用主题颜色
contextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
notifyIcon.ContextMenuStrip = contextMenu;
notifyIcon.MouseClick += (s, e) =>
{
if (e.Button == MouseButtons.Left)
{
ShowMainWindowAndHideIcon();
}
};
// 创建浮动图标窗体
CreateFloatingIcon();
// 不再根据设置自动显示浮动图标
// 浮动图标只会在主窗口最小化或关闭时显示
}
catch (Exception ex)
{
// 记录错误但不中断程序运行
MessageBox.Show($"初始化通知图标时出错: {ex.Message}", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
// 显示主窗口并隐藏浮动图标
private void ShowMainWindowAndHideIcon()
{
HideFloatingIcon();
ShowMainWindow();
}
// 显示主窗口
private void ShowMainWindow()
{
this.Show();
this.WindowState = FormWindowState.Normal;
this.Activate();
}
// 重写窗体状态改变事件
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
// 当窗口最小化时,显示浮动图标
if (this.WindowState == FormWindowState.Minimized)
{
this.Hide();
ShowFloatingIcon();
}
}
// 重写窗体关闭事件
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true; // 取消关闭操作
this.Hide(); // 隐藏窗体
ShowFloatingIcon(); // 显示浮动图标
}
else
{
// 清理资源
if (notifyIcon != null)
{
notifyIcon.Visible = false;
notifyIcon.Dispose();
}
if (floatingIcon != null && !floatingIcon.IsDisposed)
{
floatingIcon.Close();
floatingIcon.Dispose();
}
base.OnFormClosing(e);
}
}
// 创建浮动图标窗体
private void CreateFloatingIcon()
{
try
{
floatingIcon = new Form
{
Size = new Size(64, 64), // 增大尺寸,更容易点击
FormBorderStyle = FormBorderStyle.None,
ShowInTaskbar = false,
TopMost = true,
StartPosition = FormStartPosition.Manual,
TransparencyKey = Color.Magenta, // 设置透明色
BackColor = Color.Magenta, // 设置背景色为透明色
Visible = false // 确保创建时默认隐藏
};
// 创建一个圆形面板作为图标容器
RoundedPanel iconPanel = new RoundedPanel
{
Size = new Size(64, 64), // 增大尺寸
Location = new Point(0, 0),
CornerRadius = 60, // 完全圆形
BackColor = Color.FromArgb(50, 50, 50) // 使用强调色,更加醒目
};
// 添加阴影效果
iconPanel.Paint += (s, e) =>
{
// 设置高质量绘图模式
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
// 绘制阴影
using (GraphicsPath path = new GraphicsPath())
{
path.AddEllipse(0, 0, iconPanel.Width, iconPanel.Height);
// 创建渐变背景
Color baseColor = isDarkMode ? Color.FromArgb(50, 50, 50) : Color.FromArgb(240, 240, 240);
Color gradientColor = isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(220, 220, 220);
using (LinearGradientBrush bgBrush = new LinearGradientBrush(
new Point(0, 0),
new Point(0, iconPanel.Height),
baseColor,
gradientColor))
{
e.Graphics.FillPath(bgBrush, path);
}
// 创建阴影效果
using (PathGradientBrush brush = new PathGradientBrush(path))
{
brush.CenterColor = Color.FromArgb(0, 0, 0, 0);
brush.SurroundColors = new Color[] { Color.FromArgb(80, 0, 0, 0) }; // 增强阴影效果
brush.WrapMode = WrapMode.Clamp;
// 绘制阴影
e.Graphics.FillPath(brush, path);
}
// 绘制边框 - 使用白色或深色边框增加对比度
using (Pen pen = new Pen(isDarkMode ? Color.FromArgb(180, 180, 180) : Color.FromArgb(50, 50, 50), 1.5f))
{
// 设置平滑连接和端点
pen.LineJoin = LineJoin.Round;
pen.StartCap = LineCap.Round;
pen.EndCap = LineCap.Round;
pen.Alignment = PenAlignment.Center; // 确保边框居中对齐
// 使用更平滑的方式绘制圆形
e.Graphics.DrawEllipse(pen, 0, 0, iconPanel.Width - 1, iconPanel.Height - 1);
}
// 添加内部边框,创造更精致的外观
using (Pen innerPen = new Pen(isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(220, 220, 220), 1f))
{
innerPen.LineJoin = LineJoin.Round;
innerPen.StartCap = LineCap.Round;
innerPen.EndCap = LineCap.Round;
innerPen.Alignment = PenAlignment.Center; // 确保边框居中对齐
// 使用更平滑的方式绘制内部圆形
e.Graphics.DrawEllipse(innerPen, 2, 2, iconPanel.Width - 5, iconPanel.Height - 5);
}
}
};
// 添加图标
PictureBox iconBox = new PictureBox
{
Size = new Size(48, 48), // 稍微调整图标尺寸
Location = new Point(8, 8), // 居中放置
SizeMode = PictureBoxSizeMode.StretchImage,
BackColor = Color.Transparent // 使用透明背景,让图标更清晰
};
// 尝试加载自定义图标
Image iconImage = null;
if (!string.IsNullOrEmpty(settings.FloatingIconPath) && File.Exists(settings.FloatingIconPath))
{
try
{
iconImage = Image.FromFile(settings.FloatingIconPath);
}
catch
{
// 如果加载失败,使用默认图标
iconImage = this.Icon.ToBitmap();
}
}
else
{
// 使用默认图标
iconImage = this.Icon.ToBitmap();
}
// 优化图标显示
try {
// 尝试创建高质量图标
Bitmap highQualityIcon = new Bitmap(48, 48);
using (Graphics g = Graphics.FromImage(highQualityIcon))
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(iconImage, 0, 0, 48, 48);
}
iconBox.Image = highQualityIcon;
}
catch {
// 如果失败,使用原始图标
iconBox.Image = iconImage;
}
iconPanel.Controls.Add(iconBox);
floatingIcon.Controls.Add(iconPanel);
// 添加鼠标事件
bool isDragging = false;
Point dragStartPoint = Point.Empty;
// 添加双击事件
iconPanel.DoubleClick += (s, e) => {
ShowMainWindowAndHideIcon();
};
iconBox.DoubleClick += (s, e) => {
ShowMainWindowAndHideIcon();
};
// 鼠标进入时的效果 - 使用更明显的高亮效果
iconPanel.MouseEnter += (s, e) =>
{
// 高亮效果 - 使用更亮的颜色
Color brighterColor = Color.FromArgb(
Math.Min(Color.FromArgb(50, 50, 50).R + 30, 255),
Math.Min(Color.FromArgb(50, 50, 50).G + 30, 255),
Math.Min(Color.FromArgb(50, 50, 50).B + 30, 255)
);
iconPanel.BackColor = brighterColor;
// 不再设置窗体背景色
};
// 鼠标离开时的效果
iconPanel.MouseLeave += (s, e) =>
{
iconPanel.BackColor = Color.FromArgb(50, 50, 50);
// 不再设置窗体背景色
};
iconPanel.MouseDown += (s, e) =>
{
if (e.Button == MouseButtons.Left)
{
isDragging = true;
dragStartPoint = e.Location;
// 按下效果 - 使用更深的颜色
Color darkerColor = Color.FromArgb(
Math.Max(Color.FromArgb(50, 50, 50).R - 30, 0),
Math.Max(Color.FromArgb(50, 50, 50).G - 30, 0),
Math.Max(Color.FromArgb(50, 50, 50).B - 30, 0)
);
iconPanel.BackColor = darkerColor;
// 不再设置窗体背景色
}
};
iconPanel.MouseMove += (s, e) =>
{
if (isDragging)
{
// 计算新位置
Point newLocation = new Point(
floatingIcon.Location.X + e.X - dragStartPoint.X,
floatingIcon.Location.Y + e.Y - dragStartPoint.Y
);
// 确保不超出屏幕边界
newLocation = EnsureIconOnScreen(newLocation);
// 应用新位置
floatingIcon.Location = newLocation;
}
};
iconPanel.MouseUp += (s, e) =>
{
if (isDragging)
{
isDragging = false;
// 恢复悬停效果
Color brighterColor = Color.FromArgb(
Math.Min(Color.FromArgb(50, 50, 50).R + 30, 255),
Math.Min(Color.FromArgb(50, 50, 50).G + 30, 255),
Math.Min(Color.FromArgb(50, 50, 50).B + 30, 255)
);
iconPanel.BackColor = brighterColor;
// 不再设置窗体背景色
}
else if (e.Button == MouseButtons.Left)
{
// 单击左键时显示主窗口并隐藏浮动图标
ShowMainWindowAndHideIcon();
}
};
// 为图标也添加相同的事件处理
iconBox.MouseEnter += (s, e) => {
// 使用与面板相同的高亮效果
Color brighterColor = Color.FromArgb(
Math.Min(Color.FromArgb(50, 50, 50).R + 30, 255),
Math.Min(Color.FromArgb(50, 50, 50).G + 30, 255),
Math.Min(Color.FromArgb(50, 50, 50).B + 30, 255)
);
iconPanel.BackColor = brighterColor;
// 不再设置窗体背景色
};
iconBox.MouseLeave += (s, e) => {
// 恢复正常颜色
iconPanel.BackColor = Color.FromArgb(50, 50, 50);
// 不再设置窗体背景色
};
iconBox.MouseDown += (s, e) => {
if (e.Button == MouseButtons.Left)
{
isDragging = true;
dragStartPoint = e.Location;
// 按下效果 - 使用更深的颜色
Color darkerColor = Color.FromArgb(
Math.Max(Color.FromArgb(50, 50, 50).R - 30, 0),
Math.Max(Color.FromArgb(50, 50, 50).G - 30, 0),
Math.Max(Color.FromArgb(50, 50, 50).B - 30, 0)
);
iconPanel.BackColor = darkerColor;
// 不再设置窗体背景色
}
};
iconBox.MouseMove += (s, e) => {
if (isDragging)
{
// 计算新位置
Point newLocation = new Point(
floatingIcon.Location.X + e.X - dragStartPoint.X,
floatingIcon.Location.Y + e.Y - dragStartPoint.Y
);
// 确保不超出屏幕边界
newLocation = EnsureIconOnScreen(newLocation);
// 应用新位置
floatingIcon.Location = newLocation;
}
};
iconBox.MouseUp += (s, e) => {
if (isDragging)
{
isDragging = false;
// 恢复悬停效果
Color brighterColor = Color.FromArgb(
Math.Min(Color.FromArgb(50, 50, 50).R + 30, 255),
Math.Min(Color.FromArgb(50, 50, 50).G + 30, 255),
Math.Min(Color.FromArgb(50, 50, 50).B + 30, 255)
);
iconPanel.BackColor = brighterColor;
// 不再设置窗体背景色
}
else if (e.Button == MouseButtons.Left)
{
// 单击左键时显示主窗口并隐藏浮动图标
ShowMainWindowAndHideIcon();
}
};
// 右键菜单
ContextMenuStrip iconMenu = new ContextMenuStrip();
iconMenu.Items.Add("显示主窗口", null, (s, e) => { ShowMainWindowAndHideIcon(); });
iconMenu.Items.Add("-");
iconMenu.Items.Add("添加新快捷方式", null, (s, e) => { ShowMainWindowAndAddShortcut(); });
iconMenu.Items.Add("打开最近使用的项目", null, (s, e) => { ShowRecentItemsMenu(); });
iconMenu.Items.Add("-");
iconMenu.Items.Add("修改浮动按钮图标", null, (s, e) => { ChangeFloatingIconImage(); });
iconMenu.Items.Add("-");
iconMenu.Items.Add("设置", null, (s, e) => { ShowSettingsDialog(); });
iconMenu.Items.Add("-");
iconMenu.Items.Add("退出", null, (s, e) => { ExitApplication(); });
// 应用主题颜色
iconMenu.Renderer = new ModernMenuRenderer(isDarkMode);
iconPanel.ContextMenuStrip = iconMenu;
iconBox.ContextMenuStrip = iconMenu;
}
catch (Exception ex)
{
MessageBox.Show($"创建浮动图标时出错: {ex.Message}", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
// 显示主窗口并立即打开添加快捷方式对话框
private void ShowMainWindowAndAddShortcut()
{
ShowMainWindowAndHideIcon();
// 等待主窗口完全显示
this.BeginInvoke(new Action(() =>
{
if (!string.IsNullOrEmpty(currentCategory))
{
AddButton_Click(null, EventArgs.Empty);
}
else
{
MessageBox.Show("请先选择一个分类", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}));
}
// 显示最近使用的项目菜单
private void ShowRecentItemsMenu()
{
try
{
// 创建一个临时菜单
ContextMenuStrip recentMenu = new ContextMenuStrip();
recentMenu.Renderer = new ModernMenuRenderer(isDarkMode);
// 获取最近使用的项目所有分类中按最后使用时间排序的前10个项目
var recentItems = categories
.SelectMany(c => c.Value)
.Where(item => item.LastUsed > DateTime.MinValue)
.OrderByDescending(item => item.LastUsed)
.Take(10)
.ToList();
if (recentItems.Count > 0)
{
foreach (var item in recentItems)
{
var menuItem = new ToolStripMenuItem(item.Name);
// 尝试设置图标
try
{
if (item.Icon != null)
{
menuItem.Image = new Bitmap(item.Icon, new Size(16, 16));
}
}
catch { }
menuItem.Tag = item;
menuItem.Click += (s, e) =>
{
if (s is ToolStripMenuItem mi && mi.Tag is ShortcutItem shortcut)
{
LaunchApplication(shortcut.Path);
}
};
recentMenu.Items.Add(menuItem);
}
}
else
{
var noItemsMenuItem = new ToolStripMenuItem("没有最近使用的项目");
noItemsMenuItem.Enabled = false;
recentMenu.Items.Add(noItemsMenuItem);
}
// 显示菜单
recentMenu.Show(Cursor.Position);
}
catch (Exception ex)
{
MessageBox.Show($"显示最近使用项目时出错: {ex.Message}", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
// 显示设置对话框
private void ShowSettingsDialog()
{
ShowMainWindowAndHideIcon();
// 等待主窗口完全显示
this.BeginInvoke(new Action(() =>
{
// 这里可以打开设置对话框
MessageBox.Show("设置功能尚未实现", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}));
}
// 退出应用程序
private void ExitApplication()
{
// 确认是否退出
if (MessageBox.Show("确定要退出程序吗?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
try
{
// 保存设置
SaveSettings();
// 清理资源
if (notifyIcon != null)
{
notifyIcon.Visible = false;
notifyIcon.Dispose();
notifyIcon = null;
}
if (floatingIcon != null && !floatingIcon.IsDisposed)
{
floatingIcon.Close();
floatingIcon.Dispose();
floatingIcon = null;
}
// 使用 ExitThread 而不是 Exit
Application.ExitThread();
}
catch (Exception ex)
{
MessageBox.Show($"退出程序时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
// 如果出错,强制退出
Environment.Exit(0);
}
}
}
// 显示浮动图标
private void ShowFloatingIcon()
{
if (floatingIcon == null)
{
try
{
CreateFloatingIcon();
}
catch (Exception ex)
{
MessageBox.Show($"创建浮动图标时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
if (!isFloatingIconVisible && floatingIcon != null)
{
try
{
// 设置初始位置(屏幕右侧中间)
Screen screen = Screen.PrimaryScreen;
// 如果有保存的位置,使用保存的位置
Point iconPosition;
if (settings.FloatingIconPosition.X != 0 && settings.FloatingIconPosition.Y != 0)
{
iconPosition = settings.FloatingIconPosition;
// 确保图标在屏幕内
iconPosition = EnsureIconOnScreen(iconPosition);
}
else
{
// 默认位置:屏幕右侧中间
iconPosition = new Point(
screen.WorkingArea.Right - floatingIcon.Width - 20,
screen.WorkingArea.Bottom / 2 - floatingIcon.Height / 2
);
}
floatingIcon.Location = iconPosition;
floatingIcon.Show();
isFloatingIconVisible = true;
// 移除淡入效果代码,直接显示
}
catch (Exception ex)
{
MessageBox.Show($"显示浮动图标时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
// 隐藏浮动图标
private void HideFloatingIcon()
{
if (isFloatingIconVisible && floatingIcon != null)
{
try
{
// 保存当前位置
settings.FloatingIconPosition = floatingIcon.Location;
SaveSettings();
// 移除淡出效果代码,直接隐藏
floatingIcon.Hide();
isFloatingIconVisible = false;
}
catch (Exception ex)
{
// 如果出现错误,尝试直接隐藏
try
{
floatingIcon.Hide();
isFloatingIconVisible = false;
}
catch { }
MessageBox.Show($"隐藏浮动图标时出错: {ex.Message}", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
// 完全重写确保图标在屏幕内的方法
private Point EnsureIconOnScreen(Point position)
{
if (floatingIcon == null)
return position;
// 获取包含该点的屏幕
Screen screen = Screen.FromPoint(position);
if (screen == null)
{
screen = Screen.PrimaryScreen;
}
Rectangle workArea = screen.WorkingArea;
// 获取浮动图标的实际大小
int iconWidth = floatingIcon.Width;
int iconHeight = floatingIcon.Height;
// 计算实际可见图标的大小(圆形部分)
int visibleIconSize = 64; // 圆形图标的直径
// 计算边缘偏移量
int leftOffset = 0; // 左侧不需要偏移
int topOffset = 0; // 顶部不需要偏移
int rightOffset = iconWidth - visibleIconSize; // 右侧偏移量等于窗体宽度减去可见图标宽度
int bottomOffset = iconHeight - visibleIconSize; // 底部偏移量等于窗体高度减去可见图标高度
// 为了确保图标能够完全贴近右侧边缘,额外增加偏移量
//rightOffset += 10; // 额外增加20像素的偏移量
// 确保X坐标在屏幕内
if (position.X < workArea.Left - leftOffset)
{
position.X = workArea.Left - leftOffset;
}
else if (position.X + iconWidth > workArea.Right + rightOffset)
{
// 确保图标可以完全贴近屏幕右侧边缘
position.X = workArea.Right + rightOffset - iconWidth;
}
// 确保Y坐标在屏幕内
if (position.Y < workArea.Top - topOffset)
{
position.Y = workArea.Top - topOffset;
}
else if (position.Y + iconHeight > workArea.Bottom + bottomOffset)
{
position.Y = workArea.Bottom + bottomOffset - iconHeight;
}
return position;
}
// 切换浮动图标显示状态
private void ToggleFloatingIcon()
{
if (isFloatingIconVisible)
HideFloatingIcon();
else
ShowFloatingIcon();
}
// 修改浮动按钮图标
private void ChangeFloatingIconImage()
{
try
{
// 显示文件选择对话框
using (OpenFileDialog dialog = new OpenFileDialog())
{
dialog.Title = "选择新的浮动按钮图标";
dialog.Filter = "图标文件|*.ico;*.png;*.jpg;*.jpeg;*.bmp;*.gif|所有文件|*.*";
dialog.Multiselect = false;
if (dialog.ShowDialog() == DialogResult.OK)
{
string iconPath = dialog.FileName;
// 检查文件是否存在
if (!File.Exists(iconPath))
{
MessageBox.Show("选择的文件不存在", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 尝试加载图标
try
{
Image newIcon = Image.FromFile(iconPath);
// 查找浮动图标中的PictureBox控件
if (floatingIcon != null && !floatingIcon.IsDisposed)
{
foreach (Control control in floatingIcon.Controls)
{
if (control is RoundedPanel panel)
{
foreach (Control panelControl in panel.Controls)
{
if (panelControl is PictureBox iconBox)
{
// 更新图标
iconBox.Image = newIcon;
// 保存图标路径到设置
settings.FloatingIconPath = iconPath;
SaveSettings();
MessageBox.Show("浮动按钮图标已更新", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
}
}
}
}
MessageBox.Show("无法找到浮动按钮图标控件", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex)
{
MessageBox.Show($"加载图标文件失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show($"修改浮动按钮图标时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
2025-03-12 14:06:44 +08:00
}
public class ShortcutItem
{
public string Name { get; set; }
public string Path { get; set; }
[System.Text.Json.Serialization.JsonIgnore]
public Bitmap Icon { get; set; }
public DateTime DateAdded { get; set; } = DateTime.Now;
public DateTime LastUsed { get; set; } = DateTime.MinValue;
public int UsageCount { get; set; } = 0;
2025-03-12 15:18:23 +08:00
public string Description { get; set; } = ""; // 添加描述属性
public string Arguments { get; set; } = ""; // 添加启动参数
public bool RunAsAdmin { get; set; } = false; // 是否以管理员身份运行
public string Category { get; set; } = ""; // 所属分类
public string CustomIconPath { get; set; } = ""; // 自定义图标路径
public string BackgroundColor { get; set; } = ""; // 自定义背景色
public int SortOrder { get; set; } = 0; // 排序顺序
2025-03-12 14:06:44 +08:00
// 用于序列化的构造函数
public ShortcutItem()
{
}
// 加载图标的方法
public void LoadIcon()
{
try
{
2025-03-12 15:18:23 +08:00
// 如果有自定义图标,优先使用自定义图标
if (!string.IsNullOrEmpty(CustomIconPath) && File.Exists(CustomIconPath))
{
try
{
// 尝试加载自定义图标
using (System.Drawing.Icon customIcon = new System.Drawing.Icon(CustomIconPath))
{
Icon = customIcon.ToBitmap();
return;
}
}
catch
{
// 如果自定义图标加载失败,继续使用默认图标
}
}
// 使用关联图标
2025-03-12 14:06:44 +08:00
if (File.Exists(Path))
{
using (System.Drawing.Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(Path))
{
if (icon != null)
{
Icon = icon.ToBitmap();
}
else
{
Icon = SystemIcons.Application.ToBitmap();
}
}
}
else
{
Icon = SystemIcons.Application.ToBitmap();
}
}
catch
{
Icon = SystemIcons.Application.ToBitmap();
}
}
2025-03-12 15:18:23 +08:00
// 获取格式化的最后使用时间
public string GetFormattedLastUsed()
{
if (LastUsed == DateTime.MinValue)
return "从未使用";
TimeSpan span = DateTime.Now - LastUsed;
if (span.TotalDays > 365)
return $"{Math.Floor(span.TotalDays / 365)}年前";
if (span.TotalDays > 30)
return $"{Math.Floor(span.TotalDays / 30)}个月前";
if (span.TotalDays > 1)
return $"{Math.Floor(span.TotalDays)}天前";
if (span.TotalHours > 1)
return $"{Math.Floor(span.TotalHours)}小时前";
if (span.TotalMinutes > 1)
return $"{Math.Floor(span.TotalMinutes)}分钟前";
return "刚刚";
}
// 获取背景颜色
public Color GetBackgroundColor(bool isDarkMode)
{
// 如果有自定义背景色,尝试解析
if (!string.IsNullOrEmpty(BackgroundColor))
{
try
{
// 尝试解析颜色字符串,格式为 R,G,B
string[] parts = BackgroundColor.Split(',');
if (parts.Length == 3 &&
int.TryParse(parts[0], out int r) &&
int.TryParse(parts[1], out int g) &&
int.TryParse(parts[2], out int b))
{
return Color.FromArgb(r, g, b);
}
}
catch
{
// 解析失败,使用默认颜色
}
}
// 返回默认颜色
return isDarkMode ? Color.FromArgb(50, 50, 50) : Color.FromArgb(245, 245, 245);
}
}
// 添加GDI+扩展方法
public static class GraphicsExtensions
{
public static void FillRoundedRectangle(this Graphics graphics, Brush brush, Rectangle bounds, int cornerRadius)
{
if (graphics == null)
throw new ArgumentNullException("graphics");
if (brush == null)
throw new ArgumentNullException("brush");
// 设置高质量绘图模式
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
2025-03-12 15:18:23 +08:00
using (GraphicsPath path = CreateRoundedRectangle(bounds, cornerRadius))
{
graphics.FillPath(brush, path);
}
}
public static void DrawRoundedRectangle(this Graphics graphics, Pen pen, Rectangle bounds, int cornerRadius)
{
if (graphics == null)
throw new ArgumentNullException("graphics");
if (pen == null)
throw new ArgumentNullException("pen");
// 设置高质量绘图模式
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
// 设置平滑连接和端点
pen.LineJoin = LineJoin.Round;
pen.StartCap = LineCap.Round;
pen.EndCap = LineCap.Round;
2025-03-12 15:18:23 +08:00
using (GraphicsPath path = CreateRoundedRectangle(bounds, cornerRadius))
{
graphics.DrawPath(pen, path);
}
}
private static GraphicsPath CreateRoundedRectangle(Rectangle bounds, int cornerRadius)
{
GraphicsPath path = new GraphicsPath();
if (cornerRadius > 0)
{
path.AddArc(bounds.X, bounds.Y, cornerRadius * 2, cornerRadius * 2, 180, 90);
path.AddArc(bounds.Right - cornerRadius * 2, bounds.Y, cornerRadius * 2, cornerRadius * 2, 270, 90);
path.AddArc(bounds.Right - cornerRadius * 2, bounds.Bottom - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 0, 90);
path.AddArc(bounds.X, bounds.Bottom - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 90, 90);
path.CloseFigure();
}
else
{
path.AddRectangle(bounds);
}
return path;
}
2025-03-12 14:06:44 +08:00
}
}