Winform控件优化Paint事件实现圆角组件及提取绘制圆角的方法

目录
  • 前言
  • Paint事件中实现圆角控件
  • 提取绘制圆角矩形和旁边小尖角的代码为扩展方法
    • 介绍
    • 扩展方法
    • 测试尖角的显示位置
  • 重绘控件后文本的处理
    • 同时重绘文本
    • 通过添加Label控件实现对文本的处理【有尖角时需要额外处理】
  • Paint事件中绘制圆角的优点
  • 窗体失去焦点时按钮外观边框问题
  • Paint事件中绘制控件的问题【不要使用(事件)参数e.ClipRectangle】

前言

Windows 11下所有控件已经默认采用圆角,其效果更好、相对有着更好的优化,只是这是默认的行为,无法进一步自定义。

注意两点:

  • Paint事件方法中实现圆角控件不要通过事件参数e.ClipRectangle获取控件区域范围
  • 注意设置控件背景透明(虽然Winform中的透明不是完全透明,

实现圆角控件比较好的一个思路是在控件的Paint事件中进行绘制,不太好的地方在于每次实现时都要添加事件处理,且不能在设计器中实时看到效果。

只要有Paint事件的组件都实现绘制圆角【如果没有,也可以通过将控件放在Panel中,借助Panel的圆角实现】。

Paint事件中实现圆角控件

注意:由于控件在Paint事件方法中进行了重新绘制,因此文本也被覆盖了,需要处理文本的绘制显示

新建项目 CustomControlRound,窗体中添加两个Panel、三个Button、一个Label控件。button设置Flat样式、边框为0。

然后在Paint事件方法中调用绘制圆角区域的方法(具体代码参见下一部分的扩展方法),具体如下:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        panel1.Paint += Panel1_Paint;
        panel2.Paint += Panel2_Paint;

        panel1.BackColor = panel2.BackColor = Color.Transparent;

        button1.Paint += Button1_Paint;
        button1.FlatStyle = FlatStyle.Flat;
        button1.FlatAppearance.BorderSize = 0;
        button1.FlatAppearance.MouseDownBackColor = Color.Transparent;
        button1.FlatAppearance.MouseOverBackColor = Color.Transparent;
        button1.FlatAppearance.CheckedBackColor = Color.Transparent;

        button2.Paint += Button1_Paint;
        button2.FlatStyle = FlatStyle.Flat;
        button2.FlatAppearance.BorderSize = 0;
        //button2.FlatAppearance.BorderColor = SystemColors.ButtonFace;
        button2.FlatAppearance.MouseDownBackColor = Color.Transparent;
        button2.FlatAppearance.MouseOverBackColor = Color.Transparent;
        button2.FlatAppearance.CheckedBackColor = Color.Transparent;

        button3.Paint += Button1_Paint;
        button3.FlatStyle = FlatStyle.Flat;
        button3.FlatAppearance.BorderSize = 0;
        //button3.FlatAppearance.BorderColor = SystemColors.ButtonFace;
        button3.FlatAppearance.MouseDownBackColor = Color.Transparent;
        button3.FlatAppearance.MouseOverBackColor = Color.Transparent;
        button3.FlatAppearance.CheckedBackColor = Color.Transparent;

        label1.Paint += Label1_Paint;
        label1.BackColor = Color.Transparent;
    }

    private void Label1_Paint(object sender, PaintEventArgs e)
    {
        var l = (Label)sender;
        // e.Graphics.DrawRoundRectAndCusp(e.ClipRectangle,  18, Color.FromArgb(180, 200, 210), Color.FromArgb(120, 120, 100)); // 不推荐
        e.Graphics.DrawRoundRectAndCusp(new Rectangle(0,0, l.Width,l.Height),  18, Color.FromArgb(180, 200, 210), Color.FromArgb(120, 120, 100));
    }

    private void Button1_Paint(object sender, PaintEventArgs e)
    {
        var btn = (Button)sender;
        e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, btn.Width, btn.Height), 18, Color.FromArgb(0, 122, 204), Color.FromArgb(8, 39, 57));

        ((Button)sender).NotifyDefault(false); // 去除窗体失去焦点时最新激活的按钮边框外观样式
    }

    private void Panel1_Paint(object sender, PaintEventArgs e)
    {
        var panel = sender as Panel;
        var rect=e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign);
    }

    private void Panel2_Paint(object sender, PaintEventArgs e)
    {
        var panel = sender as Panel;
        var rect = e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(113, 113, 113), Color.FromArgb(0, 0, 0));
    }
}

查看效果:

在Paint事件中不需要调用 base.OnPaint(e);,只有在继承控件重写OnPaint方法时,才应该(在函数方法开始时)调用base.OnPaint(e);

提取绘制圆角矩形和旁边小尖角的代码为扩展方法

介绍

下面是提取的扩展方法,对源代码进行了修改和优化。

  • 1、可绘制渐变背景色、指定背景色、指定画刷绘制的背景;可指定渐变背景的方向
  • 2、指定圆角半径的绘制,如果半径小于等于0,将绘制直角矩形。
  • 3、指定三角小尖,默认不绘制;指定三角小尖的位置,可供八个位置选择
  • 4、三角小尖的大小,目前感觉作为参数传递不够灵活,如果需要调整可直接从代码中修改,主要修改部分为:
// 尖角的大小 默认为 开始位置为_radius 底边为20,高度为13的等腰三角形
var cuspHemlineStart = _radius;
var cuspHemlineLength = 20;
var cuspHeight = 13;

扩展方法

扩展方法代码如下,将其放在namespace System.Drawing.Drawing2D下,可直接方便的从Graphics对象调用。

/// <summary>
/// 绘制可渐变的圆角矩形,并指定是否有三角小尖及其位置
/// </summary>
/// <param name="g"></param>
/// <param name="rectangle">矩形区域</param>
/// <param name="_radius">圆角半径</param>
/// <param name="begin_bgcolor">背景渐变开始色</param>
/// <param name="end_bgcolor">背景渐变结束色</param>
/// <param name="cusp">是否有三角小尖,默认无</param>
/// <param name="rectAlign">三角小尖的位置,默认右上</param>
/// <param name="gradientMode">渐变模式,默认垂直方向渐变</param>
public static void DrawRoundRectAndCusp(this Graphics g, Rectangle rectangle, int _radius, Color begin_bgcolor, Color end_bgcolor, bool cusp = false, RectangleAlign rectAlign= RectangleAlign.RightTop, LinearGradientMode gradientMode = LinearGradientMode.Vertical)
{
    ////抗锯齿 等模式在Graphics外层自定义设置
    //g.SmoothingMode = SmoothingMode.AntiAlias;
    //渐变填充
    LinearGradientBrush linearGradientBrush = new LinearGradientBrush(rectangle, begin_bgcolor, end_bgcolor, gradientMode);
    g.DrawRoundRectAndCusp(rectangle, _radius, linearGradientBrush, cusp, rectAlign);
}

/// <summary>
/// 绘制指定背景的圆角矩形,并指定是否有三角小尖及其位置
/// </summary>
/// <param name="g"></param>
/// <param name="rectangle">矩形区域</param>
/// <param name="_radius">圆角半径</param>
/// <param name="bgcolor">指定背景色</param>
/// <param name="cusp">是否有三角小尖,默认无</param>
/// <param name="rectAlign">三角小尖的位置,默认右上</param>
public static void DrawRoundRectAndCusp(this Graphics g, Rectangle rectangle, int _radius, Color bgcolor, bool cusp = false, RectangleAlign rectAlign = RectangleAlign.RightTop)
{
    ////抗锯齿 等模式在Graphics外层自定义设置
    //g.SmoothingMode = SmoothingMode.AntiAlias;
    //渐变填充
    var  brush = new SolidBrush(bgcolor);
    g.DrawRoundRectAndCusp(rectangle, _radius, brush, cusp, rectAlign);
}

/// <summary>
/// 绘制Brush画刷的圆角矩形,并指定是否有三角小尖及其位置
/// </summary>
/// <param name="g"></param>
/// <param name="rectangle">矩形区域</param>
/// <param name="_radius">圆角半径</param>
/// <param name="bgbrush">指定背景画刷</param>
/// <param name="cusp">是否有三角小尖,默认无</param>
/// <param name="rectAlign">三角小尖的位置,默认右上</param>
public static void DrawRoundRectAndCusp(this Graphics g, Rectangle rectangle, int _radius, Brush bgbrush, bool cusp = false, RectangleAlign rectAlign = RectangleAlign.RightTop)
{
    ////抗锯齿 尽可能高质量绘制
    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
    g.SmoothingMode = SmoothingMode.AntiAlias; // SmoothingMode.HighQuality
    g.CompositingQuality = CompositingQuality.HighQuality;
    g.InterpolationMode = InterpolationMode.HighQualityBilinear;

    var rect = rectangle;
    //画尖角 对应的变更rect区域
    if (cusp)
    {
        // 尖角的大小 默认为 开始位置为_radius 底边为20,高度为13的等腰三角形
        var cuspHemlineStart = _radius;
        var cuspHemlineLength = 20;
        var cuspHeight = 13;

        // 让位出来的间隔暂时为尖角高度-1
        var span = cuspHeight - 1;

        // 三角顶点
        PointF p1, p2, p3;

        switch (rectAlign)
        {
            case RectangleAlign.AboveLeft:
                p1 = new PointF(rectangle.X + cuspHemlineStart, rectangle.Y + cuspHeight);
                p2 = new PointF(rectangle.X + cuspHemlineStart + cuspHemlineLength, rectangle.Y + cuspHeight);
                p3 = new PointF(rectangle.X + cuspHemlineStart + cuspHemlineLength / 2, rectangle.Y);
                rect = new Rectangle(rectangle.X, rectangle.Y + span, rectangle.Width, rectangle.Height - span);
                break;
            case RectangleAlign.AboveRight:
                p1 = new PointF(rectangle.Right - cuspHemlineStart, rectangle.Y + cuspHeight);
                p2 = new PointF(rectangle.Right - cuspHemlineStart - cuspHemlineLength, rectangle.Y + cuspHeight);
                p3 = new PointF(rectangle.Right - cuspHemlineStart - cuspHemlineLength / 2, rectangle.Y);
                rect = new Rectangle(rectangle.X, rectangle.Y + span, rectangle.Width, rectangle.Height - span);
                break;
            case RectangleAlign.RightBottom:
                p1 = new PointF(rectangle.Right - cuspHeight, rectangle.Bottom - cuspHemlineStart);
                p2 = new PointF(rectangle.Right - cuspHeight, rectangle.Bottom - cuspHemlineStart - cuspHemlineLength);
                p3 = new PointF(rectangle.Right, rectangle.Bottom - cuspHemlineStart - cuspHemlineLength / 2);
                rect = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width - span, rectangle.Height);
                break;
            case RectangleAlign.BelowRight:
                p1 = new PointF(rectangle.Right - cuspHemlineStart, rectangle.Bottom - cuspHeight);
                p2 = new PointF(rectangle.Right - cuspHemlineStart - cuspHemlineLength, rectangle.Bottom - cuspHeight);
                p3 = new PointF(rectangle.Right - cuspHemlineStart - cuspHemlineLength / 2, rectangle.Bottom);
                rect = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height - span);
                break;
            case RectangleAlign.BelowLeft:
                p1 = new PointF(rectangle.X + cuspHemlineStart, rectangle.Bottom - cuspHeight);
                p2 = new PointF(rectangle.X + cuspHemlineStart + cuspHemlineLength, rectangle.Bottom - cuspHeight);
                p3 = new PointF(rectangle.X + cuspHemlineStart + cuspHemlineLength / 2, rectangle.Bottom);
                rect = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height - span);
                break;
            case RectangleAlign.LeftBottom:
                p1 = new PointF(rectangle.X + cuspHeight, rectangle.Bottom - cuspHemlineStart);
                p2 = new PointF(rectangle.X + cuspHeight, rectangle.Bottom - cuspHemlineStart - cuspHemlineLength);
                p3 = new PointF(rectangle.X, rectangle.Bottom - cuspHemlineStart - cuspHemlineLength / 2);
                rect = new Rectangle(rectangle.X + span, rectangle.Y, rectangle.Width - span, rectangle.Height);
                break;
            case RectangleAlign.LeftTop:
                p1 = new PointF(rectangle.X + cuspHeight, rectangle.Y + cuspHemlineStart);
                p2 = new PointF(rectangle.X + cuspHeight, rectangle.Y + cuspHemlineStart + cuspHemlineLength);
                p3 = new PointF(rectangle.X, rectangle.Y + cuspHemlineStart + cuspHemlineLength / 2);
                rect = new Rectangle(rectangle.X + span, rectangle.Y, rectangle.Width - span, rectangle.Height);
                break;
            case RectangleAlign.RightTop:
            default:
                p1 = new PointF(rectangle.Right - cuspHeight, rectangle.Y + cuspHemlineStart);
                p2 = new PointF(rectangle.Right - cuspHeight, rectangle.Y + cuspHemlineStart + cuspHemlineLength);
                p3 = new PointF(rectangle.Right, rectangle.Y + cuspHemlineStart + cuspHemlineLength / 2);
                rect = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width - span, rectangle.Height);
                break;
        }

        PointF[] ptsArray = new PointF[] { p1, p2, p3 };

        // 填充参数点所指定的多边形内部
        g.FillPolygon(bgbrush, ptsArray);
    }
    //填充
    g.FillPath(bgbrush, rect.GetRoundedRectPath(_radius));
}

/// <summary>
/// 根据普通矩形得到圆角矩形的路径 【根据矩形区域rect,计算呈现radius圆角的Graphics路径】
/// </summary>
/// <param name="rect">原始矩形</param>
/// <param name="radius">半径</param>
/// <returns>图形路径</returns>
public static GraphicsPath GetRoundedRectPath(this Rectangle rect, int radius)
{
    #region 正确绘制圆角矩形区域
    int R = radius*2;
    Rectangle arcRect = new Rectangle(rect.Location, new Size(R, R));
    GraphicsPath path = new GraphicsPath();

    if (radius <= 0)
    {
        path.AddRectangle(rect);
    }
    else
    {
        // 左上圆弧 左手坐标系,顺时针为正 从180开始,转90度
        path.AddArc(arcRect, 180, 90);
        // 右上圆弧
        arcRect.X = rect.Right - R;
        path.AddArc(arcRect, 270, 90);
        // 右下圆弧
        arcRect.Y = rect.Bottom - R;
        path.AddArc(arcRect, 0, 90);
        // 左下圆弧
        arcRect.X = rect.Left;
        path.AddArc(arcRect, 90, 90);
    }

    //path.CloseFigure();
    // 闭合路径中所有开放图形,并形成新图形
    path.CloseAllFigures();
    return path;
    #endregion
}

/// <summary>
/// 获取圆角矩形的路径
/// </summary>
/// <param name="rect">原始矩形</param>
/// <param name="radius">半径</param>
/// <returns>图形路径</returns>
public static GraphicsPath GetRoundedRectPath(int x, int y, int width, int height, int radius)
{
    Rectangle rect = new Rectangle(x, y, width, height);
    return rect.GetRoundedRectPath(radius);
}

测试尖角的显示位置

复制几个Panel,在Paint事件中分别处理尖角的位置

panel1.Paint += Panel1_Paint;
panel3.Paint += Panel1_Paint;
panel4.Paint += Panel1_Paint;
panel5.Paint += Panel1_Paint;
panel6.Paint += Panel1_Paint;
panel7.Paint += Panel1_Paint;
panel8.Paint += Panel1_Paint;
panel9.Paint += Panel1_Paint;
/// ......
private void Panel1_Paint(object sender, PaintEventArgs e)
{
    var panel = sender as Panel;
    var rectAlign = RectangleAlign.RightTop;
    switch (panel.Name)
    {
        case "panel3":
            rectAlign = RectangleAlign.AboveLeft;
            break;
        case "panel4":
            rectAlign = RectangleAlign.AboveRight;
            break;
        case "panel5":
            rectAlign = RectangleAlign.BelowLeft;
            break;
        case "panel6":
            rectAlign = RectangleAlign.BelowRight;
            break;
        case "panel7":
            rectAlign = RectangleAlign.LeftBottom;
            break;
        case "panel8":
            rectAlign = RectangleAlign.LeftTop;
            break;
        case "panel9":
            rectAlign = RectangleAlign.RightBottom;
            break;
        default:
            break;
    }

    var rect=e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign);

    e.Graphics.DrawText(rect, "这是一个Panel控件,非常适合显示消息", Color.White, panel.Font);
}

查看效果:

重绘控件后文本的处理

由于重新绘制导致文本也被覆盖的情况,有比较常见的两种处理方法:

  • 重绘控件的同时,重绘文本文字
  • 通过添加Label控件实现文本处理

同时重绘文本

同样将绘制文本的方法提取为扩展方法,借助StringFormat字符串格式对象实现文字的布局处理。

不推荐使用Graphics.DrawString绘制按钮控件(Rectangle区域)内的文字,当然DrawString也有一定有时比如文字方向的处理。

/// <summary>
/// 绘制(控件区域)文本内容
/// </summary>
/// <param name="g"></param>
/// <param name="rect"></param>
/// <param name="text"></param>
/// <param name="color"></param>
/// <param name="font"></param>
/// <param name="_textAlign">文字布局,默认居中。实际测试并未真正的居中,垂直方向偏上,改为通过计算rect的中心位置实现,使用微软雅黑还好点,字体大小最好偶数</param>
/// <param name="rtl">是否RightToLeft 无效果,不推荐使用</param>
public static void DrawText(this Graphics g, Rectangle rect, string text, Color color, Font font, ContentAlignment _textAlign = ContentAlignment.MiddleCenter, bool rtl=false)
{
        var formatFlags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter; // 默认居中
        switch (_textAlign)
        {
            case ContentAlignment.TopLeft:
                formatFlags = TextFormatFlags.Top | TextFormatFlags.Left;
                break;
            case ContentAlignment.TopCenter:
                formatFlags = TextFormatFlags.Top | TextFormatFlags.HorizontalCenter;
                break;
            case ContentAlignment.TopRight:
                formatFlags = TextFormatFlags.Top | TextFormatFlags.Right;
                break;
            case ContentAlignment.MiddleLeft:
                formatFlags = TextFormatFlags.VerticalCenter | TextFormatFlags.Left;
                break;
            case ContentAlignment.MiddleRight:
                formatFlags = TextFormatFlags.VerticalCenter | TextFormatFlags.Right;
                break;
            case ContentAlignment.BottomLeft:
                formatFlags = TextFormatFlags.Bottom | TextFormatFlags.Left;
                break;
            case ContentAlignment.BottomCenter:
                formatFlags = TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter;
                break;
            case ContentAlignment.BottomRight:
                formatFlags = TextFormatFlags.Bottom | TextFormatFlags.Right;
                break;
            case ContentAlignment.MiddleCenter:
            default:
                break;
        }
        if (rtl)
        {
            formatFlags |= TextFormatFlags.RightToLeft; // 无效果
        }
        TextRenderer.DrawText(g, text, font, rect, color, formatFlags);
}

要注意添加了小三角后的文字绘制区域问题,如果使用默认的全部预期有可能导致文字超出范围,且,布局也不是相对于绘制的主体。如下图对比的效果。

因此,可修改圆角绘制的函数,使其返回绘制后的主体区域。

private void Panel1_Paint(object sender, PaintEventArgs e)
{
    var panel = sender as Panel;
    var rect=e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign);

    //e.Graphics.DrawText(e.ClipRectangle, "这是一个Panel控件,非常适合显示消息", Color.White, panel.Font);
    // 使用合适的区域
    e.Graphics.DrawText(rect, "这是一个Panel控件,非常适合显示消息", Color.White, panel.Font);
}

通过添加Label控件实现对文本的处理【有尖角时需要额外处理】

label2.Text = "我是Label显示在圆角按钮上";
label2.Parent = button1;
label2.AutoSize = false;
label2.Dock = DockStyle.Fill;
label2.BackColor = Color.Transparent;
label2.TextAlign = ContentAlignment.MiddleCenter;
label2.ForeColor = Color.Wheat;

Paint事件中绘制圆角的优点

完全由用户绘制按钮区域实现圆角【之前文章介绍过】,可以发现,与直接在Paint事件中实现圆角,有着一定的锯齿,虽然不是很严重,但是还是Paint事件中实现的圆角看着相对好一些。

之前完全由用户绘制控件区域出现锯齿的问题,原因在于使用new Region(graphicPath)构造函数创建的新Region对象,创建的Region无法实现抗锯齿,即使开始抗锯齿和高质量绘制(无法应用到最终的Region)。

[唯一的]解决办法,是不创建新的Region,直接绘制无锯齿图形【无法对Region进行抗锯齿】。

窗体失去焦点时按钮外观边框问题

窗体失去焦点后,Button会显示出一个边框(即使已经设置BorderSize为0),只有在窗体失去焦点后,最后一个被激活过的Button(点击过的)才会出现。

比较好的解决办法是在Button的Paint事件中执行Button.NotifyDefault(false)方法。

下面是几种解决方式:

  • 通过继承Button控件,重写NotifyDefault方法实现。
class MyButton:Button
{
    public override void NotifyDefault(bool value)
    {
        base.NotifyDefault(false);
    }
}
  • 设置FlatAppearance.BorderColor颜色与下层背景色一致

或者,还有一个取巧的解决办法,就是,设置FlatAppearance.BorderColor为Button按钮后面的背景色,这样就看不出来,类似没有的效果。如 button1.FlatAppearance.BorderColor = SystemColors.Control;

  • 在Button的Paint事件方法中调用NotifyDefault(false)

或者,不是继承重写Button控件,直接在Button的Paint事件中,调用Button.NotifyDefault(false);方法。

private void Button1_Paint(object sender, PaintEventArgs e)
{
    var btn = (Button)sender;
    e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, btn.Width, btn.Height), 18, Color.FromArgb(0, 122, 204), Color.FromArgb(8, 39, 57));

    ((Button)sender).NotifyDefault(false); // 去除窗体失去焦点时最新激活的按钮边框外观样式
}

Paint事件中绘制控件的问题【不要使用(事件)参数e.ClipRectangle】

直接看下图演示,在发生控件大小、位置调整等需要重绘时,会发生控件错乱、显示不完整重叠等问题。

比如Panel事件中,原本的写法为:

var rect=e.Graphics.DrawRoundRectAndCusp(e.ClipRectangle, 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign);

将其改为转换传递过来的控件参数为Panel对象,并通过其宽高获取其绘制区域:

var rect=e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign);

修改后错乱问题就不存在了:

到此这篇关于Winform控件优化Paint事件实现圆角组件及提取绘制圆角的扩展方法的文章就介绍到这了,更多相关Winform控件优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C# Winform实现圆角无锯齿按钮

    本文实例为大家分享了C# Winform实现圆角无锯齿按钮的具体代码,供大家参考,具体内容如下 发现用Winform做一个圆角按钮遇到麻烦,主要是锯齿问题,后面想了想办法解决问题了. 主要方法是按钮的区域通过Region指定,但按钮需要自己画,否则怎么搞都出现锯齿,网上有朋友提供一个漂亮的方案,可是代码不完整无法使用,我的解决方案现在分享如下: 代码: public enum ControlState { Hover , Normal, Pressed }     public class Ro

  • Winform控件优化之圆角按钮1

    目录 前言 圆角按钮实现[重写OnPaint实现圆角绘制] 代码主要关键点或思路.优化 使用圆角按钮 利用填充内外两层圆角矩形路径形成Border 通过缩放实现正确的内外两层圆角矩形路径 CDI+路径的填充模式 直接绘制路径作为边框[推荐]** 可以改进和实现的 在Paint事件中重绘控件为圆角 前言 Windows 11下所有控件已经默认采用圆角,其效果更好.相对有着更好的优化,只是这是默认的行为,无法进一步自定义. 圆角按钮实现[重写OnPaint实现圆角绘制] 控件自定义绘制的关键在于:重

  • Winform窗体圆角设计代码

    网上看到的很多winform窗体圆角设计代码都比较累赘,这里分享一个少量代码就可以实现的圆角.主要运用了System.Drawing.Drawing2D. 效果图 代码如下 private void BeautiLoginForm_Paint(object sender, PaintEventArgs e) { Type(this, 25, 0.1); } private void Type(Control sender, int p_1, double p_2) { GraphicsPath

  • WinForm绘制圆角的方法

    本文实例讲述了WinForm绘制圆角的方法.分享给大家供大家参考.具体实现方法如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.In

  • Winform控件优化Paint事件实现圆角组件及提取绘制圆角的方法

    目录 前言 Paint事件中实现圆角控件 提取绘制圆角矩形和旁边小尖角的代码为扩展方法 介绍 扩展方法 测试尖角的显示位置 重绘控件后文本的处理 同时重绘文本 通过添加Label控件实现对文本的处理[有尖角时需要额外处理] Paint事件中绘制圆角的优点 窗体失去焦点时按钮外观边框问题 Paint事件中绘制控件的问题[不要使用(事件)参数e.ClipRectangle] 前言 Windows 11下所有控件已经默认采用圆角,其效果更好.相对有着更好的优化,只是这是默认的行为,无法进一步自定义.

  • Winform控件优化之圆角按钮2

    目录 前言 圆角按钮实现的进一步优化 主要功能[圆角方面] OnPaint方法中不要使用e.ClipRectangle 重新创建Region的锯齿问题和优势 代码具体实现 测试扩展按钮控件ButtonPro TextRenderer.DrawText绘制文本 使用StringFormat.GenericTypographic 仅仅重写OnPaintBackground 使用TextRenderer.DrawText绘制文本 前言 接上一篇Winform控件优化之圆角按钮1继续介绍圆角按钮的实现和

  • C# WinForm控件对透明图片重叠时出现图片不透明的简单解决方法

    本文实例讲述了C# WinForm控件对透明图片重叠时出现图片不透明的简单解决方法.分享给大家供大家参考,具体如下: 在Winform中如果将一个透明图片放在窗体上能正常显示透明,但是如果将该图片放在另一个控件上会导致不能显示透明效果. 解决这种情况,可以采取在控件上使用GDI+绘画出透明图片. 这里我们就以一个pictureBox2控件上面重叠一张png透明图片为例: 我们只需要给pictureBox2控件添加Paint事件,然后对png透明图片进行绘制即可,代码如下: private voi

  • C#中WinForm控件的拖动和缩放的实现代码

    C# WinForm控件的拖动和缩放是个很有用的功能.实现起来其实很简单的,主要是设计控件的MouseDown.MouseLeave.MouseMove事件,下面的几个步骤将逐步实现C# WinForm控件的拖动和缩放的功能. 1.定义一个枚举类型,描述光标状态 private enum EnumMousePointPosition { MouseSizeNone = 0, //'无 MouseSizeRight = 1, //'拉伸右边框 MouseSizeLeft = 2, //'拉伸左边框

  • C#开发Winform控件之打开文件对话框OpenFileDialog类

    OpenFileDialog类提供了用户打开文件的功能,它有如下属性: 属性 InitialDirectory:设置对话框的初始目录. Filter: 要在对话框中显示的文件筛选器,例如,"文本文件(*.txt)|*.txt|所有文件(*.*)||*.*". FilterIndex: 在对话框中选择的文件筛选器的索引,如果选第一项就设为1. RestoreDirectory: 控制对话框在关闭之前是否恢复当前目录. FileName:第一个在对话框中显示的文件或最后一个选取的文件. T

  • C#的winform控件命名规范

    本文详细讲述了C#的winform控件命名规范.分享给大家供大家参考.具体如下: 注:这里用红字标记的部分表示有重复出现,括号内为替代表示方案 1.标准控件 序号 控件类型简写 控件类型 1 btn Button 2 chk CheckBox 3 ckl CheckedListBox 4 cmb ComboBox 5 dtp DateTimePicker 6 lbl Label 7 llb LinkLabel 8 lst ListBox 9 lvw ListView 10 mtx MaskedT

  • ASP.NET 页面中动态增加的控件、添加事件第1/2页

    要求:页面上有一个Add按钮,每点击一次该按钮,页面上动态创建一个WebPartZone! 提醒:WebPartZone只能在OnInit或之前才能创建,否则报异常! 大家都知道,按钮的点击事件是在RaisePostbackEvent时触发的,这意味着点击事件在OnLoad阶段之后才执行,远远落后于 OnInit阶段,而且ViewState在OnLoad时才准备好,OnInit以及之前的阶段根本就不能使用ViewState!如果试图在按钮点击事件里面创建WebPartZone等控件,唯一的后果就

  • jQuery的控件及事件(输入控件及回车事件)使用示例

    复制代码 代码如下: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>JavaScript</title> <style type="text/css"> body { /* 对页面布局进行调整 */ background-color: #ccc

  • Textbox控件注册回车事件及触发按钮提交事件具体实现

    引子: 在ASP.Net页面中textbox的index为1(或n),其后的提交按钮index为2(n+1),光标在textbox中,回车后自动焦点移动到后面的button上,会触发button的点击事件. 但在Lyncplus客户端中访问Web页面时遇到了TextBox控件回车自动完成按钮的提交事件失效的情况(应该是自动切换焦点). 由于并且该服务端TextBox控件没有提供OnKeyPress或OnKeyDown等事件,也无法针对回车事件写后台代码来调用Button按钮的点击事件. 于是上网

随机推荐