2017-09-04 61 views
1

我正在做一個跟蹤條類似的用戶控制。C#畫圖一個小組,圍繞它的位置值

用戶可以點擊面板上並拖動它改變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; 
     } 
    } 

回答

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; 
     } 
    } 
} 
+0

您好,感謝答案。看起來我們正在做同樣的事情。我開始懷疑是否可能與'Panel'有關,因爲你(和許多其他人)似乎更喜歡繪製矩形。 你怎麼有兩個不同的功能來計算'GetRectanglePosition()'和'UpdateCurrentValueFromPosition()'時,他們似乎做同樣的事情?另外,我不熟悉'base.Method(e)',它是什麼? – Tawm

+0

這兩種方法是互補的。 'GetRectanglePosition()'獲取當前值並計算矩形的像素中的x位置。使用'UpdateCurrentValueFromPosition()'我將獲取當前鼠標位置(當用戶拖動矩形時)並計算範圍中的當前值。 – Oliver

+0

'base.Method(e)'是必需的,因爲我覆蓋了類中現有的方法。但我不想取代這些方法。相反,我只想做一些額外的東西。因此,我必須調用基本方法來讓默認行爲運行,然後再做我的其他事情。如果你想深入挖掘,你應該搜索'虛擬覆蓋C#'。這是面向對象編程中的常用技術。 – Oliver