C#自定义TrackBar,支持自定义按钮组

C#自定义TrackBar,支持自定义按钮组

支接定义背景按钮
在这里插入图片描述
在这里插入图片描述

支接定义背景按钮不支持拖动
在这里插入图片描述

基础功能
在这里插入图片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace libBase.Controls
{

public enum ControlState { Normal, Hover, Pressed, Focused };

[DefaultBindingProperty("Value"), DefaultEvent("ValueChanged"), DefaultProperty("Value"), Designer(typeof(AutoSizeDesigner))]
[ToolboxBitmap(typeof(TrackBar))]
public class WTrackBar : Control, ISupportInitialize
{
    public WTrackBar() : base()
    {
        SetStyle(ControlStyles.UserPaint |
           ControlStyles.AllPaintingInWmPaint |
           ControlStyles.OptimizedDoubleBuffer |
           ControlStyles.ResizeRedraw |
           ControlStyles.SupportsTransparentBackColor, true);

        this.BackColor = Color.Transparent;
    }

    #region  public


    protected override Size DefaultSize => new Size(104, GetSystemMetrics(3) * 8 / 3);

    protected override ImeMode DefaultImeMode => ImeMode.Disable;

    [EditorBrowsable(EditorBrowsableState.Never)]
    protected override bool DoubleBuffered
    {
        get
        {
            return base.DoubleBuffered;
        }
        set
        {
            base.DoubleBuffered = value;
        }
    }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public override Font Font
    {
        get
        {
            return base.Font;
        }
        set
        {
            base.Font = value;
        }
    }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

    public override Color ForeColor
    {
        get
        {
            return SystemColors.WindowText;
        }
        set
        {
        }
    }
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public new ImeMode ImeMode
    {
        get
        {
            return base.ImeMode;
        }
        set
        {
            base.ImeMode = value;
        }
    }

    [Browsable(true), DefaultValue(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), EditorBrowsable(EditorBrowsableState.Always)]
    public override bool AutoSize
    {
        get
        {
            return this.autoSize;
        }
        set
        {
            if (this.autoSize != value)
            {
                this.autoSize = value;
                if (this.orientation == Orientation.Horizontal)
                {
                    base.SetStyle(ControlStyles.FixedHeight, this.autoSize);
                    base.SetStyle(ControlStyles.FixedWidth, false);
                }
                else
                {
                    base.SetStyle(ControlStyles.FixedWidth, this.autoSize);
                    base.SetStyle(ControlStyles.FixedHeight, false);
                }

                int num = this.originalLength;
                try
                {
                    if (this.orientation == Orientation.Horizontal)
                    {
                        base.Height = (this.autoSize ? this.DefaultSize.Height : num);
                    }
                    else
                    {
                        base.Width = (this.autoSize ? this.DefaultSize.Height : num);
                    }
                }
                finally
                {
                    this.originalLength = num;
                }

                this.OnAutoSizeChanged(EventArgs.Empty);
            }
        }
    }




    [Category("Track"), DefaultValue(0), Browsable(true), Description("轨道的最小值。"), RefreshProperties(RefreshProperties.All)]
    public int Minimum
    {
        get { return this._minValue; }
        set
        {
            if (this._minValue != value)
            {
                if (value > this._maxValue)
                {
                    this._maxValue = value;
                }
                this.SetRange(value, this._maxValue);
            }
        }
    }

    [Category("Track"), DefaultValue(100), Browsable(true), Description("轨道的最大值。"), RefreshProperties(RefreshProperties.All)]
    public int Maximum
    {
        get { return this._maxValue; }
        set
        {
            if (value != this._maxValue)
            {
                if (value < this._minValue)
                {
                    this._minValue = value;
                }
                this.SetRange(this._minValue, value);
            }
        }
    }


    [Category("Track"), DefaultValue(typeof(Orientation), "0"), Browsable(true), Description("控件的方向"), Localizable(true)]
    public Orientation Orientation
    {
        get { return orientation; }
        set
        {
            if (orientation != value)
            {
                orientation = value;
                this.Size = new Size(this.Height, this.Width);
                this._sliderSize = new Size(this._sliderSize.Height, this._sliderSize.Width);
                base.Invalidate();
            }
        }
    }


    [Category("Track"), DefaultValue(0), Browsable(true), Description("当前滑块的值")]
    public int Value
    {
        get { return this._currValue; }
        set
        {
            if (this._currValue != value)
            {
                if (!this.initializing && (value < this.Minimum || value > this.Maximum))
                {
                    throw new ArgumentOutOfRangeException(nameof(Value), "所设置的值超出范围");
                }

                this._currValue = value;
                base.Invalidate();
                this.OnValueChanged();
            }
        }
    }

    [Browsable(true), EditorBrowsable(EditorBrowsableState.Always), Description("当滑块的值改变后触发此事件")]
    public event EventHandler ValueChanged = null;//值改变事件

    public enum DrawTrackMode
    {
        Draw,
        Image
    }

    [Category("Track"), Description("TrackBar的绘制方式"), Browsable(true), DefaultValue(typeof(DrawTrackMode), "Draw")]
    public DrawTrackMode TrackStyle
    {
        get { return this._trackStyle; }
        set
        {
            if (this._trackStyle == value)
            {
                return;
            }
            this._trackStyle = value;
            base.Invalidate();
        }
    }

    [Category("Track"), DefaultValue(2), Browsable(true), Description("滑动轨道的宽度")]
    public int TrackLineWidth
    {
        get { return this._lineWidth; }
        set
        {
            if (this._lineWidth != value)
            {
                if (value < 1)
                {
                    throw new ArgumentException(nameof(TrackLineWidth), "滑轨宽度设置有误");
                }
                this._lineWidth = value;
                base.Invalidate();
            }
        }
    }

    [Category("Track"), Description("滑块大小,当TrackStyle为Image时,可配合使用"), Browsable(true), DefaultValue(typeof(Size), "8,20")]
    public Size TrackSliderSize
    {
        get { return this._sliderSize; }
        set
        {
            if (this._sliderSize != value)
            {
                this._sliderSize = value;
                base.Invalidate();
            }
        }
    }

    public Color FontDrawBackgroundText
    {
        get { return _fontDrawBackgroundText; }
        set
        {
            _fontDrawBackgroundText = value;
            base.Invalidate();
        }
    }

    //======color=====

    public Color ColorDrawBackgroundText
    {
        get { return this._ColorDrawBackgroundText; }
        set
        {
            if (this._ColorDrawBackgroundText != value)
            {
                this._ColorDrawBackgroundText = value;
                base.Invalidate();
            }
        }
    }

    [Category("Track"), Description("滑轨底层颜色"), Browsable(true), DefaultValue(typeof(Color), "187, 188, 188")]
    public Color ColorBackLine
    {
        get { return this._colorBackLine; }
        set
        {
            if (this._colorBackLine != value)
            {
                this._colorBackLine = value;
                base.Invalidate();
            }
        }
    }

    [Category("Track"), Description("滑轨表层颜色"), Browsable(true), DefaultValue(typeof(Color), "0, 100, 182")]
    public Color ColorSurfaceLine
    {
        get { return this._colorSurfaceLine; }
        set
        {
            if (this._colorSurfaceLine != value)
            {
                this._colorSurfaceLine = value;
                base.Invalidate();
            }
        }
    }

    [Category("Track"), Description("滑块正常状态颜色"), Browsable(true), DefaultValue(typeof(Color), "0, 100, 182")]
    public Color ColorSliderNormal
    {
        get { return this._colorSliderNormal; }
        set
        {
            if (this._colorSliderNormal != value)
            {
                this._colorSliderNormal = value;
                base.Invalidate();
            }
        }
    }

    [Category("Track"), Description("滑块鼠标滑过颜色"), Browsable(true), DefaultValue(typeof(Color), "72, 72, 73")]
    public Color ColorSliderOver
    {
        get { return this._colorSliderOver; }
        set
        {
            if (this._colorSliderOver != value)
            {
                this._colorSliderOver = value;
                base.Invalidate();
            }
        }
    }

    [Category("Track"), Description("滑块鼠标滑过颜色"), Browsable(true), DefaultValue(typeof(Color), "121, 128, 134")]
    public Color ColorSliderDown
    {
        get { return this._colorSliderDown; }
        set
        {
            if (this._colorSliderDown != value)
            {
                this._colorSliderDown = value;
                base.Invalidate();
            }
        }
    }

    //======image=====

    [Category("Track"), DefaultValue(null), Description("滑轨底层图片"), Browsable(true)]
    public Image ImageBackLine
    {
        get { return this._imageBackLine; }
        set
        {
            if (this._imageBackLine != value)
            {
                this._imageBackLine = value;
                base.Invalidate();
            }
        }
    }

    [Category("Track"), DefaultValue(null), Description("滑轨表层图片"), Browsable(true)]
    public Image ImageSurfaceLine
    {
        get { return this._imageSurfaceLine; }
        set
        {
            if (this._imageSurfaceLine != value)
            {
                this._imageSurfaceLine = value;
                base.Invalidate();
            }
        }
    }

    [Category("Track"), DefaultValue(null), Description("滑块正常状态的图像"), Browsable(true)]
    public Image ImageSliderNormal
    {
        get { return this._imageSliderNormal; }
        set
        {
            if (this._imageSliderNormal != value)
            {
                this._imageSliderNormal = value;
                base.Invalidate();
            }
        }
    }

    [Category("Track"), DefaultValue(null), Description("滑块鼠标滑过时的图像"), Browsable(true)]
    public Image ImageSliderOver
    {
        get { return this._imageSliderOver; }
        set
        {
            if (this._imageSliderOver != value)
            {
                this._imageSliderOver = value;
            }
        }
    }

    [Category("Track"), DefaultValue(null), Description("滑块鼠标按下时的图像"), Browsable(true)]
    public Image ImageSliderDown
    {
        get { return this._imageSliderDown; }
        set
        {
            if (this._imageSliderDown != value)
            {
                this._imageSliderDown = value;
            }
        }
    }


    #endregion

    #region private

    private Orientation orientation = System.Windows.Forms.Orientation.Horizontal;

    private bool autoSize = true;
    private int originalLength = GetSystemMetrics(3) * 8 / 3;//存储原始大小,用于改变成自适应尺寸之前的尺寸.


    private int _minValue = 0;
    private int _maxValue = 100;
    private int _currValue = 0;

    private DrawTrackMode _trackStyle = DrawTrackMode.Draw;

    private int _lineWidth = 2;//线宽

    private int offset = 2;//轨道距离两头的余量.

    private Size _sliderSize = new Size(8, 20);//滑块大小

    private Color _fontDrawBackgroundText = Color.Gray;

    //color
    private Color _colorBackLine = Color.FromArgb(187, 188, 188);
    private Color _colorSurfaceLine = Color.FromArgb(0, 100, 182);

    private Color _colorSliderNormal = Color.FromArgb(0, 100, 182);
    private Color _colorSliderOver = Color.FromArgb(72, 72, 73);
    private Color _colorSliderDown = Color.FromArgb(121, 128, 134);

    private Color _ColorDrawBackgroundText = Color.FromArgb(187, 188, 188);

    //Slider
    private Image _imageBackLine = null;
    private Image _imageSurfaceLine = null;

    private Image _imageSliderNormal = null;
    private Image _imageSliderOver = null;
    private Image _imageSliderDown = null;

    private bool vewSliderValueFont = false;
    private bool isDrawBackgroundText = false;

    private ControlState _controlState = ControlState.Normal;

    public event EventHandler ButtonClick = null;

    private ControlState MouseState
    {
        get { return _controlState; }
        set
        {
            if (_controlState != value)
            {
                _controlState = value;
                base.Invalidate();
            }
        }
    }

    public bool VewSliderValueFont { get => vewSliderValueFont; set => vewSliderValueFont = value; }

    protected bool isMouseDown = false;

    protected ButtonItemCollection buttonItems1 = new ButtonItemCollection();

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public ButtonItemCollection Buttons
    {
        get { return buttonItems1; }
    }

    public bool IsDrawBackgroundText { get => isDrawBackgroundText; set => isDrawBackgroundText = value; }

    #endregion

    #region override

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (!this.isMouseDown)
        {
            this.MouseState = this.IsInSliderArea(e.Location) ? ControlState.Hover : this.MouseState = ControlState.Normal;
        }
        else
        {
            if (e.Button == MouseButtons.Left)
            {
                this.MouseState = ControlState.Pressed;
                this.ChangeValue(e.Location);
            }
        }

        base.OnMouseMove(e);
    }

    protected void ActivateButtonClickEvent(object sender, EventArgs e)
    {
        if (ButtonClick != null)
        {
            ButtonClick(sender, e);
        }
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.Focus();
        if (e.Button == MouseButtons.Left && e.Clicks == 1)
        {
            ButtonItem btnitem = buttonItems1.IndexOf(e.Location);
            if (btnitem != null)
            {
                this.isMouseDown = true;
                Value = btnitem.Value;
                ActivateButtonClickEvent(btnitem, e);
            }
            else
            {
                if (this.IsInSliderArea(e.Location))//滑块内.
                {
                    this.isMouseDown = true;
                    this.MouseState = ControlState.Pressed;
                    base.OnMouseDown(e);
                }
                else
                {
                    ChangeValue(e.Location);

                    if (this.IsInSliderArea(e.Location))//滑块内.
                    {
                        this.isMouseDown = true;
                        this.MouseState = ControlState.Pressed;
                    }
                }
            }
        }

    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left && e.Clicks == 1)
        {
            this.isMouseDown = false;
            this.MouseState = this.IsInSliderArea(e.Location) ? ControlState.Hover : ControlState.Normal;
        }

        base.OnMouseUp(e);
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        if (!this.isMouseDown)
        {
            this.MouseState = ControlState.Normal;
        }
        base.OnMouseLeave(e);
    }


    protected override void OnMouseCaptureChanged(EventArgs e)
    {
        if (!base.Capture)//未捕获鼠标
        {
            isMouseDown = false;
        }
        base.OnMouseCaptureChanged(e);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        base.OnPaintBackground(e);
        e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
        switch (_trackStyle)
        {
            case DrawTrackMode.Draw:
                this.DrawWork(e.Graphics);
                break;
            case DrawTrackMode.Image:
                this.DrawImageWork(e.Graphics);
                break;
            default:
                break;
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _imageBackLine?.Dispose();
            _imageSurfaceLine?.Dispose();

            _imageSliderNormal?.Dispose();
            _imageSliderOver?.Dispose();
            _imageSliderDown?.Dispose();
        }
        base.Dispose(disposing);
    }

    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
    {
        this.originalLength = ((this.orientation == Orientation.Horizontal) ? height : width);
        if (this.autoSize)
        {
            if (this.orientation == Orientation.Horizontal)
            {
                if ((specified & BoundsSpecified.Height) != BoundsSpecified.None)
                {
                    height = this.DefaultSize.Height;
                }
            }
            else
            {
                if ((specified & BoundsSpecified.Width) != BoundsSpecified.None)
                {
                    width = this.DefaultSize.Height;
                }
            }
        }
        base.SetBoundsCore(x, y, width, height, specified);
    }

    #endregion

    #region methods

    //设置轨道长度
    private void SetRange(int minValue, int maxValue)
    {
        if (this._minValue != minValue || this._maxValue != maxValue)
        {
            if (minValue > maxValue)
            {
                maxValue = minValue;
            }
            this._minValue = minValue;
            this._maxValue = maxValue;
            if (this._currValue < this._minValue)
            {
                this._currValue = this._minValue;
            }
            if (this._currValue > this._maxValue)
            {
                this._currValue = this._maxValue;
            }
            base.Invalidate();
        }

    }

    //获取滑块位置
    private PointF GetSliderPoint()
    {
        var len = GetValueLength();
        float x, y;
        if (this.orientation == Orientation.Horizontal)
        {
            x = len - this._sliderSize.Width / 2f;
            y = (this.ClientRectangle.Height - this._sliderSize.Height) / 2f;
            if (x < offset) x = offset;
            if (x > this.ClientRectangle.Width - this._sliderSize.Width - offset) x = this.ClientRectangle.Width - this._sliderSize.Width - offset;
            return new PointF(x, y);
        }

        x = (this.ClientRectangle.Width - this._sliderSize.Width) / 2f;
        y = this.ClientRectangle.Height - len - this._sliderSize.Height / 2f;
        if (y < offset) y = offset;
        if (y > this.ClientRectangle.Height - this._sliderSize.Height - offset) y = this.ClientRectangle.Height - this._sliderSize.Height - offset;

        return new PointF(x, y);
    }

    //鼠标落点是否在滑块内
    private bool IsInSliderArea(Point point)
    {
        var rect = new RectangleF(GetSliderPoint(), this._sliderSize);

        return rect.Contains(point);
    }

    //单击或滑动改变值
    private void ChangeValue(Point point)
    {
        if (this.orientation == Orientation.Horizontal)
        {
            if (point.X <= this.ClientRectangle.X + offset + this._sliderSize.Width / 2f)
            {
                this.Value = this._minValue;
                return;
            }
            if (point.X >= this.ClientRectangle.Right - offset - this._sliderSize.Width / 2f)
            {
                this.Value = this._maxValue;
                return;
            }
            float len = point.X - this._sliderSize.Width / 2f - offset;
            var percent = len / (this.ClientRectangle.Width - this._sliderSize.Width - 2 * offset);
            var v = this._minValue + (int)((this._maxValue - this._minValue) * percent);
            if (v > this._maxValue) { v = this._maxValue; }
            if (v < this._minValue) { v = this._minValue; }
            this.Value = v;
        }
        else
        {
            if (point.Y <= this.ClientRectangle.Y + offset + this._sliderSize.Height / 2f)
            {
                this.Value = this._maxValue;
                return;
            }
            if (point.Y >= this.ClientRectangle.Bottom - offset - this._sliderSize.Height / 2f)
            {
                this.Value = this._minValue;
                return;
            }
            var len = this.ClientRectangle.Height - point.Y - offset - this._sliderSize.Height / 2f;
            var total = this.ClientRectangle.Height - this._sliderSize.Height - 2 * offset;
            var percent = len / total;
            var v = this._minValue + (int)((this._maxValue - this._minValue) * percent);
            if (v > this._maxValue) { v = this._maxValue; }
            if (v < this._minValue) { v = this._minValue; }
            this.Value = v;
        }
    }

    //当前值对应的距离控件边缘长度
    private float GetValueLength()
    {
        float total = this._maxValue - this._minValue;
        float curr = this._currValue - this._minValue;
        var percent = curr / total;
        var len = 1f;

        switch (this.orientation)
        {
            case Orientation.Horizontal:
                var hOffset = this._sliderSize.Width + 2 * offset;
                len = (this.ClientRectangle.Width - hOffset) * percent + hOffset / 2f;
                break;
            case Orientation.Vertical:
                var vOffset = this._sliderSize.Height + 2 * offset;
                len = (this.ClientRectangle.Height - vOffset) * percent + vOffset / 2f;
                break;
            default:
                len = this._sliderSize.Width / 2f + offset;
                break;
        }
        return len;
    }

    private void DrawWork(Graphics g)
    {

        DrawColorTrackLine(true, g);
        DrawColorTrackLine(false, g);

        if (isDrawBackgroundText)
            DrawBackgroundText(g);

        //滑块
        var rect = new RectangleF(GetSliderPoint(), this._sliderSize);

        Color color;
        switch (this._controlState)
        {
            case ControlState.Focused:
            case ControlState.Normal:
                color = this._colorSliderNormal;
                break;
            case ControlState.Hover:
                color = this._colorSliderOver;
                break;
            case ControlState.Pressed:
                color = this._colorSliderDown;
                break;
            default:
                color = this._colorSliderNormal;
                break;
        }
        if (!this.Enabled)
        {
            color = Color.LightGray;
        }

        var r = this.orientation == Orientation.Horizontal ? rect.Width / 2f : rect.Height / 2f;

        using (var brush = new SolidBrush(color))
        {
            using (var gp = RenderHelper.CreateRoundPath(rect, (int)r))
            {
                g.FillPath(brush, gp);
                using (var p = new Pen(color, 1))
                {
                    g.DrawPath(p, gp);
                    string text = GetSliderValue();
                    DrawSliderValueFont(g, rect, text);
                }
            }
        }

    }

    private string GetSliderValue()
    {
        ButtonItem item = buttonItems1.IndexOf(Value);
        if (item != null)
        {
            if (item.DisplayModule == ButtonDisplayModule.Caption)
                return item.Caption;
        }
        return Value.ToString();
    }

    private void DrawBackgroundText(Graphics g)
    {
        for (int i = 0; i < buttonItems1.Count; i++)
        {

            int curslidervalue = buttonItems1[i].Value;
            RectangleF rect = new RectangleF(GetSliderPoint(curslidervalue), this._sliderSize);
            buttonItems1[i].SetRect(rect.X, rect.Y, rect.Width, rect.Height);

            Color color = this.ColorBackLine;
            if (Value > buttonItems1[i].Value) color = this._colorSliderNormal;

            var r = this.orientation == Orientation.Horizontal ? rect.Width / 2f : rect.Height / 2f;

            buttonItems1[i].Display(g, color, (int)r);
            if (this.vewSliderValueFont)
            {
                string text = buttonItems1[i].Value.ToString();
                if (buttonItems1[i].DisplayModule == ButtonDisplayModule.Caption) text = buttonItems1[i].Caption.ToString();
                buttonItems1[i].DrawText(g, this.Font, buttonItems1[i].Rect, text, _fontDrawBackgroundText);
            }

        }

    }

    private float GetValueLength(int curvalue)
    {
        float total = this._maxValue - this._minValue;
        float curr = curvalue - this._minValue;
        var percent = curr / total;
        var len = 1f;

        switch (this.orientation)
        {
            case Orientation.Horizontal:
                var hOffset = this._sliderSize.Width + 2 * offset;
                len = (this.ClientRectangle.Width - hOffset) * percent + hOffset / 2f;
                break;
            case Orientation.Vertical:
                var vOffset = this._sliderSize.Height + 2 * offset;
                len = (this.ClientRectangle.Height - vOffset) * percent + vOffset / 2f;
                break;
            default:
                len = this._sliderSize.Width / 2f + offset;
                break;
        }
        return len;
    }

    //获取滑块位置
    private PointF GetSliderPoint(int curvalue)
    {
        var len = GetValueLength(curvalue);
        float x, y;
        if (this.orientation == Orientation.Horizontal)
        {
            x = len - this._sliderSize.Width / 2f;
            y = (this.ClientRectangle.Height - this._sliderSize.Height) / 2f;
            if (x < offset) x = offset;
            if (x > this.ClientRectangle.Width - this._sliderSize.Width - offset) x = this.ClientRectangle.Width - this._sliderSize.Width - offset;
            return new PointF(x, y);
        }

        x = (this.ClientRectangle.Width - this._sliderSize.Width) / 2f;
        y = this.ClientRectangle.Height - len - this._sliderSize.Height / 2f;
        if (y < offset) y = offset;
        if (y > this.ClientRectangle.Height - this._sliderSize.Height - offset) y = this.ClientRectangle.Height - this._sliderSize.Height - offset;

        return new PointF(x, y);
    }

    //画颜色轨道
    private void DrawColorTrackLine(bool isBackLine, Graphics g)
    {
        var sm = g.SmoothingMode;

        g.SmoothingMode = SmoothingMode.Default;

        if (isBackLine)
        {
            var color = this.Enabled ? this._colorBackLine : Color.LightGray;

            using (Pen backPen = new Pen(color, this._lineWidth))
            {

                switch (this.orientation)
                {
                    case Orientation.Horizontal:
                        g.DrawLine(backPen, offset + this._sliderSize.Width / 2f, this.ClientRectangle.Height / 2f, this.ClientRectangle.Width - offset - this._sliderSize.Width / 2f, this.ClientRectangle.Height / 2f);
                        break;
                    case Orientation.Vertical:
                        g.DrawLine(backPen, this.ClientRectangle.Width / 2f, offset + this._sliderSize.Height / 2f, this.ClientRectangle.Width / 2f, this.ClientRectangle.Height - offset - this._sliderSize.Height / 2f);
                        break;
                    default:
                        break;
                }
            }
        }
        else
        {
            var color = this.Enabled ? this._colorSurfaceLine : Color.LightGray;
            var len = GetValueLength();
            using (Pen surfacePen = new Pen(color, this._lineWidth))
            {
                switch (this.orientation)
                {
                    case Orientation.Horizontal:
                        g.DrawLine(surfacePen, offset + this._sliderSize.Width / 2f, this.ClientRectangle.Height / 2f, len, this.ClientRectangle.Height / 2f);
                        break;
                    case Orientation.Vertical:
                        g.DrawLine(surfacePen, this.ClientRectangle.Width / 2f, this.ClientRectangle.Height - len, this.ClientRectangle.Width / 2f, this.ClientRectangle.Height - offset - this._sliderSize.Height / 2f);
                        break;
                    default:
                        break;
                }
            }
        }
        g.SmoothingMode = sm;
    }

    private void DrawImageWork(Graphics g)
    {
        //底层
        if (this._imageBackLine == null)
        {
            this.DrawColorTrackLine(true, g);
        }
        else
        {
            RectangleF backRect;
            if (orientation == Orientation.Horizontal)
            {
                backRect = new RectangleF(offset + this._sliderSize.Width / 2f, (this.ClientRectangle.Height - this._lineWidth) / 2f, this.ClientRectangle.Width - offset * 2 - this._sliderSize.Width, this._lineWidth);
            }
            else
            {
                backRect = new RectangleF((this.ClientRectangle.Width - this._lineWidth) / 2f, offset + this._sliderSize.Height / 2f, this._lineWidth, this.ClientRectangle.Height - offset * 2 - this._sliderSize.Height);
            }

            if (!this.Enabled)
            {
                using (var bmp = this._imageBackLine.Clone() as Bitmap)
                {
                    GrayImage(bmp);
                    g.DrawImage(bmp, backRect);
                }
            }
            else
                g.DrawImage(this._imageBackLine, backRect);
        }
        //表层
        if (this._imageSurfaceLine == null)
        {
            this.DrawColorTrackLine(false, g);
        }
        else
        {
            var len = GetValueLength();
            RectangleF sufaceRect;
            if (orientation == Orientation.Horizontal)
            {
                sufaceRect = new RectangleF(offset + this._sliderSize.Width / 2f, (this.ClientRectangle.Height - this._lineWidth) / 2f, len - offset - this._sliderSize.Width / 2f, this._lineWidth);
            }
            else
            {
                sufaceRect = new RectangleF((this.ClientRectangle.Width - this._lineWidth) / 2f, this.ClientRectangle.Height - len, this._lineWidth, len - offset - this._sliderSize.Height / 2f);
            }

            if (!this.Enabled)
            {
                using (var bmp = this._imageSurfaceLine.Clone() as Bitmap)
                {
                    GrayImage(bmp);
                    g.DrawImage(bmp, sufaceRect);
                }
            }
            else
                g.DrawImage(this._imageSurfaceLine, sufaceRect);
        }

        //滑块
        var rect = new RectangleF(GetSliderPoint(), this._sliderSize);
        if (!this.Enabled)
        {
            using (var bmp = this._imageSliderNormal.Clone() as Bitmap)
            {
                GrayImage(bmp);
                g.DrawImage(bmp, rect);
            }
            return;
        }

        Image img;
        switch (this._controlState)
        {

            case ControlState.Focused:
            case ControlState.Normal:
            default:
                img = this._imageSliderNormal;
                break;
            case ControlState.Hover:
                img = this._imageSliderOver;
                break;
            case ControlState.Pressed:
                img = this._imageSliderDown;
                break;
        }
        if (img != null)
            g.DrawImage(img, rect);
    }

    private void DrawSliderValueFont(Graphics g, RectangleF R, string text)
    {
        if (vewSliderValueFont)
        {
            SolidBrush brush = new SolidBrush(Color.YellowGreen);
            StringFormat format = new StringFormat(StringFormatFlags.NoClip);
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;
            g.DrawString(text, this.Font, brush, R, format);
        }
    }

    protected virtual void OnValueChanged()
    {
        ValueChanged?.Invoke(this, EventArgs.Empty);
    }


    private unsafe static void GrayImage(Bitmap bmp)
    {
        if (bmp == null)
        {
            return;
        }
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        int step = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8;

        BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
        int w = bmpData.Width;
        int h = bmpData.Height;
        int offset = bmpData.Stride - bmpData.Width * step;
        byte* ptr = (byte*)(bmpData.Scan0);
        for (int i = 0; i < h; i++)
        {
            for (int j = 0; j < w; j++)
            {
                byte color = (byte)(ptr[2] * 0.299 + ptr[1] * 0.587 + ptr[0] * 0.114);
                ptr[2] = ptr[1] = ptr[0] = color;
                ptr += step;
            }
            ptr += offset;
        }
        bmp.UnlockBits(bmpData);
    }
	
    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern int GetSystemMetrics(int nIndex);
	
    #endregion

    #region ISupportInitialize

    private bool initializing;
    void ISupportInitialize.BeginInit()
    {
        initializing = true;
    }

    void ISupportInitialize.EndInit()
    {
        initializing = false;

        if (this.Value < this.Minimum)
        {
            this.Value = this.Minimum;
        }
        if (this.Value > this.Maximum)
        {
            this.Value = this.Maximum;
        }
    }

    #endregion
}

public class WTrackButtonsBar : WTrackBar
{

    public WTrackButtonsBar()
    {
        this.TrackLineWidth = 10;
        Size s = new Size(20, 20);
        this.TrackSliderSize = s;
        this.IsDrawBackgroundText = true;
        this.VewSliderValueFont = true;
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        //base.OnMouseMove(e);
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        //base.OnMouseUp(e);
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.Focus();
        if (e.Button == MouseButtons.Left && e.Clicks == 1)
        {
            ButtonItem btnitem = this.buttonItems1.IndexOf(e.Location);
            if (btnitem != null)
            {
                isMouseDown = true;
                Value = btnitem.Value;
                ActivateButtonClickEvent(btnitem, e);
            }
        }
    }

}

internal class AutoSizeDesigner : ControlDesigner
{
    public override SelectionRules SelectionRules
    {
        get
        {
            SelectionRules selectionRules = base.SelectionRules;
            PropertyDescriptor propDescriptor = TypeDescriptor.GetProperties(this.Component)["AutoSize"];

            PropertyDescriptor oriDescriptor = TypeDescriptor.GetProperties(this.Component)["Orientation"];

            if (propDescriptor != null)
            {
                bool autoSize = (bool)propDescriptor.GetValue(this.Component);
                if (autoSize)
                {
                    if (oriDescriptor != null)
                    {
                        var ori = (Orientation)oriDescriptor.GetValue(this.Component);
                        if (ori == Orientation.Horizontal)
                        {
                            selectionRules = SelectionRules.Visible | SelectionRules.Moveable | SelectionRules.LeftSizeable | SelectionRules.RightSizeable;
                        }
                        else
                        {
                            selectionRules = SelectionRules.Visible | SelectionRules.Moveable | SelectionRules.BottomSizeable | SelectionRules.TopSizeable;
                        }
                    }
                    else
                    {
                        selectionRules = SelectionRules.Visible | SelectionRules.Moveable;
                    }
                }
                else
                {
                    selectionRules = SelectionRules.Visible | SelectionRules.AllSizeable | SelectionRules.Moveable;
                }
            }
            return selectionRules;
        }
    }
}

/// 
/// 窗体自绘辅助类
/// 
public class RenderHelper
{


    /// 
    /// 取低位 X 坐标
    /// 
    public static int LOWORD(int value)
    {
        return value & 0xFFFF;
    }

    /// 
    /// 取高位 Y 坐标
    /// 
    public static int HIWORD(int value)
    {
        return value >> 16;
    }

    /// 
    /// 绘制窗体边框
    /// 
    /// 需要绘制边框的窗体
    /// 绘制边框所用的绘图对象
    /// 边框图片
    /// 边框的圆角矩形
    public static void DrawFormFringe(Form destForm, Graphics g, Image fringeImg, int radius)
    {
        DrawImageWithNineRect(
            g,
            fringeImg,
            new Rectangle(-radius, -radius, destForm.ClientSize.Width + 2 * radius, destForm.ClientSize.Height + 2 * radius),
            new Rectangle(0, 0, fringeImg.Width, fringeImg.Height));
    }

    /// 
    /// 利用九宫图绘制图像
    /// 
    /// 绘图对象
    /// 所需绘制的图片
    /// 目标矩形
    /// 来源矩形
    public static void DrawImageWithNineRect(Graphics g, Image img, Rectangle targetRect, Rectangle srcRect)
    {
        int offset = 5;
        Rectangle NineRect = new Rectangle(img.Width / 2 - offset, img.Height / 2 - offset, 2 * offset, 2 * offset);
        int x = 0, y = 0, nWidth, nHeight;
        int xSrc = 0, ySrc = 0, nSrcWidth, nSrcHeight;
        int nDestWidth, nDestHeight;
        nDestWidth = targetRect.Width;
        nDestHeight = targetRect.Height;
        // 左上-------------------------------------;
        x = targetRect.Left;
        y = targetRect.Top;
        nWidth = NineRect.Left - srcRect.Left;
        nHeight = NineRect.Top - srcRect.Top;
        xSrc = srcRect.Left;
        ySrc = srcRect.Top;
        g.DrawImage(img, new Rectangle(x, y, nWidth, nHeight), xSrc, ySrc, nWidth, nHeight, GraphicsUnit.Pixel);
        // 上-------------------------------------;
        x = targetRect.Left + NineRect.Left - srcRect.Left;
        nWidth = nDestWidth - nWidth - (srcRect.Right - NineRect.Right);
        xSrc = NineRect.Left;
        nSrcWidth = NineRect.Right - NineRect.Left;
        nSrcHeight = NineRect.Top - srcRect.Top;
        g.DrawImage(img, new Rectangle(x, y, nWidth, nHeight), xSrc, ySrc, nSrcWidth, nSrcHeight, GraphicsUnit.Pixel);
        // 右上-------------------------------------;
        x = targetRect.Right - (srcRect.Right - NineRect.Right);
        nWidth = srcRect.Right - NineRect.Right;
        xSrc = NineRect.Right;
        g.DrawImage(img, new Rectangle(x, y, nWidth, nHeight), xSrc, ySrc, nWidth, nHeight, GraphicsUnit.Pixel);
        // 左-------------------------------------;
        x = targetRect.Left;
        y = targetRect.Top + NineRect.Top - srcRect.Top;
        nWidth = NineRect.Left - srcRect.Left;
        nHeight = targetRect.Bottom - y - (srcRect.Bottom - NineRect.Bottom);
        xSrc = srcRect.Left;
        ySrc = NineRect.Top;
        nSrcWidth = NineRect.Left - srcRect.Left;
        nSrcHeight = NineRect.Bottom - NineRect.Top;
        g.DrawImage(img, new Rectangle(x, y, nWidth, nHeight), xSrc, ySrc, nSrcWidth, nSrcHeight, GraphicsUnit.Pixel);
        // 中-------------------------------------;
        x = targetRect.Left + NineRect.Left - srcRect.Left;
        nWidth = nDestWidth - nWidth - (srcRect.Right - NineRect.Right);
        xSrc = NineRect.Left;
        nSrcWidth = NineRect.Right - NineRect.Left;
        g.DrawImage(img, new Rectangle(x, y, nWidth, nHeight), xSrc, ySrc, nSrcWidth, nSrcHeight, GraphicsUnit.Pixel);

        // 右-------------------------------------;
        x = targetRect.Right - (srcRect.Right - NineRect.Right);
        nWidth = srcRect.Right - NineRect.Right;
        xSrc = NineRect.Right;
        nSrcWidth = srcRect.Right - NineRect.Right;
        g.DrawImage(img, new Rectangle(x, y, nWidth, nHeight), xSrc, ySrc, nSrcWidth, nSrcHeight, GraphicsUnit.Pixel);

        // 左下-------------------------------------;
        x = targetRect.Left;
        y = targetRect.Bottom - (srcRect.Bottom - NineRect.Bottom);
        nWidth = NineRect.Left - srcRect.Left;
        nHeight = srcRect.Bottom - NineRect.Bottom;
        xSrc = srcRect.Left;
        ySrc = NineRect.Bottom;
        g.DrawImage(img, new Rectangle(x, y, nWidth, nHeight), xSrc, ySrc, nWidth, nHeight, GraphicsUnit.Pixel);
        // 下-------------------------------------;
        x = targetRect.Left + NineRect.Left - srcRect.Left;
        nWidth = nDestWidth - nWidth - (srcRect.Right - NineRect.Right);
        xSrc = NineRect.Left;
        nSrcWidth = NineRect.Right - NineRect.Left;
        nSrcHeight = srcRect.Bottom - NineRect.Bottom;
        g.DrawImage(img, new Rectangle(x, y, nWidth, nHeight), xSrc, ySrc, nSrcWidth, nSrcHeight, GraphicsUnit.Pixel);
        // 右下-------------------------------------;
        x = targetRect.Right - (srcRect.Right - NineRect.Right);
        nWidth = srcRect.Right - NineRect.Right;
        xSrc = NineRect.Right;
        g.DrawImage(img, new Rectangle(x, y, nWidth, nHeight), xSrc, ySrc, nWidth, nHeight, GraphicsUnit.Pixel);
    }

    /// 
    /// 获取当前命名空间下嵌入的资源图片
    /// 
    /// 嵌入的图片资源的路径
    public static Image GetImageFormResourceStream(string imagePath)
    {
        return Image.FromStream(
            Assembly.GetExecutingAssembly().
            GetManifestResourceStream(
            MethodBase.GetCurrentMethod().DeclaringType.Namespace + "." + imagePath));
    }

    /// 
    /// 获取绘制带有阴影的字符串的图像
    /// 
    /// 需要绘制的字符串
    /// 显示字符串的字体
    /// 字符串的颜色
    /// 字符串阴影颜色
    /// 阴影的宽度
    /// 绘有发光字符串的Image对象
    public static Image GetStringImgWithShadowEffect(string str, Font font, Color foreColor, Color shadowColor, int shadowWidth)
    {
        Bitmap bitmap = null;//实例化Bitmap类
        using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))//实例化Graphics类
        {
            SizeF size = g.MeasureString(str, font);//对字符串进行测量
            using (Bitmap bmp = new Bitmap((int)size.Width, (int)size.Height))//通过文字的大小实例化Bitmap类
            using (Graphics Var_G_Bmp = Graphics.FromImage(bmp))//实例化Bitmap类
            using (SolidBrush Var_BrushBack = new SolidBrush(Color.FromArgb(16, shadowColor.R, shadowColor.G, shadowColor.B)))//根据RGB的值定义画刷
            using (SolidBrush Var_BrushFore = new SolidBrush(foreColor))//定义画刷
            {
                Var_G_Bmp.SmoothingMode = SmoothingMode.HighQuality;//设置为高质量
                Var_G_Bmp.InterpolationMode = InterpolationMode.HighQualityBilinear;//设置为高质量的收缩
                Var_G_Bmp.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;//消除锯齿
                Var_G_Bmp.DrawString(str, font, Var_BrushBack, 0, 0);//给制文字
                bitmap = new Bitmap(bmp.Width + shadowWidth, bmp.Height + shadowWidth);//根据辉光文字的大小实例化Bitmap类
                using (Graphics Var_G_Bitmap = Graphics.FromImage(bitmap))//实例化Graphics类
                {
                    Var_G_Bitmap.SmoothingMode = SmoothingMode.HighQuality;//设置为高质量
                    Var_G_Bitmap.InterpolationMode = InterpolationMode.HighQualityBilinear;//设置为高质量的收缩
                    Var_G_Bitmap.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;//消除锯齿
                    //遍历辉光文字的各象素点
                    for (int x = 0; x <= shadowWidth; x++)
                    {
                        for (int y = 0; y <= shadowWidth; y++)
                        {
                            Var_G_Bitmap.DrawImageUnscaled(bmp, x, y);//绘制辉光文字的点
                        }
                    }
                    Var_G_Bitmap.DrawString(str, font, Var_BrushFore, shadowWidth / 2, shadowWidth / 2);//绘制文字
                }
            }
        }

        return bitmap;

    }


    /// 
    /// 建立带有圆角样式的路径。
    /// 
    /// 用来建立路径的矩形。
    /// 圆角的大小。
    /// 建立的路径。
    public static GraphicsPath CreateRoundPath(RectangleF rect, int radius)
    {
        GraphicsPath path = new GraphicsPath();
        int radiusCorrection = 1;
        path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
        path.AddArc(
            rect.Right - radius - radiusCorrection,
            rect.Y,
            radius,
            radius,
            270,
            90);
        path.AddArc(
            rect.Right - radius - radiusCorrection,
            rect.Bottom - radius - radiusCorrection,
            radius,
            radius, 0, 90);
        path.AddArc(
            rect.X,
            rect.Bottom - radius - radiusCorrection,
            radius,
            radius,
            90,
            90);
        path.CloseFigure();
        return path;
    }

    /// 
    /// 返回给定的颜色的ARGB的分量差值的颜色
    /// 
    /// 
    /// A
    /// R
    /// G
    /// B
    /// 
    public static Color GetColor(Color colorBase, int a, int r, int g, int b)
    {
        int a0 = colorBase.A;
        int r0 = colorBase.R;
        int g0 = colorBase.G;
        int b0 = colorBase.B;

        if (a + a0 > 255) { a = 255; } else { a = Math.Max(a + a0, 0); }
        if (r + r0 > 255) { r = 255; } else { r = Math.Max(r + r0, 0); }
        if (g + g0 > 255) { g = 255; } else { g = Math.Max(g + g0, 0); }
        if (b + b0 > 255) { b = 255; } else { b = Math.Max(b + b0, 0); }

        return Color.FromArgb(a, r, g, b);
    }

    /// 
    /// 绘制窗体主体部分白色透明层
    /// 
    /// 
    /// 
    public static void DrawFromAlphaMainPart(Form form, Graphics g)
    {
        Color[] colors =
        {
            Color.FromArgb(5, Color.White),
            Color.FromArgb(30, Color.White),
            Color.FromArgb(145, Color.White),
            Color.FromArgb(150, Color.White),
            Color.FromArgb(30, Color.White),
            Color.FromArgb(5, Color.White)
        };

        float[] pos =
        {
            0.0f,
            0.04f,
            0.10f,
            0.90f,
            0.97f,
            1.0f
        };

        ColorBlend colorBlend = new ColorBlend(6);
        colorBlend.Colors = colors;
        colorBlend.Positions = pos;

        RectangleF destRect = new RectangleF(0, 0, form.Width, form.Height);
        using (LinearGradientBrush lBrush = new LinearGradientBrush(destRect, colors[0], colors[5], LinearGradientMode.Vertical))
        {
            lBrush.InterpolationColors = colorBlend;
            g.FillRectangle(lBrush, destRect);
        }
    }
}

}

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace libBase.Controls
{

public enum ButtonViewOption  {Horizontal,Vertical};

public enum ButtonDisplayModule { Value, Caption };

[Serializable]
public class ButtonItem
{

    private int id = 0;
    private object tag = null;
    private string caption = "";
    private float width = 0;
    private float height = 0;
    private float x = 0;
    private float y = 0;
    private bool selected = false;
    private bool visible = true;
    private bool isMouseMove = false;
    private int value = 0;
    private ButtonDisplayModule displayModule = ButtonDisplayModule.Value;

    public bool Selected
    {
        get { return selected; }
        set { selected = value; }
    }

    public RectangleF Rect
    {
        get { return new RectangleF(x, y, width, height); }
    }

    public string Caption
    {
        get { return caption; }
        set { caption = value; }
    }

    public bool Visible { get => visible; set => visible = value; }
    public bool IsMouseMove { get => isMouseMove; set => isMouseMove = value; }
    public int Id { get => id; set => id = value; }
    public object Tag { get => tag; set => tag = value; }
    public int Value { get => value; set => this.value = value; }
    public ButtonDisplayModule DisplayModule { get => displayModule; set => displayModule = value; }

    public void Display(Graphics g)
    {

        int btnwidth = 0;

        using (Bitmap bmp = new Bitmap((int)width, (int)height))
        {

            Graphics tmpG = Graphics.FromImage(bmp);

            Font f = new Font("宋体", 10);
            Pen p = new Pen(Color.YellowGreen, 1);
            SolidBrush sbp = new SolidBrush(Color.Yellow);
            SolidBrush sbf = new SolidBrush(Color.Black);
            StringFormat drawFormat = new StringFormat();
            drawFormat.Alignment = StringAlignment.Center;
            drawFormat.LineAlignment = StringAlignment.Center;

            Rectangle rect1 = new Rectangle(0, 0, (int)width - btnwidth, (int)height);
            tmpG.DrawString(caption, f, sbf, rect1, drawFormat);

            if (selected)
                sbp.Color = Color.PaleVioletRed;
            else if (IsMouseMove) sbp.Color = Color.BlanchedAlmond;

            g.FillRectangle(sbp, Rect);
            g.DrawImage(bmp, Rect, new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
            g.DrawRectangle(p, Rect.X, Rect.Y, Rect.Width, Rect.Height);

        }

    }

    public void Display(Graphics g, Color color, int r)
    {
        using (var brush = new SolidBrush(color))
        {
            using (var gp = RenderHelper.CreateRoundPath(Rect, (int)r))
            {
                g.FillPath(brush, gp);
                using (var p = new Pen(color, 1))
                {
                    g.DrawPath(p, gp);
                }
            }
        }

    }

    public void DrawText(Graphics g, Font font, RectangleF r, string text, Color color)
    {
        SolidBrush brush = new SolidBrush(color);
        StringFormat format = new StringFormat(StringFormatFlags.NoClip);
        format.Alignment = StringAlignment.Center;
        format.LineAlignment = StringAlignment.Center;
        g.DrawString(text, font, brush, r, format);
    }

    public void SetRect(float x, float y, float w, float h)
    {
        this.x = x;
        this.y = y;
        this.width = w;
        this.height = h;
    }

}

[Serializable]
public class ButtonItemCollection : List
{

    public void AddItems(string[] buttons)
    {
        for (int i = 0; i < buttons.Length; i++)
            AddItem(buttons[i]);
    }

    public ButtonItem AddItem(string c)
    {
        ButtonItem item = new ButtonItem();
        item.Caption = c;
        Add(item);
        return item;
    }

    public void InitSelected()
    {
        for (int i = 0; i < Count; i++)
        {
            this[i].Selected = false;
        }
    }

    public void InitMouseMove()
    {
        for (int i = 0; i < Count; i++)
        {
            this[i].IsMouseMove = false;
        }
    }

    public ButtonItem IndexOf(Point p)
    {
        for (int i = 0; i < Count; i++)
        {
            if (this[i].Rect.Contains(p))
            {
                return this[i];
            }
        }
        return null;
    }

    public ButtonItem IndexOf(int Value)
    {
        for (int i = 0; i < Count; i++)
        {
            if (this[i].Value == Value)
            {
                return this[i];
            }
        }
        return null;
    }

}

[DefaultProperty("Object")]
public class ButtonsControl : UserControl
{

    private ButtonViewOption viewOption = ButtonViewOption.Horizontal;
    private ButtonItemCollection btns = new ButtonItemCollection();
    public event EventHandler ButtonClick = null;

    //[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    //[Editor(typeof(PropertyEditor), typeof(UITypeEditor))]
    //[Localizable(true)]
    //[Category("Appearance")]
    //[Description("自定义数据列表")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public ButtonItemCollection Items
    {
        get
        {
            return btns;
        }
    }

    public ButtonViewOption ViewOption { get => viewOption; set => viewOption = value; }

    public ButtonsControl()
    {
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
    }

    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        Refresh();
    }

    protected virtual void OnVerticalDraw(Graphics g)
    {

        float btnheigth = (this.Height - 1) / Math.Max(1, btns.Count);

        SolidBrush blueBrush = new SolidBrush(Color.FromName("ActiveCaption"));
        g.FillRectangle(blueBrush, new Rectangle(0, 0, this.Width, this.Height));
        g.DrawRectangle(new Pen(Color.White), new Rectangle(0, 0, this.Width - 1, this.Height - 1));

        //显示检测结果
        int offset = 0;
        for (int i = 0; i < btns.Count; i++)
        {
            if (!btns[i].Visible) continue;
            btns[i].SetRect(1, (offset * btnheigth), this.Width-2, btnheigth);
            btns[i].Display(g);
            offset++;
        }

    }

    protected virtual void OnHorizontalDraw(Graphics g)
    {

        float btnwidth = (this.Width - 1) / Math.Max(1, btns.Count);

        SolidBrush blueBrush = new SolidBrush(Color.FromName("ActiveCaption"));
        g.FillRectangle(blueBrush, new Rectangle(0, 0, this.Width, this.Height));
        g.DrawRectangle(new Pen(Color.White), new Rectangle(0, 0, this.Width - 1, this.Height - 1));

        //显示检测结果
        int offset = 0;
        for (int i = 0; i < btns.Count; i++)
        {
            if (!btns[i].Visible) continue;
            btns[i].SetRect((offset * btnwidth) + 1, 1, btnwidth, this.Height-2);
            btns[i].Display(g);
            offset++;
        }

    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        using (Bitmap Gmap = new Bitmap(this.Width, this.Height))
        {
            Graphics g = Graphics.FromImage(Gmap);
            switch(ViewOption)
            {
                case ButtonViewOption.Horizontal:
                    {
                        OnHorizontalDraw(g);
                        break;
                    }
                case ButtonViewOption.Vertical:
                    {
                        OnVerticalDraw(g);
                        break;
                    }
            }
            e.Graphics.DrawImage(Gmap, new Rectangle(0, 0, this.Width, this.Height));
            g.Dispose();
        }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        btns.InitMouseMove();
        ButtonItem btn = btns.IndexOf(e.Location);
        if (btn != null)
        {
            btn.IsMouseMove = true;
        }
        this.Invalidate();
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        btns.InitSelected();
        ButtonItem btn = btns.IndexOf(e.Location);
        if (btn != null)
        {
            btn.Selected = true;
        }
        this.Invalidate();
    }

    protected override void OnMouseClick(MouseEventArgs e)
    {
        base.OnMouseClick(e);
        ButtonItem btn = btns.IndexOf(e.Location);
        if (btn != null)
        {
            if (ButtonClick != null) ButtonClick(btn, e);
        }
        this.Invalidate();
    }

}

///  
/// 自定义属性编辑器 
///  
public class PropertyEditor : UITypeEditor
{

    public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
    {
        //指定为模式窗体属性编辑器类型 
        return UITypeEditorEditStyle.Modal;
    }

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        ButtonsControl c = (ButtonsControl)context.Instance;
        frmMyObjectEditor frm = new frmMyObjectEditor(c.Items);
        frm.ShowDialog();
        MessageBox.Show(value.ToString());
        context.PropertyDescriptor.SetValue(context.Instance, value);
        return c;
    }
}

}

注:控件WTrackBar扩展

下载地址:https://download.csdn.net/download/qq_42977942/10901640

你可能感兴趣的:(源码,C#,trackbar,自定义,控件,slider)