From 3fe559694156ed5726c6324f1e83a3fe0cba4cbf Mon Sep 17 00:00:00 2001 From: zhubanghao <58813184@qq.com> Date: Tue, 20 Jan 2026 09:05:19 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=98=BA=20=E6=96=B0=E5=A2=9E=20=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B=20BallTest=20=E6=82=AC=E6=B5=AE=E7=90=83=E7=AA=97?= =?UTF-8?q?=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AntdUI.sln | 9 +- example/BallTest/BallLayeredForm.cs | 387 ++++++++++++++++++++++++++ example/BallTest/BallLayeredForm.resx | 120 ++++++++ example/BallTest/BallTest.csproj | 20 ++ example/BallTest/Program.cs | 26 ++ 5 files changed, 561 insertions(+), 1 deletion(-) create mode 100644 example/BallTest/BallLayeredForm.cs create mode 100644 example/BallTest/BallLayeredForm.resx create mode 100644 example/BallTest/BallTest.csproj create mode 100644 example/BallTest/Program.cs diff --git a/AntdUI.sln b/AntdUI.sln index 77a03c95..8aa89b39 100644 --- a/AntdUI.sln +++ b/AntdUI.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.1.11312.151 d18.0 +VisualStudioVersion = 18.1.11312.151 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{B9AB491E-DDF2-4E3D-97FA-622E36504B91}" EndProject @@ -23,6 +23,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{3762ED79-9 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphemeSplitterTest", "test\GraphemeSplitterTest\GraphemeSplitterTest.csproj", "{01ACFED0-8673-06F4-52A8-D45E69339517}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BallTest", "example\BallTest\BallTest.csproj", "{6EF92ED2-D4CF-A5F8-09EF-FDE92C580659}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +59,10 @@ Global {01ACFED0-8673-06F4-52A8-D45E69339517}.Debug|Any CPU.Build.0 = Debug|Any CPU {01ACFED0-8673-06F4-52A8-D45E69339517}.Release|Any CPU.ActiveCfg = Release|Any CPU {01ACFED0-8673-06F4-52A8-D45E69339517}.Release|Any CPU.Build.0 = Release|Any CPU + {6EF92ED2-D4CF-A5F8-09EF-FDE92C580659}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6EF92ED2-D4CF-A5F8-09EF-FDE92C580659}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6EF92ED2-D4CF-A5F8-09EF-FDE92C580659}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6EF92ED2-D4CF-A5F8-09EF-FDE92C580659}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -69,6 +75,7 @@ Global {94493153-4FF8-4F33-8589-D72A8563AF52} = {B9AB491E-DDF2-4E3D-97FA-622E36504B91} {3A032088-E22D-BFA0-83BC-B0CD61CAD7BF} = {5243A57B-3E12-49E1-BA51-CBB5D786193F} {01ACFED0-8673-06F4-52A8-D45E69339517} = {3762ED79-94BC-42B3-A024-E0F1F375BCEB} + {6EF92ED2-D4CF-A5F8-09EF-FDE92C580659} = {B9AB491E-DDF2-4E3D-97FA-622E36504B91} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6B151716-3D07-4DA4-8C4D-2D2BBE164EAA} diff --git a/example/BallTest/BallLayeredForm.cs b/example/BallTest/BallLayeredForm.cs new file mode 100644 index 00000000..0e810879 --- /dev/null +++ b/example/BallTest/BallLayeredForm.cs @@ -0,0 +1,387 @@ +using AntdUI; +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace BallTest +{ + public partial class BallLayeredForm : ILayeredFormOpacity + { + #region 属性 + // 防误触阈值 + private const int DRAG_THRESHOLD = 5; + + // 拖动相关变量 + private Point? dragStartPoint = null; + private bool isBeingDragged = false; + private bool isClick = false; + + // 鼠标悬停状态 + private bool isMouseOver = false; + /// + /// 菜单项列表 - 使用AntdUI控件 + /// + private AntdUI.IContextMenuStripItem[] menuItems; + #region 颜色配置字段 - 封装颜色定义,便于自定义和修改 + + private Color _normalStartColor = Color.FromArgb(0, 128, 255); // 正常状态起始颜色 + private Color _normalEndColor = Color.FromArgb(0, 75, 150); // 正常状态结束颜色 + private Color _hoverStartColor = Color.FromArgb(0, 191, 255); // 悬停状态起始颜色 + private Color _hoverEndColor = Color.FromArgb(0, 100, 200); // 悬停状态结束颜色 + private Color _highlightColor1 = Color.White; // 主高光颜色 + private int _highlightAlpha1 = 150; // 主高光透明度 + private Color _highlightColor2 = Color.White; // 次高光颜色 + private int _highlightAlpha2 = 100; // 次高光透明度 + private Color _borderColor = Color.FromArgb(0, 50, 100); // 边框颜色 + private int _borderAlpha = 120; // 边框透明度 + private int _borderWidth = 2; // 边框宽度 + + // 颜色配置公共属性,便于外部自定义 + // 添加DesignerSerializationVisibility特性以解决WFO1000警告 + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public Color NormalStartColor + { + get => _normalStartColor; + set { _normalStartColor = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public Color NormalEndColor + { + get => _normalEndColor; + set { _normalEndColor = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public Color HoverStartColor + { + get => _hoverStartColor; + set { _hoverStartColor = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public Color HoverEndColor + { + get => _hoverEndColor; + set { _hoverEndColor = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public Color HighlightColor1 + { + get => _highlightColor1; + set { _highlightColor1 = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public int HighlightAlpha1 + { + get => _highlightAlpha1; + set { _highlightAlpha1 = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public Color HighlightColor2 + { + get => _highlightColor2; + set { _highlightColor2 = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public int HighlightAlpha2 + { + get => _highlightAlpha2; + set { _highlightAlpha2 = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public Color BorderColor + { + get => _borderColor; + set { _borderColor = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public int BorderAlpha + { + get => _borderAlpha; + set { _borderAlpha = value; Print(); } + } + + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public int BorderWidth + { + get => _borderWidth; + set { _borderWidth = value; Print(); } + } + + #endregion + #endregion + + #region 构造相关的方法 + public BallLayeredForm() : base(255) + { + // 设置默认大小和位置 + int size = 200; + int x = Screen.PrimaryScreen.Bounds.Width / 2 - size / 2; + int y = Screen.PrimaryScreen.Bounds.Height / 2 - size / 2; + + SetSize(size, size); + SetLocation(x, y); + // 同时设置Size和Location属性,确保窗体正确显示 + Size = new Size(size, size); + Location = new Point(x, y); + + // 设置为最顶层窗口,确保能看到 + TopMost = true; + + // 初始化菜单项 + InitializeMenuItems(); + } + + public override bool UFocus => false; + + public override string name => nameof(BallLayeredForm); + + // 初始化菜单项 + private void InitializeMenuItems() + { + + string svg_back = "", svg_refresh = "", svg_save = "", svg_print = "", svg_laptop = "", svg_qr = "", svg_a = "", svg_fy = "", svg_add = "", svg_share = "", svg_about = ""; + + menuItems = new AntdUI.IContextMenuStripItem[] + { + new AntdUI.ContextMenuStripItem("返回", "Alt+向左键").SetIcon(svg_back), + new AntdUI.ContextMenuStripItem("刷新", "Ctrl+R").SetIcon(svg_refresh), + new AntdUI.ContextMenuStripItemDivider(), + new AntdUI.ContextMenuStripItem("另存为", "Ctrl+S").SetIcon(svg_save), + new AntdUI.ContextMenuStripItem("打印", "Ctrl+P").SetIcon(svg_print), + new AntdUI.ContextMenuStripItemDivider(), + new AntdUI.ContextMenuStripItem("发送标签页到你的设备").SetIcon(svg_laptop), + new AntdUI.ContextMenuStripItem("为此页面创建QR代码").SetIcon(svg_qr), + new AntdUI.ContextMenuStripItem("大声朗读", "Ctrl+Shift+U").SetIcon(svg_a), + new AntdUI.ContextMenuStripItem("翻译为 中文(简体)").SetIcon(svg_fy), + new AntdUI.ContextMenuStripItem("将页面添加到集锦").SetIcon(svg_add).SetSub( + new AntdUI.ContextMenuStripItem("返回", "Alt+向左键").SetIcon(svg_back).SetSub( + new AntdUI.ContextMenuStripItem("返回", "Alt+向左键").SetIcon(svg_back), + new AntdUI.ContextMenuStripItem("刷新", "Ctrl+R").SetIcon(svg_refresh), + new AntdUI.ContextMenuStripItemDivider(), + new AntdUI.ContextMenuStripItem("另存为", "Ctrl+S").SetIcon(svg_save), + new AntdUI.ContextMenuStripItem("打印", "Ctrl+P").SetIcon(svg_print) + ), + new AntdUI.ContextMenuStripItem("刷新", "Ctrl+R").SetIcon(svg_refresh), + new AntdUI.ContextMenuStripItemDivider(), + new AntdUI.ContextMenuStripItem("另存为", "Ctrl+S").SetIcon(svg_save), + new AntdUI.ContextMenuStripItem("打印", "Ctrl+P").SetIcon(svg_print) + ), + new AntdUI.ContextMenuStripItemDivider(), + new AntdUI.ContextMenuStripItem("共享").SetIcon(svg_share), + new AntdUI.ContextMenuStripItem("关于").SetIcon(svg_about) + }; + } + #endregion + + #region 鼠标相关事件 + protected override void OnHandleCreated(EventArgs e) + { + base.OnHandleCreated(e); + // 窗口句柄创建后立即渲染 + Print(); + } + + public override Bitmap? PrintBit() + { + // 获取目标区域大小 + var rect = TargetRect; + var rectXY = TargetRectXY; + + // 创建一个与目标区域大小相同的位图,使用32位ARGB格式 + var bitmap = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + + using (var g = Graphics.FromImage(bitmap)) + { + // 设置高质量绘图选项 + g.SmoothingMode = SmoothingMode.AntiAlias; + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + + // 清除背景(透明) + g.Clear(Color.Transparent); + + // 绘制渐变圆球 + int centerX = rect.Width / 2; + int centerY = rect.Height / 2; + int radius = Math.Min(centerX, centerY) - 10; + + // 根据鼠标状态选择渐变颜色 + Color startColor = isMouseOver ? _hoverStartColor : _normalStartColor; + Color endColor = isMouseOver ? _hoverEndColor : _normalEndColor; + + // 使用线性渐变,从左上角到右下角 + using (var gradientBrush = new LinearGradientBrush( + new Point(centerX - radius, centerY - radius), + new Point(centerX + radius, centerY + radius), + startColor, + endColor)) + { + // 绘制圆形主体 + g.FillEllipse(gradientBrush, centerX - radius, centerY - radius, radius * 2, radius * 2); + + // 添加多层次高光,增强立体感 + // 主高光:左上角明亮的白色椭圆形高光(参考图片2) + using (var highlightBrush1 = new SolidBrush(Color.FromArgb(_highlightAlpha1, _highlightColor1))) + { + int highlightWidth = radius * 3 / 2; + int highlightHeight = radius * 3 / 4; + g.FillEllipse(highlightBrush1, + centerX - highlightWidth / 2, + centerY - highlightHeight / 2 - radius / 6, + highlightWidth, highlightHeight); + } + + // 次高光:中心位置的白色高亮区 + using (var highlightBrush2 = new SolidBrush(Color.FromArgb(_highlightAlpha2, _highlightColor2))) + { + int centerHighlightSize = radius * 2 / 3; + g.FillEllipse(highlightBrush2, + centerX - centerHighlightSize / 2, + centerY - centerHighlightSize / 2, + centerHighlightSize, centerHighlightSize); + } + + // 调整边框:使用深蓝色边框,更精致 + using (var pen = new Pen(Color.FromArgb(_borderAlpha, _borderColor), _borderWidth)) + { + g.DrawEllipse(pen, centerX - radius, centerY - radius, radius * 2, radius * 2); + } + } + } + + return bitmap; + } + + protected override void OnMouseEnter(EventArgs e) + { + isMouseOver = true; + Print(); + base.OnMouseEnter(e); + } + + protected override void OnMouseLeave(EventArgs e) + { + isMouseOver = false; + Print(); + base.OnMouseLeave(e); + } + + // 鼠标按下事件,开始拖动或显示右键菜单 + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + if (e.Button == MouseButtons.Left) + { + isClick = true; + dragStartPoint = e.Location; + // 更改光标样式 + Cursor = Cursors.SizeAll; + } + else if (e.Button == MouseButtons.Right) + { + // 获取鼠标在屏幕上的位置 + Point screenPos = PointToScreen(e.Location); + + // 显示AntdUI右键菜单 + var config = new AntdUI.ContextMenuStrip.Config(new AntdUI.Target(this), item => + { + // 处理菜单项点击事件 + //switch (item.Text) + //{ + // case "返回": + // // 移动功能已通过拖动实现 + + // break; + // case "刷新": + // // IClose(true); + // break; + // case "关于": + // break; + //} + AntdUI.Notification.open(this, item.Text, "AntdUI 作者人不错", TAlignFrom.Top); + }, menuItems) + { + Location = screenPos, // 设置菜单位置为当前鼠标位置 + TopMost = true + }; + AntdUI.ContextMenuStrip.open(config); + } + } + + // 鼠标移动事件,处理拖动 + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + // 处理拖动逻辑 + if (dragStartPoint.HasValue) + { + int deltaX = e.X - dragStartPoint.Value.X; + int deltaY = e.Y - dragStartPoint.Value.Y; + + // 检查是否超过防误触阈值 + if (!isBeingDragged && (Math.Abs(deltaX) > DRAG_THRESHOLD || Math.Abs(deltaY) > DRAG_THRESHOLD)) + { + isBeingDragged = true; + isClick = false; + } + + if (isBeingDragged) + { + // 更新位置 + var rect = TargetRect; + int newX = rect.X + deltaX; + int newY = rect.Y + deltaY; + + // 设置新位置 + SetLocation(newX, newY); + Location = new Point(newX, newY); + + // 使用PrintCache优化拖动性能 + PrintCache(); + } + } + } + + // 鼠标释放事件,结束拖动 + protected override void OnMouseUp(MouseEventArgs e) + { + base.OnMouseUp(e); + + // 恢复默认光标 + Cursor = DefaultCursor; + + // 处理点击事件 + if (isClick && !isBeingDragged) + { + // 左键点击关闭窗口 + if (e.Button == MouseButtons.Left) + { + //IClose(true); + } + } + + // 重置拖动状态 + dragStartPoint = null; + isBeingDragged = false; + isClick = false; + } + + protected override void OnMouseClick(MouseEventArgs e) + { + base.OnMouseClick(e); + // 右键点击事件已由ContextMenuStrip处理 + } + #endregion + } + + +} \ No newline at end of file diff --git a/example/BallTest/BallLayeredForm.resx b/example/BallTest/BallLayeredForm.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/example/BallTest/BallLayeredForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/example/BallTest/BallTest.csproj b/example/BallTest/BallTest.csproj new file mode 100644 index 00000000..443cdc96 --- /dev/null +++ b/example/BallTest/BallTest.csproj @@ -0,0 +1,20 @@ + + + + WinExe + net8.0-windows + true + enable + + + + + + + + + Form + + + + \ No newline at end of file diff --git a/example/BallTest/Program.cs b/example/BallTest/Program.cs new file mode 100644 index 00000000..d9977845 --- /dev/null +++ b/example/BallTest/Program.cs @@ -0,0 +1,26 @@ +using System; +using System.Windows.Forms; +using AntdUI; + +namespace BallTest +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + // 创建并显示圆球窗体 + var ballForm = new BallLayeredForm(); + ballForm.Show(); + + // 运行应用程序消息循环 + Application.Run(); + } + } +} \ No newline at end of file