2017-09-04 3 views
1

私はTrackBarのようなユーザーコントロールを作っています。C#パネルをペイントしてその位置の値を囲みます

ユーザーはパネルをクリックしてドラッグしてint SelectedMinの値を変更できます。

SelectedMinパネルをマウスで囲むには、マウスでドラッグする代わりにドラッグします。換言すれば、パネルの中心がSelectedMinの代わりにSelectedMinの値で表示されるようにしたいと思います。

私はこれが私のToolboxCustomTrackBar_Paint()方法でラインで作業しなければならないと考えている。

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

プログラムが... - PanelWidth/2が働いていることを示す、パネルの半分だけがもともと表示して、正常に起動しますが、その後、Iパネルをクリックしてドラッグすると、マウスカーソルがあるパネルの中央が中央になります。


トップイメージは現在発生しているものです。下のイメージは私が達成しようとしているものです。

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()」が同じことをしているように見える2つの異なる関数はどうでしょうか?また、私は 'base.Method(e)'に慣れていません、それは何ですか? – Tawm

+0

2つの方法は相補的です。 'GetRectanglePosition()'は現在の値をとり、長方形のピクセル単位のx位置を計算します。 'UpdateCurrentValueFromPosition()'では、現在のマウスの位置(ユーザが矩形をドラッグしたとき)をとり、範囲内の現在の値を計算します。 – Oliver

+0

'base.Method(e)'が必要です。なぜなら、クラス内の既存のメソッドを上書きするからです。しかし、私はこれらの方法を置き換えることを好まない。代わりに私はいくつかの追加のものだけをしたいと思います。したがって、私は基本メソッドを呼び出して、デフォルトの動作を実行させ、その後に私の追加のことを行わなければなりません。深く掘り下げたいのであれば、 'virtual override c#'を検索するべきです。これはオブジェクト指向プログラミングの一般的なテクニックです。 – Oliver

関連する問題