2013-04-28 2 views
0

Я разрабатываю пользовательский контроль времени для использования видео. вот фото моей работы: enter image description hereобновление только части usercontrol

здесь у меня проблема. когда currentTime изменяется, я должен обновить интерфейс. но когда я использую 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

спасибо брату. я попробую и вернусь –

+0

DoubleBuffered = true; работал на меня. благодаря –

Смежные вопросы