C#绘制一个面板以包围其位置值

时间:2017-09-04 06:14:55

标签: c# panel paint

我正在制作类似TrackBar的用户控件。

用户可以单击面板并拖动它以更改int SelectedMin

的值

我想绘制SelectedMin面板以围绕鼠标,因为我拖动而不是从鼠标开始。换句话说,我希望面板的中心显示在我的SelectedMin值,而不是SelectedMin面板的左侧。

我认为这应该使用ToolboxCustomTrackBar_Paint()方法中的一行:

minPanel.Location = new Point((SelectedMin * Width / (Max - Min)) - PanelWidth/2, LabelHeight);

程序正常启动,最初显示的面板只有一半,表示... - PanelWidth/2正在工作,但是当我点击面板拖动它时,它将面板左侧居中放置鼠标光标是。

顶部图像是目前发生的事情。最底层的图像是我想要实现的目标。

enter image description here

相关代码:

    private int min = 0;
    private int max = 1000;
    private int selectedMin = 200;
    private int labelWidth = 0;
    private int labelHeight = 200;
    private int panelWidth = 10;

    public int Min
    {
        get { return min; }
        set { min = value; Invalidate(); }
    }
    public int Max
    {
        get { return max; }
        set { max = value; Invalidate(); }
    }
    public int SelectedMin
    {
        get { return selectedMin; }
        set
        {
            if (value >= Min && value <= Max)
            {
                selectedMin = value;
                Invalidate();
            }
        }
    }
    public int LabelWidth
    {
        get { return labelWidth; }
        set { labelWidth = value; Invalidate(); }
    }
    public int LabelHeight
    {
        get { return labelHeight; }
        set { labelHeight = value; Invalidate(); }
    }
    public int PanelWidth
    {
        get { return panelWidth; }
        set { panelWidth = value; Invalidate(); }
    }

    public ToolboxCustomTrackBar()
    {
        InitializeComponent();
        SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

        selectionWidth = (Max - Min) / Width;

        minLabel.Text = "0";
        LabelWidth = minLabel.Width;
    }

    private void ToolboxCustomTrackBar_Paint(object sender, PaintEventArgs e)
    {
        foreach (var panel in panels)
        {
            panel.Height = Height - LabelHeight;

            if (panel != backdropPanel)
            {
                panel.Width = PanelWidth;
            }
        }

        minPanel.Location = new Point((SelectedMin * Width / (Max - Min)) - PanelWidth/2, LabelHeight);
    }

    private void minPanel_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            SelectedMin += Min + e.X * (Max - Min) / Width;
        }
    }

1 个答案:

答案 0 :(得分:0)

刚刚在我自己创建了一个跟踪栏,它似乎有效:

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

namespace TestProjectWinforms
{
    public partial class TrackBar : UserControl
    {
        private int _CurrentValue;
        private bool _IsDragging;
        private int _MaximumValue;
        private int _MinimumValue;

        public TrackBar()
        {
            InitializeComponent();
            TrackColor = Color.Red;
            TrackWidth = 10;
            MinimumValue = 0;
            MaximumValue = 10000;
            CurrentValue = 3000;
            HotTrackEnabled = true;
        }

        public event EventHandler CurrentValueChanged;

        public int CurrentValue
        {
            get => _CurrentValue;
            set
            {
                _CurrentValue = value;
                ValidateCurrentValue();
                Invalidate();
                RaiseEvent(CurrentValueChanged);
            }
        }

        public bool HotTrackEnabled { get; set; }

        public int MaximumValue
        {
            get => _MaximumValue;
            set
            {
                _MaximumValue = value;

                if (_MaximumValue < _MinimumValue)
                    _MaximumValue = _MinimumValue;

                ValidateCurrentValue();
                Invalidate();
            }
        }

        public int MinimumValue
        {
            get => _MinimumValue;
            set
            {
                _MinimumValue = value;

                if (_MinimumValue > _MaximumValue)
                    _MinimumValue = _MaximumValue;

                ValidateCurrentValue();
                Invalidate();
            }
        }

        public Color TrackColor { get; set; }

        public int TrackWidth { get; set; }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (HotTrackEnabled)
                _IsDragging = true;
        }

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

            if (_IsDragging)
            {
                UpdateCurrentValueFromPosition(e.X);
                Invalidate();
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            _IsDragging = false;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            using (var brush = new SolidBrush(TrackColor))
            {
                e.Graphics.FillRectangle(brush, CreateRectangle());
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            Invalidate();
        }

        private RectangleF CreateRectangle()
        {
            var position = GetRectanglePosition();
            var rectangle = new RectangleF(position, 0, TrackWidth, Height);
            return rectangle;
        }

        private float GetRectanglePosition()
        {
            var range = _MaximumValue - _MinimumValue;
            var value = _CurrentValue - _MinimumValue;
            var percentage = (float)value * 100 / range;
            var position = percentage * Width / 100;

            return position - (float)TrackWidth / 2;
        }

        private void RaiseEvent(EventHandler handler)
        {
            handler?.Invoke(this, EventArgs.Empty);
        }

        private void UpdateCurrentValueFromPosition(float x)
        {
            var percentage = x * 100 / Width;
            var range = _MaximumValue - _MinimumValue;
            var rawValue = percentage * range / 100;
            var value = rawValue + _MinimumValue;

            CurrentValue = (int)Math.Round(value);
        }

        private void ValidateCurrentValue()
        {
            if (_CurrentValue < _MinimumValue)
                _CurrentValue = _MinimumValue;

            if (_CurrentValue > _MaximumValue)
                _CurrentValue = _MaximumValue;
        }
    }
}