winform自定义控件-水管

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Windows.Forms.VisualStyles;

namespace ControlLibrary
{
    /// <summary>
    /// 管道左、右的转向类型
    /// </summary>
    public enum PipeTurnDirection
    {
        Up = 1,
        Down,
        Left,
        Right,
        None
    }

    /// <summary>
    /// 管道的样式,水平还是数值
    /// </summary>
    public enum DirectionStyle
    {
        Horizontal = 1,
        Vertical
    }

    public partial class UserControl1: UserControl
    {
        public UserControl1()
        {
            InitializeComponent();

            //对本身进行设置
            //设置控件样式
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);    //减少闪烁
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);   //双缓冲,也是减少闪烁
            this.SetStyle(ControlStyles.ResizeRedraw, true);    //调整大小
            this.SetStyle(ControlStyles.Selectable, true);  //接收焦点
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);    //模拟透明度
            this.SetStyle(ControlStyles.UserPaint, true);   //控件描绘控件本身

            //自动移动
            mytimer = new Timer();
            mytimer.Tick += Mytimer_Tick;
            mytimer.Enabled = true;
        }
        
        //移动
        private void Mytimer_Tick(object sender, EventArgs e)
        {
            startOffset -= moveSpeed;   //减才是向右移动

            if (startOffset > (this.gapLength + this.pipeLength))
            {
                startOffset = 0;
            }

            this.Invalidate();  //没有这个不会动,有这个才会重写绘制
        }

        private Graphics g; //画布

        private Pen p;  //画笔

        private Timer mytimer;

        private float startOffset = 0.0f;



        #region Fileds

        private int pipeWidth = 5;

        [Browsable(true), Category("自定义属性"), Description("流动条宽度")]
        public int PipeWidth
        {
            get { return pipeWidth; }
            set
            {
                this.pipeWidth = value;

                base.Invalidate();  //this和base是一样的,这个是Windows.Forms里面的方法,调用父类和子类是一样的
            }
        }

        private Color colorCenter = Color.DodgerBlue;

        [Browsable(true), Category("自定义属性"), Description("获取或设置管道控件的流动颜色")]
        public Color ColorCenter
        {
            get
            {
                return this.colorCenter;
            }
            set
            {
                this.colorCenter = value;
                base.Invalidate();
            }
        }

        private Color borderColor = Color.DimGray;

        [Browsable(true), Category("自定义属性"), Description("获取或设置管道边线颜色")]
        public Color BorderColor
        {
            get
            {
                return this.borderColor;
            }
            set
            {
                this.borderColor = value;
                p = new Pen(value, 1.0f);   //画边框笔的颜色
                base.Invalidate();
            }
        }

        private Color edgeColor = Color.DimGray;

        [Browsable(true), Category("自定义属性"), Description("获取或设置管道边缘颜色")]
        public Color EdgeColor
        {
            get
            {
                return this.edgeColor;
            }
            set
            {
                this.edgeColor = value;
                base.Invalidate();
            }
        }

        private Color centerColor = Color.LightGray;

        [Browsable(true), Category("自定义属性"), Description("获取或设置管道控件的中心颜色")]
        public Color LineCenterColor
        {
            get
            {
                return this.centerColor;
            }
            set
            {
                this.centerColor = value;
                base.Invalidate();
            }
        }


        private PipeTurnDirection pipeTurnLeft = PipeTurnDirection.None;

        [Browsable(true), Category("自定义属性"), Description("左管道的转向类型")]
        public PipeTurnDirection PipeTurnLeft
        {
            get
            {
                return this.pipeTurnLeft;
            }
            set
            {
                this.pipeTurnLeft = value;
                base.Invalidate();
            }
        }

        private PipeTurnDirection pipeTurnRight = PipeTurnDirection.None;

        [Browsable(true), Category("自定义属性"), Description("右管道的转向类型")]
        public PipeTurnDirection PipeTurnRight
        {
            get
            {
                return this.pipeTurnRight;
            }
            set
            {
                this.pipeTurnRight = value;
                base.Invalidate();
            }
        }

        private DirectionStyle pipeLineStyle = DirectionStyle.Horizontal;

        [Browsable(true), Category("自定义属性"), Description("设置管道是横向的还是纵向的")]
        public DirectionStyle PipeLineStyle
        {
            get
            {
                return this.pipeLineStyle;
            }
            set
            {
                this.pipeLineStyle = value;
                base.Invalidate();
            }
        }

        private bool isActive = false;

        [Browsable(true), Category("自定义属性"), DefaultValue(false), Description("获取或设置管道线是否激活液体显示")]
        public bool IsActive
        {
            get
            {
                return this.isActive;
            }
            set
            {
                this.isActive = value;

                this.mytimer.Enabled = value;   //滚动条激活,靠这个动的
                this.mytimer.Start();

                base.Invalidate();
            }
        }


        private float moveSpeed = 0.3f;

        [Browsable(true), Category("自定义属性"), Description("管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
        public float MoveSpeed
        {
            get
            {
                return this.moveSpeed;
            }
            set
            {
                this.moveSpeed = value;
                base.Invalidate();
            }
        }

        private int pipeLength = 5;

        [Browsable(true), Category("自定义属性"), Description("流动条长度")]
        public int PipeLength
        {
            get
            {
                return this.pipeLength;
            }
            set
            {
                this.pipeLength = value;
                base.Invalidate();
            }
        }

        private int gapLength = 5;

        [Browsable(true), Category("自定义属性"), Description("间隙长度")]
        public int GapLength
        {
            get
            {
                return this.gapLength;
            }
            set
            {
                this.gapLength = value;
                base.Invalidate();
            }
        }


        #endregion




        //重写onPaint
        protected override void OnPaint(PaintEventArgs e)
        {
            g = e.Graphics; //重事件中获取数据

            //设置显示质量
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;   //设置文本质量
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; //平滑-抗锯齿
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;   //这个也是抗锯齿

            p = new Pen(this.BorderColor, 1.0f);    //笔的颜色和笔头大小

            //渐变颜色数组
            ColorBlend colorBlend = new ColorBlend();
            colorBlend.Positions = new float[]
            {
                0.0f, 0.5f, 1.0f
            };
            colorBlend.Colors = new Color[]
            {
                this.BorderColor, this.centerColor, this.borderColor
            };

            //水平管道
            if (this.pipeLineStyle == DirectionStyle.Horizontal)
            {
                //水平方向的竖直刷
                LinearGradientBrush linearGradientBrush = new LinearGradientBrush(new Point(0, 0), new Point(0, this.Height), edgeColor, borderColor);
                linearGradientBrush.InterpolationColors = colorBlend;   //这个是渐变的颜色

                //左边弯曲
                switch (this.pipeTurnLeft)
                {
                    case PipeTurnDirection.Up:
                        DrawEllipse(g, p, colorBlend, new Rectangle(0, this.Height * (-1), this.Height * 2, this.Height * 2), 90.0f, 90.0f);
                        break;
                    case PipeTurnDirection.Down:
                        DrawEllipse(g, p, colorBlend, new Rectangle(0, 0, this.Height * 2, this.Height * 2), 180.0f, 90.0f);
                        break;
                    default:
                        this.PaintRectangle(g, linearGradientBrush, p, new Rectangle(0, 0, this.Height, this.Height));
                        break;
                }

                //右边弯曲
                switch (this.pipeTurnRight)
                {
                    case PipeTurnDirection.Up:
                        DrawEllipse(g, p, colorBlend, new Rectangle(this.Width - this.Height * 2, this.Height*(-1), this.Height * 2, this.Height * 2), 0.0f, 90.0f);
                        break;
                    case PipeTurnDirection.Down:
                        DrawEllipse(g, p, colorBlend, new Rectangle(this.Width - this.Height * 2, 0, this.Height * 2, this.Height * 2), 270.0f, 90.0f);
                        break;
                    case PipeTurnDirection.None:
                        PaintRectangle(g, linearGradientBrush, p, new Rectangle(this.Width - this.Height, 0, this.Height, this.Height));
                        break;
                }

                //画中间管道的矩形
                if(this.Width >= this.Height * 2)
                {
                    PaintRectangle(g, linearGradientBrush, p, new Rectangle(this.Height-1, 0, this.Width-this.Height*2+2, this.Height));
                }


                //画中间的流水
                if (isActive)
                {
                    GraphicsPath graphicspath = new GraphicsPath();

                    //左转弯流水
                    switch (this.pipeTurnLeft)
                    {
                        case PipeTurnDirection.Up:
                            //这条曲线要注意,是要按照流动的顺序才行
                            graphicspath.AddArc(new Rectangle(this.Height / 2, this.Height/2 * (-1)-1, this.Height, this.Height), 180.0f, -90.0f);
                            break;
                        case PipeTurnDirection.Down:
                            graphicspath.AddArc(new Rectangle(this.Height / 2, this.Height / 2, this.Height, this.Height), 180.0f, 90.0f);
                            break;
                        default:
                            graphicspath.AddLine(new Point(0, this.Height/2), new Point(this.Height, this.Height/2));
                            break;
                    }

                    //中间流水
                    if(this.Width >= this.Height * 2)
                    {
                        graphicspath.AddLine(this.Height, this.Height / 2, this.Width - this.Height -1, this.Height / 2);
                    }


                    //右转弯流水
                    switch (this.pipeTurnRight)
                    {
                        case PipeTurnDirection.Up:
                            graphicspath.AddArc(new Rectangle(this.Width - this.Height - this.Height/2, this.Height / 2 * (-1), this.Height, this.Height), 0.0f, 90.0f);
                            break;
                        case PipeTurnDirection.Down:
                            graphicspath.AddArc(new Rectangle(this.Width - this.Height - this.Height/2, this.Height / 2, this.Height, this.Height), 270.0f, 90.0f);
                            break;
                        case PipeTurnDirection.None:
                            graphicspath.AddLine(new Point(this.Width - this.Height, this.Height / 2), new Point(this.Width, this.Height / 2));
                            break;
                    }

                    //画笔要能画虚线的
                    Pen pen = new Pen(this.colorCenter, PipeWidth);
                    pen.DashStyle = DashStyle.Custom;
                    pen.DashPattern = new float[]
                    {
                        pipeLength, pipeLength
                    };
                    pen.DashOffset = startOffset;
                    g.DrawPath(pen, graphicspath);
                }
            }

            //这个是自带的,但好像没什么用
            //base.OnPaint(e);
        }



        private void DrawEllipse(Graphics g, Pen p, ColorBlend colorBlend, Rectangle rect, float startAngle, float sweepAngle)
        {
            //画渐变画刷
            GraphicsPath graphicspath = new GraphicsPath();
            graphicspath.AddEllipse(rect);

            //椭圆的渐变画刷
            PathGradientBrush pathGradientBrush = new PathGradientBrush(graphicspath);

            pathGradientBrush.CenterPoint = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
            pathGradientBrush.InterpolationColors = colorBlend;


            //画扇形和沿着扇形的路线
            g.FillPie(pathGradientBrush, rect, startAngle, sweepAngle);
            g.DrawArc(p, rect, startAngle, sweepAngle);
        }

        /// <summary>
        /// 画中间的矩形
        /// </summary>
        /// <param name="g"></param>
        /// <param name="brush">这个是渐变画刷</param>
        /// <param name="pen"></param>
        /// <param name="rectangle"></param>
        private void PaintRectangle(Graphics g, Brush brush, Pen pen, Rectangle rectangle)
        {
            g.FillRectangle(brush, rectangle);  //矩形填满

            switch (this.pipeLineStyle) //矩形周围的线
            {
                case DirectionStyle.Horizontal:
                    g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X + rectangle.Width, rectangle.Y);  //上面的线
                    g.DrawLine(pen, rectangle.X, rectangle.Y + rectangle.Height - 1, rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height - 1);  //上面的线
                    break;
                case DirectionStyle.Vertical:
                    g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X, rectangle.Y + rectangle.Height);   //左边线
                    g.DrawLine(pen, rectangle.X + rectangle.Width - 1, rectangle.Y, rectangle.X + rectangle.Width - 1, rectangle.Y + rectangle.Height - 1);
                    break;
                default:
                    break;
            }
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值