2017-08-30 60 views
0

我有一个用户控制其充当跟踪条带SelectedMinValueMinMax的界限内SelectedMax用户控件。创建一个使用另一个用户控制

我现在想创建另一个用户控件作为上述用户控件的一种外壳,以便包含悬停标签以显示每个选定值的当前值。

我想在单独的用户控件中执行此操作,因为将所有内容都向下移动以为TrackBar用户控件中的值标签腾出空间似乎很痛苦。

这是我目前的CustomTrackBar.cs用户控件。对不起,它很凌乱:

public partial class CustomTrackBar : UserControl 
{ 

    #region variables 
    private int min = 0; 
    private int max = 1000; 
    private int selectedMin = 0; 
    private int selectedMax; 
    private int value; 

    private int sliderWidth = 2; 
    #endregion 

    #region accessors 

    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 
     { 
      selectedMin = value; 
      if (AnythingChanged != null) 
      { 
       //SelectionChanged(this, null); 
       AnythingChanged(this, null); 
      } 
      MinChanged = true; 
      Invalidate(); 
     } 
    } 

    public int SelectedMax 
    { 
     get { return selectedMax; } 
     set 
     { 
      selectedMax = value; 
      if (AnythingChanged != null) 
      { 
       //SelectionChanged(this, null); 
       AnythingChanged(this, null); 
      } 
      MaxChanged = true; 
      Invalidate(); 
      MaxChanged = false; 
     } 
    } 

    public int Value 
    { 
     get { return value; } 
     set 
     { 
      this.value = value; 
      if (AnythingChanged != null) 
      { 
       //ValueChanged(this, null); 
       AnythingChanged(this, null); 
      } 
      ValueChanged = true; 
      Invalidate(); 
     } 
    } 

    public int SliderWidth 
    { 
     get { return sliderWidth; } 
     set 
     { 
      this.sliderWidth = value; 
      Invalidate(); 
     } 
    } 

    public Boolean MinChanged 
    { 
     get; private set; 
    } 
    public Boolean ValueChanged 
    { 
     get; private set; 
    } 
    public Boolean MaxChanged 
    { 
     get; private set; 
    } 

    #endregion 

    //Fired when SelectedMin or SelectedMax changes. 
    //public event EventHandler SelectionChanged; 

    //Fired when Value changes. 
    //public event EventHandler ValueChanged; 

    //Fired if anything changes 
    public event EventHandler AnythingChanged; 


    public CustomTrackBar() 
    { 
     //Set default values 
     Value = (Max - Min)/2; 
     SelectedMax = Max; 

     SliderWidth = SliderWidth/(Max - Min); //this line is horrible 

     InitializeComponent(); 



     //Avoid flickering 
     SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
     SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 

     //Events 
     Paint += new PaintEventHandler(CustomTrackBar_Paint); 
     MouseDown += new MouseEventHandler(CustomTrackBar_MouseDown); 
     MouseMove += new MouseEventHandler(CustomTrackBar_MouseMove); 
    } 

    //Create a rectangle 
    void CustomTrackBar_Paint(object sender, PaintEventArgs e) 
    { 
     //paint background in white 
     e.Graphics.FillRectangle(Brushes.White, ClientRectangle); 

     //Create a rectangle object 
     Rectangle selectionRect = new Rectangle(
      0, 
      0, 
      Width, 
      Height); 

     /* 
     Rectangle selectionRect = new Rectangle(
     (SelectedMin - Min) * Width/(Max - Min), 
     15, 
     (SelectedMax - selectedMin) * Width/(Max - Min), 
     Height - 30); 
     */ 

     //paint the rectangle object 
     e.Graphics.FillRectangle(Brushes.GreenYellow, selectionRect); 

     //Again how does this work? 
     Rectangle firstFrameRect = new Rectangle(
      (SelectedMin - SliderWidth/2) * Width/(Max - Min), 
      0, 
      SliderWidth * Width/(Max - Min), 
      Height 
      ); 
     e.Graphics.FillRectangle(Brushes.DarkBlue, firstFrameRect); 


     Rectangle lastFrameRect = new Rectangle(
      (SelectedMax - SliderWidth/2) * Width/(Max - Min), 
      0, 
      SliderWidth * Width/(Max - Min), 
      Height 
      ); 

     /* 
      Rectangle lastFrameRect = new Rectangle(
      SelectedMax * Width/(Max - Min), 
      0, 
      5 * Width/(Max - Min), 
      Height 
      ); 
     */ 

     e.Graphics.FillRectangle(Brushes.OrangeRed, lastFrameRect); 


     //draw a black frame around our control 
     e.Graphics.DrawRectangle(Pens.Black, 0, 0, Width - 1, Height - 1); 

     //draw a simple vertical line at the Value position 
     e.Graphics.DrawLine(Pens.Black, 
      (Value - Min) * Width/(Max - Min) - 5, 
      0, 
      (Value - Min) * Width/(Max - Min) - 5, 
      Height); 
    } 

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

    void CustomTrackBar_MouseMove(object sender, MouseEventArgs e) 
    { 
     //if the left button is pushed, move the selected thumb 
     if (e.Button != MouseButtons.Left) 
      return; 
     int pointedValue = Min + e.X * (Max - Min)/Width; 
     if (movingMode == MovingMode.MovingValue) 
     { 
      if (pointedValue <= Max && pointedValue >= Min) 
       Value = pointedValue; 
     } 
     else if (movingMode == MovingMode.MovingMin) 
     { 
      if (pointedValue < SelectedMax && pointedValue >= Min) 
       SelectedMin = pointedValue; 
     } 
     else if (movingMode == MovingMode.MovingMax) 
     { 
      if (pointedValue > SelectedMin && pointedValue <= Max) 
       SelectedMax = pointedValue; 
     } 
    } 


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

    public String AllValues() 
    { 
     return String.Format("{0}\t{1}\t{2}", SelectedMin, Value, SelectedMax); 
    } 

} 

这是CustomTrackBar现在的样子。垂直蓝色,黑色和红色的线是能够被点击并拖动:

这里是什么,我打算把它看起来像一个素描:

我不真的不知道如何开始新的用户控制。我试图在新的用户控件中创建一个CustomTrackBar对象,但这似乎没有画任何东西。

此外,是否创建另一个用户控件添加件到TrackBar是“正确的”?我应该坚持下来,并在第一次用户控制中做所有事情吗?

谢谢。

回答

1

当你建立的新控件没有绘图时,你应该做的第一件事是验证它具有正确的非零尺寸,并且你没有覆盖绘图代码(你在CustomTrackBar_Paint中做过)。除非你对坐标空间有很强的把握,并且你的绘图代码实际上在做什么,否则你应该更喜欢构图来定制绘图。

我的意思是组成是将控件拆分为具有多个内部控件的容器,所有这些控件都已存在于框架中。例如,您可以制作UserControl,背景图和PanelsLabels。正确定位和调整它们的大小,更新滑块值/ min/max/etc的更改情况。如果你这样做,你简化你的代码,而不必去触摸绘图代码。

事情是这样的:

public partial class CustomTrackBar : Panel 
{ 
    private Panel backdrop; 
    private Panel minBar; 
    private Panel maxBar; 
    private Panel currentBar; 
    private Label minDisplay; 
    private Label maxDisplay; 
    private Label currentDisplay; 

    public CustomTrackBar() 
    { 
     InitializeComponent(); // This should almost always be first. 
     backdrop = new Panel() { 
      BackColor = Color.LightGreen, 
      // set position, size, etc. 
     }; 
     // add event handlers to backdrop... 
     Controls.Add(backdrop); 
     // repeat for minBar, maxBar, etc. 

     SizeChanged += (sender, args) => { 
      Update(); 
     }; 

     // ... remaining initialization logic. 
    } 

    private void Update() 
    { 
     // adjust the position and size of each inner control... 
    } 
} 

只有当你做到了这一点,并测量性能的影响,你应该移动到自定义绘制。这将允许您用工作代码进行渐进式更改,而不是在黑暗中进行刺探。

+0

这绝对是创建自定义轨迹条的更好方法。谢谢。 – Tawm

+0

我很高兴我能帮上忙。 –

+0

我很难在其他面板中放置面板,并确保它们都可见。我在一个新的用户控件上放置了一个'backdropPanel',并在''''backgroundPanel''中放置了3个额外的'panel',它们看起来在下面并且不可见。不知道有什么问题。 – Tawm

相关问题