如何在自定义的WinForms按钮中使用OnPaint绘制可缩放的勾号?
我在WinForms中创建一个自定义的圆形按钮。我可以使用 DrawEllipse 成功绘制圆形。然而,我不知道如何计算正确的等比例坐标,在按钮内部绘制一个可缩放的勾号,以便它能正确调整大小。如何计算勾号的等比例点,使其与按钮的大小正确缩放?
public class MyButton : Button
{
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics graphics = e.Graphics;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle rectangle = new Rectangle();
rectangle.Height = 111;
rectangle.Width = 100;
graphics.FillEllipse(Brushes.White, rectangle);
graphics.DrawEllipse(Pens.White, rectangle);
}
}
解决方案
以下是在按钮内绘制可缩放文本的做法:
if (Text is { Length: > 0 }) {
SizeF textSize = e.Graphics.MeasureString(Text, Font);
float scale = Math.Min(Width / textSize.Width, Height / textSize.Height);
e.Graphics.TranslateTransform((Width - textSize.Width * scale) / 2, (Height - textSize.Height * scale) / 2);
e.Graphics.ScaleTransform(scale, scale);
using var textBrush = new SolidBrush(ForeColor);
e.Graphics.DrawString(Text, Font, textBrush, (RectangleF)ClientRectangle);
}
然后你可以在按钮的 Text 属性中使用以下其中一个Unicode勾号:
- ✓ U+2713(勾号)
- ✔ U+2714(粗勾号)
- ✅ U+2705(白色粗勾号)
- ☑ U+2611(带勾的选票框)
- 🗸 U+1F5F8(轻勾号)
- 🗹 U+1F5F9(带粗勾的选票框)
并非所有字体都包含这些字符。此外,某些字体可能需要对缩放系数和定位进行一些调整。
下面是我的椭圆形按钮的完整代码。请注意,它暴露了一些属性,允许你在属性编辑器中更改按钮的外观:
public class EllipseButton : Control
{
private Color _borderColor = Color.DimGray;
[Category("Appearance"), DefaultValue(typeof(Color), "DimGray")]
public Color BorderColor
{
get => _borderColor;
set {
_borderColor = value;
Invalidate();
}
}
private Color _buttonBackColor = Color.LightCoral;
[Category("Appearance"), DefaultValue(typeof(Color), "LightCoral")]
public Color ButtonBackColor
{
get => _buttonBackColor;
set {
_buttonBackColor = value;
Invalidate();
}
}
private float _borderWidth = 2.5f;
[Category("Appearance"), DefaultValue(2.5f)]
public float BorderWidth
{
get => _borderWidth;
set {
_borderWidth = value;
Invalidate();
}
}
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override Color BackColor { get => base.BackColor; set => base.BackColor = value; }
protected override void OnParentChanged(EventArgs e)
{
if (Parent is not null) {
BackColor = Parent.BackColor;
Parent.BackColorChanged += (s, e) => BackColor = Parent.BackColor;
}
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.Clear(BackColor);
RectangleF rect = ClientRectangle;
float halfBorder = -0.5f * BorderWidth;
rect.Inflate(halfBorder, halfBorder);
rect.Width -= 1;
rect.Height -= 1;
using var buttonBrush = new SolidBrush(ButtonBackColor);
e.Graphics.FillEllipse(buttonBrush, rect);
using var borderPen = new Pen(BorderColor, BorderWidth);
e.Graphics.DrawEllipse(borderPen, rect);
if (Text is { Length: > 0 }) {
SizeF textSize = e.Graphics.MeasureString(Text, Font);
float scale = Math.Min(
(Width - BorderWidth) / textSize.Width,
(Height - BorderWidth) / textSize.Height);
e.Graphics.TranslateTransform((Width - textSize.Width * scale) / 2, (Height - textSize.Height * scale) / 2);
e.Graphics.ScaleTransform(scale, scale);
using var textBrush = new SolidBrush(ForeColor);
e.Graphics.DrawString(Text, Font, textBrush, (RectangleF)ClientRectangle);
}
}
}
BackColor 在属性窗口中是隐藏的,并且会自动设置以匹配表单或容器控件的颜色。相反,暴露了一个 ButtonBackColor 属性,以及 BorderColor 和 BorderWidth。
按钮可以具有任意尺寸,并且不是硬编码的。ForeColor 用作文本颜色。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。