ToolBox/MainForm.cs
2025-03-12 15:18:23 +08:00

1579 lines
62 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Linq;
using System.Runtime.InteropServices; // 添加P/Invoke支持
using System.Drawing.Drawing2D; // 添加GDI+支持
using Microsoft.Win32; // 添加Registry访问支持
namespace QuickLauncher
{
public partial class MainForm : Form
{
// 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;
public int CornerRadius
{
get { return _cornerRadius; }
set { _cornerRadius = value; Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// 创建圆角路径
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();
this.Region = new Region(path);
}
}
}
// 添加圆角按钮支持的类
private class RoundedButton : Button
{
private int _cornerRadius = 8;
public int CornerRadius
{
get { return _cornerRadius; }
set { _cornerRadius = value; Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// 创建圆角路径
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();
this.Region = new Region(path);
}
}
}
// 原有的字段
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; // 增加每次缩放的步长
// 左侧面板调整相关
private bool isResizing = false;
private int resizingStartX = 0;
private int initialPanelWidth = 0;
private const int MIN_PANEL_WIDTH = 200;
private const int MAX_PANEL_WIDTH = 500;
private Panel resizeHandle;
// 用于保存设置的类
private class AppSettings
{
public string LastSelectedCategory { get; set; } = "";
public string SortMode { get; set; } = "Name"; // Name, DateAdded
public int IconSize { get; set; } = 48; // 保存图标大小
public int LeftPanelWidth { get; set; } = 300; // 左侧面板宽度
}
private AppSettings settings = new AppSettings();
public MainForm()
{
InitializeComponent();
// 配置工具提示 - 调整为更合适的值
toolTip1 = new ToolTip();
toolTip1.AutoPopDelay = 5000;
toolTip1.InitialDelay = 200; // 稍微增加初始延迟
toolTip1.ReshowDelay = 200; // 稍微增加重新显示延迟
toolTip1.ShowAlways = true;
toolTip1.UseFading = true;
toolTip1.IsBalloon = false; // 使用标准样式
// 初始化数据和UI
InitializeUI();
// 应用Windows 11风格
ApplyWin11Style();
SetupContextMenus();
SetupEventHandlers();
LoadSettings();
LoadData();
SelectDefaultCategory();
// 监听系统主题变化
SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
}
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();
// 重新应用Windows 11风格
ApplyWin11Style();
}
// 应用Windows 11风格
private void ApplyWin11Style()
{
// 检测系统主题
isDarkMode = IsSystemUsingSysemDarkTheme();
// 应用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));
// 应用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;
}
// 应用主题颜色
ApplyThemeColors();
}
// 检测系统是否使用深色主题
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 { }
return false;
}
// 应用主题颜色
private void ApplyThemeColors()
{
// 设置主窗体颜色
this.ForeColor = isDarkMode ? darkTextColor : lightTextColor;
// 设置左侧面板颜色
leftPanel.BackColor = isDarkMode ? Color.FromArgb(40, 40, 40) : Color.FromArgb(243, 243, 243);
// 设置右侧面板颜色
rightPanel.BackColor = isDarkMode ? Color.FromArgb(32, 32, 32) : Color.FromArgb(250, 250, 250);
// 设置工具面板颜色
toolPanel.BackColor = isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(230, 230, 230);
// 设置快捷方式面板颜色
shortcutsPanel.BackColor = isDarkMode ? Color.FromArgb(32, 32, 32) : Color.FromArgb(250, 250, 250);
// 设置添加按钮颜色
addButton.BackColor = accentColor;
addButton.ForeColor = Color.White;
addButton.FlatAppearance.BorderSize = 0;
// 设置菜单颜色
menuStrip.BackColor = isDarkMode ? Color.FromArgb(45, 45, 45) : Color.FromArgb(230, 230, 230);
menuStrip.ForeColor = isDarkMode ? darkTextColor : lightTextColor;
// 设置菜单项颜色
foreach (ToolStripMenuItem item in menuStrip.Items)
{
item.ForeColor = isDarkMode ? Color.White : Color.Black;
// 设置下拉菜单项颜色
foreach (ToolStripItem dropItem in item.DropDownItems)
{
if (dropItem is ToolStripMenuItem menuItem)
{
menuItem.ForeColor = isDarkMode ? Color.White : Color.Black;
}
}
}
// 设置菜单渲染器
menuStrip.Renderer = new ModernMenuRenderer(isDarkMode);
// 刷新分类列表和当前分类的快捷方式仅当categories已初始化时
if (categories != null)
{
RefreshCategoryList();
if (!string.IsNullOrEmpty(currentCategory))
{
ShowCategoryItems(currentCategory);
}
}
}
// 设置上下文菜单
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));
// 应用主题颜色
categoryContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
// 右侧面板右键菜单
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("-"); // 分隔线
// 添加图标大小调整菜单,增加更多选项
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);
// 添加主题切换选项
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);
// 应用主题颜色
shortcutsPanelContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
// 快捷方式项目右键菜单
shortcutItemContextMenu = new ContextMenuStrip();
shortcutItemContextMenu.Items.Add("启动", null, (s, e) =>
{
if (s is ToolStripMenuItem menuItem && menuItem.Tag is ShortcutItem item)
{
LaunchApplication(item.Path);
}
});
shortcutItemContextMenu.Items.Add("删除", null, (s, e) =>
{
if (s is ToolStripMenuItem menuItem && menuItem.Tag is ShortcutItem item)
{
DeleteShortcut(item);
}
});
shortcutItemContextMenu.Items.Add("重命名", null, (s, e) =>
{
if (s is ToolStripMenuItem menuItem && menuItem.Tag is ShortcutItem item)
{
RenameShortcut(item);
}
});
shortcutItemContextMenu.Items.Add("属性", null, (s, e) =>
{
if (s is ToolStripMenuItem menuItem && menuItem.Tag is ShortcutItem item)
{
ShowShortcutProperties(item);
}
});
// 应用主题颜色
shortcutItemContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
}
// 切换主题
private void ChangeTheme(bool darkMode)
{
isDarkMode = darkMode;
ApplyThemeColors();
// 更新上下文菜单渲染器
categoryContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
shortcutsPanelContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
shortcutItemContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
}
// 跟随系统主题
private void FollowSystemTheme()
{
isDarkMode = IsSystemUsingSysemDarkTheme();
ApplyThemeColors();
// 更新上下文菜单渲染器
categoryContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
shortcutsPanelContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
shortcutItemContextMenu.Renderer = new ModernMenuRenderer(isDarkMode);
}
// 现代菜单渲染器
private class ModernMenuRenderer : ToolStripProfessionalRenderer
{
private bool _isDarkMode;
public ModernMenuRenderer(bool isDarkMode) : base(new ModernColorTable(isDarkMode))
{
_isDarkMode = isDarkMode;
}
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);
}
}
}
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);
}
}
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
// 菜单文本颜色
e.TextColor = _isDarkMode ? Color.FromArgb(240, 240, 240) : Color.FromArgb(20, 20, 20);
base.OnRenderItemText(e);
}
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);
}
}
}
// 现代菜单颜色表
private class ModernColorTable : ProfessionalColorTable
{
private bool _isDarkMode;
public ModernColorTable(bool isDarkMode)
{
_isDarkMode = isDarkMode;
}
// 菜单项
public override Color MenuItemSelected => _isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(210, 230, 250);
public override Color MenuItemBorder => Color.Transparent;
// 菜单栏
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);
// 工具栏
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);
}
// 调整图标大小
private void ResizeIcons(int newSize)
{
if (newSize >= MIN_ICON_SIZE && newSize <= MAX_ICON_SIZE)
{
iconSize = newSize;
settings.IconSize = iconSize;
SaveSettings();
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 };
var button = new Button() { Text = "确定", DialogResult = DialogResult.OK, Location = new Point(110, 60) };
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;
string oldCategory = currentCategory;
currentCategory = newName;
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 };
var button = new Button() { Text = "确定", DialogResult = DialogResult.OK, Location = new Point(110, 60) };
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 };
var button = new Button() { Text = "确定", DialogResult = DialogResult.OK, Location = new Point(150, 220) };
dialog.Controls.AddRange(new Control[] { icon, nameLabel, nameValue, pathLabel, pathValue,
dateLabel, dateValue, usageLabel, usageValue, button });
dialog.AcceptButton = button;
dialog.ShowDialog();
}
}
// 选择默认分类
private void SelectDefaultCategory()
{
// 如果没有分类,不做任何操作
if (categories.Count == 0)
return;
// 尝试选择上次选择的分类
if (!string.IsNullOrEmpty(settings.LastSelectedCategory) &&
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;
settings.LeftPanelWidth = leftPanel.Width;
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; // 加载保存的图标大小
leftPanel.Width = settings.LeftPanelWidth;
}
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;
// 添加鼠标滚轮事件处理
shortcutsPanel.MouseWheel += ShortcutsPanel_MouseWheel;
// 为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;
}
}
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()
{
// 初始化数据
categories = new Dictionary<string, List<ShortcutItem>>();
// 设置窗体样式
this.FormBorderStyle = FormBorderStyle.Sizable;
this.MinimumSize = new Size(800, 600);
// 设置控件样式
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);
// 设置分类标签样式
categoryLabel.Font = new Font("Microsoft YaHei UI", 11);
categoryLabel.ForeColor = isDarkMode ? Color.Black : Color.White;
// 创建左侧面板调整手柄
CreateResizeHandle();
// 刷新分类列表
RefreshCategoryList();
}
// 创建左侧面板调整手柄
private void CreateResizeHandle()
{
// 创建调整手柄
resizeHandle = new Panel
{
Width = 5,
Dock = DockStyle.Right,
Cursor = Cursors.SizeWE,
BackColor = Color.Transparent
};
// 添加鼠标事件
resizeHandle.MouseDown += ResizeHandle_MouseDown;
resizeHandle.MouseMove += ResizeHandle_MouseMove;
resizeHandle.MouseUp += ResizeHandle_MouseUp;
// 添加到左侧面板
leftPanel.Controls.Add(resizeHandle);
resizeHandle.BringToFront();
}
// 调整手柄鼠标按下事件
private void ResizeHandle_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
isResizing = true;
resizingStartX = e.X;
initialPanelWidth = leftPanel.Width;
// 捕获鼠标
resizeHandle.Capture = true;
}
}
// 调整手柄鼠标移动事件
private void ResizeHandle_MouseMove(object sender, MouseEventArgs e)
{
if (isResizing)
{
// 计算新宽度
int newWidth = initialPanelWidth + (e.X - resizingStartX);
// 限制宽度范围
if (newWidth < MIN_PANEL_WIDTH)
newWidth = MIN_PANEL_WIDTH;
else if (newWidth > MAX_PANEL_WIDTH)
newWidth = MAX_PANEL_WIDTH;
// 设置新宽度
leftPanel.Width = newWidth;
// 刷新布局
this.PerformLayout();
// 刷新分类列表,以适应新宽度
RefreshCategoryList();
}
}
// 调整手柄鼠标释放事件
private void ResizeHandle_MouseUp(object sender, MouseEventArgs e)
{
if (isResizing)
{
isResizing = false;
// 释放鼠标捕获
resizeHandle.Capture = false;
// 保存设置
settings.LeftPanelWidth = leftPanel.Width;
SaveSettings();
}
}
private void AddCategory_Click(object sender, EventArgs e)
{
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;
dialog.BackColor = isDarkMode ? Color.FromArgb(32, 32, 32) : Color.FromArgb(243, 243, 243);
dialog.ForeColor = isDarkMode ? Color.White : Color.Black;
var label = new Label() {
Text = "分类名称:",
Location = new Point(10, 20),
ForeColor = isDarkMode ? Color.White : Color.Black
};
var textBox = new TextBox() {
Location = new Point(120, 17),
Width = 180,
BackColor = isDarkMode ? Color.FromArgb(45, 45, 45) : Color.White,
ForeColor = isDarkMode ? Color.White : Color.Black
};
var button = new RoundedButton() {
Text = "确定",
DialogResult = DialogResult.OK,
Location = new Point(110, 60),
Width = 100,
Height = 30,
BackColor = Color.FromArgb(210, 210, 210, 200), // 自定义RGB颜色
ForeColor = Color.FromArgb(40, 40, 40),
CornerRadius = cornerRadius
};
dialog.Controls.AddRange(new Control[] { label, textBox, button });
dialog.AcceptButton = button;
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();
// 自动选择新创建的分类
currentCategory = newCategory;
ShowCategoryItems(currentCategory);
}
}
}
}
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 = "";
// 删除分类后,选择新的默认分类
if (categories.Count > 0)
{
currentCategory = categories.Keys.First();
ShowCategoryItems(currentCategory);
}
}
}
private void RefreshCategoryList()
{
// 如果categories为空直接返回
if (categories == null)
return;
leftPanel.Controls.Clear();
int buttonY = 10;
foreach (var category in categories.Keys)
{
var categoryPanel = new RoundedPanel
{
Width = leftPanel.Width - 5,
Height = CATEGORY_BUTTON_HEIGHT,
Location = new Point(0, buttonY),
CornerRadius = cornerRadius
};
var btn = new RoundedButton
{
Text = category,
Width = leftPanel.Width - 20,
Height = CATEGORY_BUTTON_HEIGHT,
Location = new Point(10, 0),
FlatStyle = FlatStyle.Flat,
BackColor = category == currentCategory ?
accentColor :
(isDarkMode ? Color.FromArgb(60, 60, 60) : Color.FromArgb(230, 230, 230)),
ForeColor = category == currentCategory ?
Color.White :
(isDarkMode ? Color.FromArgb(240, 240, 240) : Color.FromArgb(20, 20, 20)),
Tag = category,
CornerRadius = cornerRadius,
FlatAppearance = { BorderSize = 0 }
};
// 移除旧的事件处理器
btn.Click -= null;
btn.Click += (s, e) =>
{
currentCategory = category;
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;
var panel = new RoundedPanel
{
Width = panelWidth,
Height = panelHeight,
Margin = new Padding(5),
Tag = item,
BackColor = isDarkMode ? Color.FromArgb(50, 50, 50) : Color.FromArgb(245, 245, 245),
CornerRadius = cornerRadius
};
var icon = new PictureBox
{
Size = new Size(iconSize, iconSize),
Location = new Point((panel.Width - iconSize) / 2, 5),
Image = item.Icon ?? SystemIcons.Application.ToBitmap(),
SizeMode = PictureBoxSizeMode.StretchImage,
Tag = item,
Cursor = Cursors.Hand // 鼠标悬停时显示手型光标
};
var label = new Label
{
Text = item.Name,
AutoSize = false,
TextAlign = ContentAlignment.MiddleCenter,
Width = panel.Width,
Height = 30,
Location = new Point(0, iconSize + 10),
Tag = item,
Cursor = Cursors.Hand, // 鼠标悬停时显示手型光标
ForeColor = isDarkMode ? Color.FromArgb(240, 240, 240) : Color.FromArgb(20, 20, 20)
};
panel.Controls.Add(icon);
panel.Controls.Add(label);
// 设置右键菜单
panel.ContextMenuStrip = shortcutItemContextMenu;
icon.ContextMenuStrip = shortcutItemContextMenu;
label.ContextMenuStrip = shortcutItemContextMenu;
// 为右键菜单项设置Tag
foreach (ToolStripItem menuItem in shortcutItemContextMenu.Items)
{
if (menuItem is ToolStripMenuItem)
{
menuItem.Tag = item;
}
}
// 移除旧的事件处理器并重新绑定
panel.DoubleClick -= null;
icon.DoubleClick -= null;
label.DoubleClick -= null;
// 双击事件 - 启动应用程序
panel.DoubleClick += (s, e) => LaunchApplication(item.Path);
icon.DoubleClick += (s, e) => LaunchApplication(item.Path);
label.DoubleClick += (s, e) => LaunchApplication(item.Path);
// 添加鼠标悬停效果
panel.MouseEnter += Panel_MouseEnter;
panel.MouseLeave += Panel_MouseLeave;
icon.MouseEnter += Panel_MouseEnter;
icon.MouseLeave += Panel_MouseLeave;
label.MouseEnter += Panel_MouseEnter;
label.MouseLeave += Panel_MouseLeave;
// 添加鼠标点击效果
panel.MouseDown += Panel_MouseDown;
panel.MouseUp += Panel_MouseUp;
icon.MouseDown += Panel_MouseDown;
icon.MouseUp += Panel_MouseUp;
label.MouseDown += Panel_MouseDown;
label.MouseUp += Panel_MouseUp;
// 直接设置工具提示
string tipText = $"名称: {item.Name}\n路径: {item.Path}\n双击启动";
toolTip1.SetToolTip(panel, tipText);
toolTip1.SetToolTip(icon, tipText);
toolTip1.SetToolTip(label, tipText);
shortcutsPanel.Controls.Add(panel);
}
// 鼠标进入面板时的效果
private void Panel_MouseEnter(object sender, EventArgs e)
{
if (sender is Control control && control.Parent is RoundedPanel panel)
{
// 应用悬停效果
panel.BackColor = isDarkMode ? Color.FromArgb(70, 70, 70) : Color.FromArgb(230, 230, 230);
// 显示工具提示
if (panel.Tag is ShortcutItem item)
{
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}");
}
}
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}");
}
}
// 鼠标离开面板时的效果
private void Panel_MouseLeave(object sender, EventArgs e)
{
if (sender is Control control && control.Parent is RoundedPanel panel)
{
// 恢复正常颜色
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);
}
}
// 鼠标按下时的效果
private void Panel_MouseDown(object sender, MouseEventArgs e)
{
if (sender is Control control && control.Parent is RoundedPanel panel)
{
// 应用按下效果
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);
}
}
// 鼠标释放时的效果
private void Panel_MouseUp(object sender, MouseEventArgs e)
{
if (sender is Control control && control.Parent is RoundedPanel panel)
{
// 恢复悬停颜色
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);
}
}
// 添加面板鼠标移动事件处理
private void ShortcutsPanel_MouseMove(object sender, MouseEventArgs e)
{
// 获取鼠标位置下的控件
Control control = shortcutsPanel.GetChildAtPoint(e.Location);
// 如果鼠标不在任何子控件上,则隐藏工具提示
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);
}
}
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);
// 加载所有图标
foreach (var category in categories.Values)
{
foreach (var item in category)
{
item.LoadIcon();
}
}
RefreshCategoryList();
}
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();
}
}
}
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;
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; // 排序顺序
// 用于序列化的构造函数
public ShortcutItem()
{
}
// 加载图标的方法
public void LoadIcon()
{
try
{
// 如果有自定义图标,优先使用自定义图标
if (!string.IsNullOrEmpty(CustomIconPath) && File.Exists(CustomIconPath))
{
try
{
// 尝试加载自定义图标
using (System.Drawing.Icon customIcon = new System.Drawing.Icon(CustomIconPath))
{
Icon = customIcon.ToBitmap();
return;
}
}
catch
{
// 如果自定义图标加载失败,继续使用默认图标
}
}
// 使用关联图标
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();
}
}
// 获取格式化的最后使用时间
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");
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");
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;
}
}
}