【解決方法】選択範囲と範囲 (親指 3 本) を備えた TrackBar – 可能ですか?

プログラミングQA


やあ、
私は Visual C# を使用するのが初めてです。 スライダー (トラックバー) に 3 つのサム (最小値を選択するもの、最大値を選択するもの、そして実際の選択値を選択するもの) が必要であるという問題に遭遇しました。

私は過去数時間をグーグルで解決策を見つけるのに費やしました。 いくつかのカスタム トラックバー コントロール (スライダー 1 つ付き) と範囲コントロール (スライダー 2 つ付き) をいくつか見つけましたが、私が求めているものは何もありませんでした。

誰かがそのようなコントロールを作成する方法を教えてくれますか? この段階でどんな情報でも構いません!
ありがとう、
リチャード

解決策 4

[Description("Very basic slider control with selection range.")]
 public partial class SelectionRangeSlider : UserControl
 {
   /// <summary>
   /// Minimum value of the slider.
   /// </summary>
   [Description("Minimum value of the slider.")]
   public Single Min
   {
     get { return min; }
     set { min = value; Invalidate(); }
   }
   Single min = 0;
   /// <summary>
   /// Maximum value of the slider.
   /// </summary>
   [Description("Maximum value of the slider.")]
   public Single Max
   {
     get { return max; }
     set { max = value; Invalidate(); }
   }
   Single max = 100;
   /// <summary>
   /// Minimum value of the selection range.
   /// </summary>
   [Description("Minimum value of the selection range.")]
   public Single SelectedMin
   {
     get { return selectedMin; }
     set
     {
       selectedMin = value;
       if (SelectionChanged != null)
         SelectionChanged(this, null);
       Invalidate();
     }
   }
   Single selectedMin = 0;
   /// <summary>
   /// Maximum value of the selection range.
   /// </summary>
   [Description("Maximum value of the selection range.")]
   public Single SelectedMax
   {
     get { return selectedMax; }
     set
     {
       selectedMax = value;
       if (SelectionChanged != null)
         SelectionChanged(this, null);
       Invalidate();
     }
   }
   Single selectedMax = 100;
   /// <summary>
   /// Current value.
   /// </summary>
   [Description("Current value.")]
   public Single Value
   {
     get { return value; }
     set
     {
       this.value = value;
       if (ValueChanged != null)
         ValueChanged(this, null);
       Invalidate();
     }
   }
   Single value = 50;
   /// <summary>
   /// Fired when SelectedMin or SelectedMax changes.
   /// </summary>
   [Description("Fired when SelectedMin or SelectedMax changes.")]
   public event EventHandler SelectionChanged;
   /// <summary>
   /// Fired when Value changes.
   /// </summary>
   [Description("Fired when Value changes.")]
   public event EventHandler ValueChanged;

   public SelectionRangeSlider()
   {
     InitializeComponent();
     //avoid flickering
     SetStyle(ControlStyles.AllPaintingInWmPaint, true);
     SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
     Paint += new PaintEventHandler(SelectionRangeSlider_Paint);
     MouseDown += new MouseEventHandler(SelectionRangeSlider_MouseDown);
     MouseMove += new MouseEventHandler(SelectionRangeSlider_MouseMove);
   }

   Font drawFont = new Font("Arial", 16);
   SolidBrush drawBrush = new SolidBrush(Color.White);

   void SelectionRangeSlider_Paint(object sender, PaintEventArgs e)
   {
     //paint background in white
     e.Graphics.FillRectangle(Brushes.Transparent, ClientRectangle);
     //paint selection range in blue
     Rectangle selectionRect = new Rectangle((int)((selectedMin - Min) * Width / (Max - Min)), 0, (int)((selectedMax - selectedMin) * Width / (Max - Min)), Height);
     e.Graphics.FillRectangle(Brushes.Blue, selectionRect);
     //draw a black frame around our control
     e.Graphics.DrawRectangle(Pens.Black, 0, 0, Width - 1, Height - 1);

     e.Graphics.DrawString(SelectedMin.ToString("0.00"), drawFont, drawBrush, ClientRectangle.Left, ClientRectangle.Top);
     e.Graphics.DrawString(SelectedMax.ToString("0.00"), drawFont, drawBrush, ClientRectangle.Right - 85, ClientRectangle.Top);
     e.Graphics.DrawString(value.ToString("0.00"), drawFont, drawBrush, (ClientRectangle.Left + ClientRectangle.Right) / 2, ClientRectangle.Top);

   }

   void SelectionRangeSlider_MouseDown(object sender, MouseEventArgs e)
   {
     //check where the user clicked so we can decide which thumb to move
     Single pointedValue = Min + e.X * (Max - Min) / Width;
     Single distValue = Math.Abs(pointedValue - Value);
     Single distMin = Math.Abs(pointedValue - SelectedMin);
     Single distMax = Math.Abs(pointedValue - SelectedMax);
     Single minDist = Math.Min(distValue, Math.Min(distMin, distMax));
     if (minDist == distValue)
       movingMode = MovingMode.MovingValue;
     else if (minDist == distMin)
       movingMode = MovingMode.MovingMin;
     else
       movingMode = MovingMode.MovingMax;
     //call this to refreh the position of the selected thumb
     SelectionRangeSlider_MouseMove(sender, e);
   }

   void SelectionRangeSlider_MouseMove(object sender, MouseEventArgs e)
   {
     //if the left button is pushed, move the selected thumb
     if (e.Button != MouseButtons.Left)
       return;
     Single pointedValue = Min + e.X * (Max - Min) / Width;

     if (movingMode == MovingMode.MovingMax && pointedValue > max)
     {
       pointedValue = max;
     }

     if (movingMode == MovingMode.MovingMax && pointedValue < selectedMin + 5)
     {
       pointedValue = selectedMin + 5;
     }

     if (movingMode == MovingMode.MovingMin && pointedValue < min)
     {
       pointedValue = min;
     }

     if (movingMode == MovingMode.MovingMin && pointedValue > selectedMax - 5)
     {
       pointedValue = selectedMax - 5;
     }

     if (movingMode == MovingMode.MovingValue)
       Value = (Single)Math.Round(pointedValue, 2);
     else if (movingMode == MovingMode.MovingMin)
       SelectedMin = (Single)Math.Round(pointedValue, 2);
     else if (movingMode == MovingMode.MovingMax)
       SelectedMax = (Single)Math.Round(pointedValue, 2);
   }

   /// <summary>
   /// To know which thumb is moving
   /// </summary>
   enum MovingMode { MovingValue, MovingMin, MovingMax }
   MovingMode movingMode;
 }

解決策 2

なぜ3つも必要なのかよくわかりません TrackBars スライダーが一方の端にある場合は Min に設定され、もう一方の端は Max に設定され、スライダーがどこにあっても値になります。

それでも、納得できる場合は、 UserControl、その上に 3 つのトラックバーを配置し、必要なプロパティを表示すると、ボブはあなたの叔父になります。

解決策 1

もちろんです (正確な仕様が必要です)。 これはそれほど難しいことではありません。

ただし、この種のコントロールとの使用は非常に混同されやすいため、それを行う場合は、通常のコントロールとは視覚的に異なる非常に優れたものにすることをお勧めします。 TrackBar しかし、他のコントロールとうまく融合しています。 したがって、主な関心事はデザインである必要があります。 ここでの実装ははるかに簡単です。

検索を停止し、利用可能なヘルプに集中するだけで済みます。 System.Windows.Forms.Control クラス。 オーバーロードをレンダリングするために、このクラスからコントロールを派生させます Control.OnPaint; いつも使う System.Drawing.Graphics の議論から OnPaint (決してグラフィックを作成しないでください。よくある間違いです!)。

何かを変更すると、レンダリングの変更がトリガーされます。 Control.Invalidate; 部分的な再描画のみが必要な場合は、コントロールの一部のみを無効にするパラメーターを含むオーバーロードされたメソッドの 1 つを使用します。

どうやらオーバーライド OnMouseDownOnMouseUp、(オプション) OnMouseEnterOnMouseLeaveOnMouseMoveOnMouseWheelOnKeyUpOnKeyDown。 また、フォーカスされた状態を別の方法でレンダリングするには、OnGotFocus、OnLostFocus をオーバーライドする必要がある場合もあります (コントロールの場合は、 Control.CanFocus == true)。

-SA

解決策 3

これには実際に必要なもの以上のものが含まれています。
Windows.Forms のカスタム C# グラデーション エディター[^]。

トラックバーに似たグラデーションストップをさらに追加できるため、このコントロールのロジックを再利用して必要なことを実現できるはずです。

よろしく
アスペン・ハーリン

コメント

タイトルとURLをコピーしました