【C#】分享一个可灵活设置边框的Panel

---------------------------更新:2014-05-19---------------------------

优化了一下逻辑,就是既然可以通过设置BorderSide=None来不显示边框,那么再设计一个BorderMode.None就显得多余,即BorderMode枚举只需要2个元素即可(Single和ThreeD),而与其弄一个只有2个元素的枚举还不如干脆不要这个枚举,改为给PanelEx加一个布尔属性BorderIsSingleMode(之所以这样命名是考虑把与边框相关的属性都以Border开头,方便在设计器中使用),为true则代表单色模式,否则为三维模式,而显不显示、显示哪些边则完全交给BorderSide控制,同时把BorderSide的默认值设为None,即默认不显示边框。修改后的代码如下:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace AhDung.Controls
{
    /// <summary>
    /// 可设置边框样式的Panel
    /// </summary>
    public class PanelEx : Panel
    {
        private Color borderColor;
        private Border3DStyle border3DStyle;
        private ToolStripStatusLabelBorderSides borderSide;
        private bool borderIsSingleMode;

        [DefaultValue(true), Description("指定边框是否为单色模式。false代表三维模式")]
        public bool BorderIsSingleMode
        {
            get { return borderIsSingleMode; }
            set
            {
                if (borderIsSingleMode == value) { return; }
                borderIsSingleMode = value;
                this.Invalidate();
            }
        }

        [DefaultValue(typeof(Color), "Black"), Description("边框颜色。仅当边框为单色模式时有效")]
        public Color BorderColor
        {
            get { return borderColor; }
            set
            {
                if (borderColor == value) { return; }
                borderColor = value;
                this.Invalidate();
            }
        }

        [DefaultValue(Border3DStyle.Etched), Description("边框三维样式。仅当边框为三维模式时有效")]
        public Border3DStyle Border3DStyle
        {
            get { return border3DStyle; }
            set
            {
                if (border3DStyle == value) { return; }
                border3DStyle = value;
                this.Invalidate();
            }
        }

        //之所以不直接用Border3DSide是因为这货不被设计器支持,没法灵活选择位置组合
        [DefaultValue(ToolStripStatusLabelBorderSides.None), Description("边框位置。可自由启用各个方位的边框")]
        public ToolStripStatusLabelBorderSides BorderSide
        {
            get { return borderSide; }
            set
            {
                if (borderSide == value) { return; }
                borderSide = value;
                this.Invalidate();
            }
        }

        public PanelEx()
        {
            this.borderIsSingleMode = true;
            this.borderColor = Color.Black;
            this.border3DStyle = System.Windows.Forms.Border3DStyle.Etched;
            this.borderSide = ToolStripStatusLabelBorderSides.None;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (this.BorderStyle != System.Windows.Forms.BorderStyle.None
                || BorderSide == ToolStripStatusLabelBorderSides.None)
            { return; }

            using (Graphics g = e.Graphics)
            {
                //单色模式
                if (this.BorderIsSingleMode)
                {
                    using (Pen pen = new Pen(BorderColor))
                    {
                        //若是四条边都启用,则直接画矩形
                        if (BorderSide == ToolStripStatusLabelBorderSides.All)
                        {
                            g.DrawRectangle(pen, 0, 0, this.Width - 1, this.Height - 1);
                        }
                        else //否则分别绘制线条
                        {
                            if ((BorderSide & ToolStripStatusLabelBorderSides.Top) == ToolStripStatusLabelBorderSides.Top)
                            {
                                g.DrawLine(pen, 0, 0, this.Width - 1, 0);
                            }

                            if ((BorderSide & ToolStripStatusLabelBorderSides.Right) == ToolStripStatusLabelBorderSides.Right)
                            {
                                g.DrawLine(pen, this.Width - 1, 0, this.Width - 1, this.Height - 1);
                            }

                            if ((BorderSide & ToolStripStatusLabelBorderSides.Bottom) == ToolStripStatusLabelBorderSides.Bottom)
                            {
                                g.DrawLine(pen, 0, this.Height - 1, this.Width - 1, this.Height - 1);
                            }

                            if ((BorderSide & ToolStripStatusLabelBorderSides.Left) == ToolStripStatusLabelBorderSides.Left)
                            {
                                g.DrawLine(pen, 0, 0, 0, this.Height - 1);
                            }
                        }
                    }
                }
                else //三维模式
                {
                    ControlPaint.DrawBorder3D(g, this.ClientRectangle, this.Border3DStyle, (Border3DSide) BorderSide); //这儿要将ToolStripStatusLabelBorderSides转换为Border3DSide
                }
            }
        }
    }
}

---------------------------原文:2014-05-14---------------------------

注:此乃Winform控件,开发环境为.net 2.0

工作需要,我对自带Panel进行了一下呈现上的扩展,方便设置边框效果。先看效果:

说明:

* 只有当原有属性BorderStyle为None时才能应用样式,此时可通过BorderMode设置【不显示、单色、三维】三种边框模式;这是因为BorderStyle为FixedSingle或Fixed3D时,自带边框似乎不属于Panel的一部分,不能控制或清除,我猜应该是底层API负责绘制的,所以唯有在None时才能自由发挥;

* 无论单色或是三维模式,均可通过BorderSide自由启用/禁用各个方位的边框;

* 在单色模式下,可通过BorderColor设置边框颜色,此时设置三维样式(Border3DStyle)无效;

* 在三维模式下,可通过Border3DStyle设置三维样式,此时设置边框颜色(BorderColor)无效;

代码在此:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace AhDung.Controls
{
    /// <summary>
    /// 边框模式(无、单色、三维)
    /// </summary>
    public enum BorderMode { None, Single, ThreeD }
    
    /// <summary>
    /// 可设置边框样式的Panel
    /// </summary>
    public class PanelEx : Panel
    {
        private Color borderColor;
        private Border3DStyle border3DStyle;
        private ToolStripStatusLabelBorderSides borderSide;
        private BorderMode borderMode;

        [DefaultValue(BorderMode.None), Description("边框模式。可设置单色模式或三维模式")]
        public BorderMode BorderMode
        {
            get { return borderMode; }
            set
            {
                if (borderMode == value) { return; }
                borderMode = value;
                this.Invalidate();
            }
        }

        [DefaultValue(typeof(Color), "Black"), Description("边框颜色。仅当边框为单色模式时有效")]
        public Color BorderColor
        {
            get { return borderColor; }
            set
            {
                if (borderColor == value) { return; }
                borderColor = value;
                this.Invalidate();
            }
        }

        [DefaultValue(Border3DStyle.Etched), Description("边框三维样式。仅当边框为三维模式时有效")]
        public Border3DStyle Border3DStyle
        {
            get { return border3DStyle; }
            set
            {
                if (border3DStyle == value) { return; }
                border3DStyle = value;
                this.Invalidate();
            }
        }

        //之所以不直接用Border3DSide是因为这货不被设计器支持,没法灵活选择位置组合
        [DefaultValue(ToolStripStatusLabelBorderSides.All), Description("边框位置。可自由启用各个方位的边框")]
        public ToolStripStatusLabelBorderSides BorderSide
        {
            get { return borderSide; }
            set
            {
                if (borderSide == value) { return; }
                borderSide = value;
                this.Invalidate();
            }
        }

        public PanelEx()
        {
            this.borderMode = BorderMode.None;
            this.borderColor = Color.Black;
            this.border3DStyle = System.Windows.Forms.Border3DStyle.Etched;
            this.borderSide = ToolStripStatusLabelBorderSides.All;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (this.BorderStyle != System.Windows.Forms.BorderStyle.None
                || BorderMode == BorderMode.None
                || BorderSide == ToolStripStatusLabelBorderSides.None)
            { return; }

            using (Graphics g = e.Graphics)
            {
                //三维模式
                if (this.BorderMode == BorderMode.ThreeD)
                {
                    ControlPaint.DrawBorder3D(g, this.ClientRectangle, this.Border3DStyle, (Border3DSide)BorderSide);//这儿要将ToolStripStatusLabelBorderSides转换为Border3DSide
                }
                else //单色模式
                {
                    using (Pen pen = new Pen(BorderColor))
                    {
                        //若是四条边都启用,则直接画矩形
                        if (BorderSide == ToolStripStatusLabelBorderSides.All)
                        {
                            g.DrawRectangle(pen, 0, 0, this.Width - 1, this.Height - 1);
                        }
                        else //否则分别绘制线条
                        {
                            if ((BorderSide & ToolStripStatusLabelBorderSides.Top) == ToolStripStatusLabelBorderSides.Top)
                            { g.DrawLine(pen, 0, 0, this.Width - 1, 0); }

                            if ((BorderSide & ToolStripStatusLabelBorderSides.Right) == ToolStripStatusLabelBorderSides.Right)
                            { g.DrawLine(pen, this.Width - 1, 0, this.Width - 1, this.Height - 1); }

                            if ((BorderSide & ToolStripStatusLabelBorderSides.Bottom) == ToolStripStatusLabelBorderSides.Bottom)
                            { g.DrawLine(pen, 0, this.Height - 1, this.Width - 1, this.Height - 1); }

                            if ((BorderSide & ToolStripStatusLabelBorderSides.Left) == ToolStripStatusLabelBorderSides.Left)
                            { g.DrawLine(pen, 0, 0, 0, this.Height - 1); }
                        }
                    }
                }
            }
        }
    }
}

-文毕-

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏应用案例

D3.js 满足你对数据可视化的一切幻想

D3.js D3的全称是Data-Driven Documents(数据驱动的文档),是一个用来做数据可视化的JavaScript函数库,而JavaScript...

54710
来自专栏糊一笑

移动端效果之Picker

写在前面 接着前面的移动端效果的研究,这次来看看picker选择器的实现原理 移动端效果之Swiper 移动端效果之CellSwiper 移动端效果之Index...

4103
来自专栏Code_iOS

OpenGL ES 2.0 (iOS)[05-1]:进入 3D 世界,从正方体开始

a. 渲染管线的基础知识 《OpenGL ES 2.0 (iOS)[01]: 一步从一个小三角开始》

1643
来自专栏Flutter入门

Flutter开发实战分析-animation_demo瞎复写总结

以下代码基本参考于 flutter_gallery中的animation_demo示例。(可以结合本文看源码)

5703
来自专栏转载gongluck的CSDN博客

CListCtrl控件使用方法总结

今天第一次用CListCtrl控件,遇到不少问题,查了许多资料,现将用到的一些东西总结如下: 以下未经说明,listctrl默认view 风格为report ...

42513
来自专栏進无尽的文章

绘图-CAShapeLayer、CABasicAnimation以及核心动画

QeartzCore是iOS中的图层框架,Quartz Core 的渲染能力可以像三维一样对二维图像进行任意操纵,在这个框架中我们可以对试图的图层进行定制,以实...

1542
来自专栏Windows Community

New UWP Community Toolkit - AdaptiveGridView

概述 UWP Community Toolkit  中有一个自适应的 GridView 控件 - AdaptiveGridView,本篇我们结合代码详细讲解  ...

3297
来自专栏格子的个人博客

Markdown语法学习记录

鉴于每次写博客,写文章的时候,总是要重复去查询Markdown的相关语法,这种闹心的感觉我再也不要了。

1102
来自专栏DeveWork

jQuery仿极客公园火箭发射“返回顶部”效果(优化篇)

承接上一篇《jQuery仿极客公园火箭发射“返回顶部”效果(初始篇)》,本文将对前一篇的代码进行优化。还是转载自andyliu: 先给出个演示Demo:演示地址...

2096
来自专栏Alan's Lab

swift 写 iOS 空心字描边动画

http://oleb.net/blog/2010/12/animating-drawing-of-cgpath-with-cashapelayer/ http...

1773

扫码关注云+社区

领取腾讯云代金券