65.9K
CodeProject 正在变化。 阅读更多。
Home

SBButton

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.18/5 (15投票s)

2008年3月3日

CPOL

1分钟阅读

viewsIcon

54599

downloadIcon

1820

一个完全可定制的 .NET 2.0 按钮控件。

SBButtonControl2.PNG

引言

SBButton 控件是我正在开发的一组控件(Sysbytes Controls)中的一个按钮控件,用于我正在编写的一个应用程序。这个按钮控件几乎可以按照用户喜欢的任何方式进行自定义。您可以为该控件的不同状态设置不同的样式,例如:DefaultStyleMouseOverStyleMouseDownStyleDisabledStyle

工作原理

该控件继承自 Control 类和 IButtonControl 接口,并使用 OnPaint 事件使用 GDI+ 绘制控件。该控件使用一些与 .NET 提供的 Button 控件不同的属性。以下是这些属性:

  • DefaultStyle(默认样式)
  • MouseOverStyle(鼠标悬停样式)
  • MouseDownStyle(鼠标按下样式)
  • DisabledStyle(禁用样式)
  • RoundedCorners(圆角)
  • ShowFocusCue(显示焦点提示)
  • Image
  • ImageAlignment(图像对齐方式)
  • FocusCueColor(焦点提示颜色)

属性 DefaultStyleMouseOverStyleMouseDownStyleDisabledStyle 均源自一个名为 SBButtonAppearance 的类,并且所有这些属性都具有一些共同的子属性。它们是:

  • BackColor1(背景色1)
  • BackColor2(背景色2)
  • HighLightColor(高亮颜色)
  • GlowColor(发光颜色)
  • InnerBorderColor(内边框颜色)
  • OuterBorderColor(外边框颜色)
  • TextColor
  • FillMode(填充模式)
  • 字体
  • HighLightOpacity1(高亮透明度1)
  • HighLightOpacity2(高亮透明度2)
  • GlowOpacity(发光透明度)
  • InnerBorderOpacity(内边框透明度)

源代码

SBButtonAppearanceClass 的源代码如下:

[Serializable()]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SBButtonAppearance
{
    public event EventHandler<EventArgs> SBButtonAppearanceChanged;

    private Color _backColor1 = SystemColors.ButtonFace;

    public Color BackColor1
    {
        get { return _backColor1; }
        set 
        {
            _backColor1 = value;
            AppearanceChanged();
        }
    }

    private Color _backColor2 = SystemColors.ButtonFace;

    public Color BackColor2
    {
        get { return _backColor2; }
        set 
        {
            _backColor2 = value;
            AppearanceChanged();
        }
    }

    private Color _outerBorderColor = SystemColors.ControlDarkDark;

    public Color OuterBorderColor
    {
        get { return _outerBorderColor; }
        set 
        {
            _outerBorderColor = value;
            AppearanceChanged();
        }
    }

    private Color _innerBorderColor = SystemColors.ControlLightLight;

    public Color InnerBorderColor
    {
        get { return _innerBorderColor; }
        set 
        {
            _innerBorderColor = value;
            AppearanceChanged();
        }
    }

    private Color _glowColor = SystemColors.ControlLightLight;

    public Color GlowColor
    {
        get { return _glowColor; }
        set 
        { 
            _glowColor = value;
            AppearanceChanged();
        }
    }

    private Color _highLightColor = SystemColors.ControlLightLight;

    public Color HighLightColor
    {
        get { return _highLightColor; }
        set 
        {
            _highLightColor = value;
            AppearanceChanged();
        }
    }

    private Color _textColor = SystemColors.ControlText;

    public Color TextColor
    {
        get { return _textColor; }
        set
        {
            _textColor = value;
            AppearanceChanged();
        }
    }

    private Font _font = SystemFonts.DefaultFont;

    public Font Font
    {
        get { return _font; }
        set
        {
            _font = value;
            AppearanceChanged();
        }
    }

    private LinearGradientMode _fillMode = LinearGradientMode.Horizontal;

    public LinearGradientMode FillMode
    {
        get { return _fillMode; }
        set
        {
            _fillMode = value;
            AppearanceChanged();
        }
    }

    private int _innerBorderOpacity = 200;

    public int InnerBorderOpacity
    {
        get { return _innerBorderOpacity; }
        set
        {
            if (value > 255) value = 255;
            if (value < 0) value = 0;

            _innerBorderOpacity = value;
            AppearanceChanged();
        }
    }

    private int _highLightOpacity1 = 200;

    public int HightLightOpacity1
    {
        get { return _highLightOpacity1; }
        set
        {
            if (value > 255) value = 255;
            if (value < 0) value = 0;

            _highLightOpacity1 = value;
            AppearanceChanged();
        }
    }

    private int _highLightOpacity2 = 150;

    public int HightLightOpacity2
    {
        get { return _highLightOpacity2; }
        set
        {
            if (value > 255) value = 255;
            if (value < 0) value = 0;

            _highLightOpacity2 = value;
            AppearanceChanged();
        }
    }

    private int _glowOpacity = 120;

    public int GlowOpacity
    {
        get { return _glowOpacity; }
        set
        {
            if (value > 255) value = 255;
            if (value < 0) value = 0;

            _glowOpacity = value;
            AppearanceChanged();
        }
    }

    public override string ToString()
    {
        return null;
    }

    private void AppearanceChanged()
    {
        EventHandler<EventArgs> temp = SBButtonAppearanceChanged;
        if (temp != null)
            temp(this, new EventArgs());
    }
}

绘制按钮的代码

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
        e.Graphics.TextRenderingHint = 
          System.Drawing.Text.TextRenderingHint.SystemDefault;

        if(!isMouseIn && !isMouseDown && this.Enabled)
            this.DrawDefault(e);

        if (isMouseIn && !isMouseDown && this.Enabled)
            this.DrawMouseOver(e);

        if (isMouseIn && isMouseDown && this.Enabled)
            this.DrawMouseDown(e);

        if (!isMouseIn && isMouseDown && this.Enabled)
            this.DrawMouseDown(e);

        if (!this.Enabled)
            this.DrawDisabled(e);

        if (this.Focused && this.ShowFocusCue && this.Enabled)
            ControlPaint.DrawBorder(e.Graphics, new Rectangle(
                2, 2, this.Width - 4, this.Height - 4), this.FocusCueColor,
                ButtonBorderStyle.Dashed);
    }
    private void DrawDefault(PaintEventArgs e)
    {
        LinearGradientBrush brBackground = new LinearGradientBrush(
            this.ClientRectangle, this.DefaultStyle.BackColor1, 
            this.DefaultStyle.BackColor2, this.DefaultStyle.FillMode);
        LinearGradientBrush brHighlight = new LinearGradientBrush(new Rectangle(
            2, 2, this.Width - 5, this.Height / 2), 
            Color.FromArgb(this.DefaultStyle.HightLightOpacity1, 
            this.DefaultStyle.HighLightColor), 
            Color.FromArgb(this.DefaultStyle.HightLightOpacity2, 
            this.DefaultStyle.HighLightColor), LinearGradientMode.Vertical);
        LinearGradientBrush brGlow = new LinearGradientBrush(new Rectangle(
            0, this.Height - this.Height / 4 - 1, this.Width - 1, this.Height / 4),
            Color.Transparent, Color.FromArgb(this.DefaultStyle.GlowOpacity, 
            this.DefaultStyle.GlowColor), LinearGradientMode.Vertical);

        Pen pnOuterBorder = new Pen(this.DefaultStyle.OuterBorderColor, 1);
        Pen pnInnerBorder = new Pen(Color.FromArgb(DefaultStyle.InnerBorderOpacity, 
            this.DefaultStyle.InnerBorderColor));

        GraphicsPath gpBackground = Common.RoundedRect(new Rectangle(
            0, 0, this.Width - 1, this.Height - 1), 3);
        GraphicsPath gpGlow = Common.RoundedRect(new Rectangle(
            1, this.Height - this.Height / 4, this.Width - 3, this.Height / 4), 1,1,3,3);
        GraphicsPath gpHighlight = Common.RoundedRect(new Rectangle(
            2, 2, this.Width - 5, this.Height / 2 - 1), 3, 3, 1, 1);
        GraphicsPath gpOuterBorder = Common.RoundedRect(new Rectangle(
            0, 0, this.Width - 1, this.Height - 1), 3);
        GraphicsPath gpInnerBorder = Common.RoundedRect(new Rectangle(
            1, 1, this.Width - 3, this.Height - 3), 3);

        Rectangle rectBackground = new Rectangle(0, 0, this.Width - 1, this.Height - 1);
        Rectangle rectGlow = new Rectangle(1, this.Height - this.Height / 4, 
            this.Width - 3, this.Height / 4);
        Rectangle rectHighlight = new Rectangle(2, 2, this.Width - 5, this.Height / 2 - 1);
        Rectangle rectOuterBorder = new Rectangle(0, 0, this.Width - 1, this.Height - 1);
        Rectangle rectInnerBorder = new Rectangle(1, 1, this.Width - 3, this.Height - 3);

        Size textSize = TextRenderer.MeasureText(this.Text, this.DefaultStyle.Font);

        Point textPos = new Point(this.Width / 2 - textSize.Width / 2,
            this.Height / 2 - textSize.Height / 2);
        Point imagePos = new Point();

        switch (this.ImageAlignment)
        {
            case Alignment.Right:
                if (this.Image != null)
                {
                    textPos = new Point(5, this.Height / 2 - textSize.Height / 2);
                    imagePos = new Point(this.Width - this.Image.Width - 5,
                        this.Height / 2 - this.Image.Size.Height / 2);
                }
                break;
            case Alignment.Left:
                if (this.Image != null)
                {
                    textPos = new Point(this.Width - textSize.Width - 5,
                        this.Height / 2 - textSize.Height / 2);
                    imagePos = new Point(5, this.Height / 2 - this.Image.Size.Height / 2);
                }
                break;
        }

        if (this.RoundedCorners)
        {
            e.Graphics.FillPath(brBackground, gpBackground);
            e.Graphics.FillPath(brGlow, gpGlow);
            e.Graphics.FillPath(brHighlight, gpHighlight);
            e.Graphics.DrawPath(pnOuterBorder, gpOuterBorder);
            e.Graphics.DrawPath(pnInnerBorder, gpInnerBorder);
        }
        else
        {
            e.Graphics.FillRectangle(brBackground, rectBackground);
            e.Graphics.FillRectangle(brGlow, rectGlow);
            e.Graphics.FillRectangle(brHighlight, rectHighlight);
            e.Graphics.DrawRectangle(pnOuterBorder, rectOuterBorder);
            e.Graphics.DrawRectangle(pnInnerBorder, rectInnerBorder);
        }

        if (this.Image != null)
            e.Graphics.DrawImage(this.Image, imagePos.X, imagePos.Y, 
                this.Image.Width, this.Image.Height);

        TextRenderer.DrawText(e.Graphics, this.Text, this.DefaultStyle.Font, 
            textPos, this.DefaultStyle.TextColor);
    }

方法 DrawMouseOverDrawMouseDownDrawDisabledDrawDefault 相同,只是使用的颜色和透明度值不同。您可能注意到此方法调用了一个函数 Common.RoundedRect。此函数将返回一个带有圆角的矩形,作为 GraphicsPath

以下是此函数的代码:

    public static System.Drawing.Drawing2D.GraphicsPath RoundedRect(
        System.Drawing.Rectangle baseRect, int topLeftRadius,
        int topRightRadius, int bottomLeftRadius, int bottomRightRadius)
    {
        int topLeftDiameter = topLeftRadius * 2;
        int topRightDiameter = topRightRadius * 2;
        int bottomLeftDiameter = bottomLeftRadius * 2;
        int bottomRightDiameter = bottomRightRadius * 2;

        System.Drawing.Drawing2D.GraphicsPath gp = 
               new System.Drawing.Drawing2D.GraphicsPath();

        System.Drawing.Rectangle rectTopLeft = new System.Drawing.Rectangle(
            baseRect.Left, baseRect.Top, topLeftDiameter, topLeftDiameter);
        System.Drawing.Rectangle rectTopRight = new System.Drawing.Rectangle(
            baseRect.Right - topRightDiameter, baseRect.Top, topRightDiameter, 
            topRightDiameter);
        System.Drawing.Rectangle rectBottomLeft = new System.Drawing.Rectangle(
            baseRect.Left, baseRect.Bottom - bottomLeftDiameter, bottomLeftDiameter, 
            bottomLeftDiameter);
        System.Drawing.Rectangle rectBottomRight = new System.Drawing.Rectangle(
            baseRect.Right - bottomRightDiameter, baseRect.Bottom - bottomRightDiameter, 
            bottomRightDiameter, bottomRightDiameter);

        gp.AddArc(rectTopLeft, 180, 90);
        gp.AddArc(rectTopRight, 270, 90);
        gp.AddArc(rectBottomRight, 0, 90);
        gp.AddArc(rectBottomLeft, 90, 90);

        gp.CloseFigure();

        return gp;
    }
    public static System.Drawing.Drawing2D.GraphicsPath RoundedRect(
        System.Drawing.Rectangle baseRect, int cornerRadius)
    {
        int diameter = cornerRadius * 2;

        System.Drawing.Drawing2D.GraphicsPath gp = 
               new System.Drawing.Drawing2D.GraphicsPath();

        System.Drawing.Rectangle rectTopLeft = new System.Drawing.Rectangle(
            baseRect.Left, baseRect.Top, diameter, diameter);
        System.Drawing.Rectangle rectTopRight = new System.Drawing.Rectangle(
            baseRect.Right - diameter, baseRect.Top, diameter, diameter);
        System.Drawing.Rectangle rectBottomLeft = new System.Drawing.Rectangle(
            baseRect.Left, baseRect.Bottom - diameter, diameter, diameter);
        System.Drawing.Rectangle rectBottomRight = new System.Drawing.Rectangle(
            baseRect.Right - diameter, baseRect.Bottom - diameter, diameter, diameter);

        gp.AddArc(rectTopLeft, 180, 90);
        gp.AddArc(rectTopRight, 270, 90);
        gp.AddArc(rectBottomRight, 0, 90);
        gp.AddArc(rectBottomLeft, 90, 90);

        gp.CloseFigure();

        return gp;
    }

关注点

此控件支持图像,并且图像只能对齐到左侧或右侧。如果没有图像,文本将始终对齐到控件的中心。您可以很容易地通过编辑方法 DrawDefaultDrawMouseOverDrawMouseDownDrawDisabled 来修改这些行为。

© . All rights reserved.