2013-04-28 173 views
0

我开发了视频使用时间轴用户控制的一部分。这里是我的作品照片: enter image description here更新只是一个usercontrol

这里我有问题。当currentTime更改时,我必须更新UI。但是当我使用this.Invalidate();它刷新了整个控制。但我想更新指针(灰色背景中的白线)。因为它会导致控制在非常微小的时间变化中一遍又一遍地眨眼。 如何更新指针? 这里是我的OnPaint方法

private void OnPaint(object sender, System.Windows.Forms.PaintEventArgs e) 
    { 
     int width = this.Width; 
     int height = this.Height; 
     int Floor = height - FloorDistance; 
     Pen SecPen = new Pen(SecColor); 
     Pen MinPen = new Pen(MinColor); 
     SolidBrush TimeLineBrush = new SolidBrush(Color.Gray); 
     StringFormat stringFormat = new StringFormat(); 
     SolidBrush TimesolidBrush = new SolidBrush(TimeColor); 
     SolidBrush BackBrush = new SolidBrush(TimlineBackColor); 
     SolidBrush PointerBrush = new SolidBrush(PointerColor); 
     stringFormat.FormatFlags = StringFormatFlags.DirectionVertical; 
     switch (Zoom) 
     { 
      case ZoomLEvel.Quarter: 
       width = (int)Math.Ceiling((TotalDuration/900)) * ThickDistance; 
       break; 
      case ZoomLEvel.Minute: 
       width = (int)Math.Ceiling((TotalDuration/60)) * ThickDistance; 
       break; 
      case ZoomLEvel.Secound: 
       width = (int)Math.Ceiling(TotalDuration) * ThickDistance; 
       break; 
      case ZoomLEvel.MiliSecound: 
       width = (int)Math.Ceiling(TotalDuration * 10) * ThickDistance; 
       break; 
     } 
     width += 11; 
     this.Width = width; 

     e.Graphics.FillRectangle(TimeLineBrush, 0, Floor, width, 3); 
     e.Graphics.FillRectangle(BackBrush, 0, 0, width, height - FloorDistance); 

     int x = ThickDistance; 
     int step = 0; 
     while (x <= width - ThickDistance) 
     { 
      if (step % 5 == 0) 
      { 
       e.Graphics.DrawLine(MinPen, x, Floor, x, Floor - _MinHeight); 
       // print time 
       string time = ""; 
       double totalSecounds = 0; 
       PointF pointF = new PointF(x - 8, Floor + 5); 


       switch (Zoom) 
       { 
        case ZoomLEvel.Quarter: 
         totalSecounds = step * 900; 
         break; 
        case ZoomLEvel.Minute: 
         totalSecounds = step * 60; 
         break; 
        case ZoomLEvel.Secound: 
         totalSecounds = step; 
         break; 
        case ZoomLEvel.MiliSecound: 
         totalSecounds = step/10d; 
         break; 
       } 

       time = (new TimeSpan(0, 0, 0, (int)totalSecounds, (int)(step % 10) * 100)).ToString(@"hh\:mm\:ss\:fff"); 
       e.Graphics.DrawString(time, this.Font, TimesolidBrush, pointF, stringFormat); 

      } 
      else 
       e.Graphics.DrawLine(SecPen, x, Floor, x, Floor - _SecHeight); 
      x += ThickDistance; 
      step++; 
     } 
     int PointerTime = 0;//(int)Math.Floor(CurrentTime); 
     int pointerX = 0; 
     switch (Zoom) 
     { 
      case ZoomLEvel.Quarter: 

       PointerTime = (int)Math.Floor(CurrentTime/900); 
       pointerX = PointerTime * ThickDistance; 
       break; 
      case ZoomLEvel.Minute: 
       PointerTime = (int)Math.Floor(CurrentTime/60); 
       pointerX = PointerTime * ThickDistance; 
       break; 
      case ZoomLEvel.Secound: 
       PointerTime = (int)Math.Floor(CurrentTime); 
       pointerX = PointerTime * ThickDistance; 
       break; 
      case ZoomLEvel.MiliSecound: 
       PointerTime = (int)Math.Floor(CurrentTime * 10); 
       pointerX = PointerTime * ThickDistance; 
       break; 
     } 
     pointerX += 5; 
     e.Graphics.FillRectangle(PointerBrush, pointerX, 0, 2, height - FloorDistance); 
    } 

回答

2

Invalidate()方法的重载接受一个定义要刷新的区域Rectangle类型参数,称为剪辑矩形。你应该通过指针的边界矩形(白线,可能在所有边填充10个像素)。在您的OnPaint()方法中,您应该检查e.ClipRectangle属性以了解需要重绘的区域。现在,您的所有绘图逻辑(e.Graphics。DrawX()调用),你应该首先确认是否该元素与剪切区域相交(可以很容易地使用Rectangle.IntersectsWith()来完成)。如果是这样,你应该调用DrawX方法,否则你不应该这样做。

避免闪烁,你应该把你的控制的DoubleBuffered属性True。实现真正流畅的渲染很长一段路要走。

另外,我看到你在声明的OnPaint方法很多刷子和笔,而不是使用后处置他们。我认为很多这些都将被一次又一次的要求,所以你可能要在类级别声明它们,然后在你的控制Dispose()方法处理掉了。这将为您节省一些处理,因为这是一个与视频相关的应用程序。

希望有所帮助。

+0

感谢兄弟。我会试一试并回来 – 2013-04-28 09:12:12

+0

DoubleBuffered = true;为我工作。谢谢 – 2013-04-28 09:29:32