正确做法是先用GraphicsPath构建圆角路径并赋给Region属性以定义可交互区域,再在OnPaint中根据鼠标状态重绘,配合抗锯齿和高DPI适配。

用 GraphicsPath 截取控件区域再重绘背景
WinForms 默认按钮和 PictureBox 都是矩形裁剪,想实现圆角或圆形,核心不是“画个圆”,而是**提前告诉系统:这个控件的可点击/可绘制区域不是矩形**。直接重写 OnPaint 只画圆角边框没用——鼠标事件仍按矩形响应,背景色也盖不住原角。
正确做法是在 OnPaint 前,用 GraphicsPath 构建路径,再赋给控件的 Region 属性:
protected override void OnPaint(PaintEventArgs e) {
using (var path = new GraphicsPath()) {
// 圆角矩形:左上、右上、右下、左下半径都为 8
path.AddArc(0, 0, 16, 16, 180, 90); // 左上
path.AddArc(Width - 16, 0, 16, 16, -90, 90); // 右上
path.AddArc(Width - 16, Height - 16, 16, 16, 0, 90); // 右下
path.AddArc(0, Height - 16, 16, 16, 90, 90); // 左下
path.CloseFigure();
Region = new Region(path);
}
base.OnPaint(e);
}
注意:Region 设置必须在 base.OnPaint(e) 之前,否则无效;且仅对当前控件生效,子控件不受影响。
圆角按钮要响应鼠标悬停和点击状态,得重写 OnMouseEnter/OnMouseLeave 并缓存状态
单纯靠 Region 裁剪后,按钮视觉上变圆了,但 :hover 这类状态在 WinForms 里没有自动机制。你得自己记状态、触发重绘:
- 声明私有字段
private bool _isHovered;和private bool _isPressed; - 在
OnMouseEnter里设_isHovered = true;并调用Invalidate(); - 在
OnMouseLeave里设_isHovered = false;并调用Invalidate(); - 在
OnMouseDown中设_isPressed = true;,OnMouseUp中设_isPressed = false;,都调Invalidate();
然后在 OnPaint 里根据这些布尔值切换填充色或边框粗细。别忘了调用 e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;,否则圆角边缘锯齿明显。
画圆形图片不能只靠 DrawImage 缩放,得用 TextureBrush 或二次裁剪
把一张方形图变成圆形显示,常见错误是直接 e.Graphics.DrawImage(img, rect) 并把 rect 设成正方形——这只会拉伸图像。真正靠谱的是两种方式:
-
用
TextureBrush+ 圆形路径:先创建圆形GraphicsPath,再用该路径定义Region,最后用TextureBrush填充这个区域(需确保图片尺寸与控件匹配) -
离屏绘制 +
SetClip:创建一个与控件同尺寸的Bitmap,在其Graphics上先画圆(用FillEllipse),再调graphics.SetClip(new Rectangle(...)),最后DrawImage—— 图像只在圆形区域内显现
推荐后者,控制更直观。注意:SetClip 后所有后续绘制都会被裁剪,记得用 graphics.ResetClip() 恢复。
高 DPI 下圆角会模糊或错位,必须启用 SetStyle 并处理缩放
WinForms 在高 DPI 缩放(如 125%、150%)下,Width/Height 返回的是逻辑像素,但 GraphicsPath 构建时若用整数坐标,会导致圆角半径失真。解决方案分两步:
- 构造控件时调用
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw, true); - 在计算圆角路径前,用
Graphics.DpiX和DpiY获取当前缩放比例,把设计时的“8px 半径”换算成设备像素:int radius = (int)(8f * e.Graphics.DpiX / 96f);
不处理 DPI,你在 4K 屏上看到的圆角按钮可能一边圆一边方,或者点击区域和视觉完全不重合。










