2013-04-28 2 views
0

저는 비디오 사용을위한 타임 라인 사용자 정의 컨트롤을 개발 중입니다. 여기 내 일의 사진입니다 : enter image description here은 사용자 정의 컨트롤의 일부만 업데이트합니다.

여기에 문제가 있습니다. 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 방법으로 많은 브러시와 펜을 선언하고 사용 후 폐기하지 않는 것을 확인했습니다. 저는이 중 많은 것들이 몇 번이고 반복 될 것이라고 생각합니다. 따라서 클래스 레벨에서 선언하고 싶을 때, 제어 방법에 따라 폐기하십시오. 이것은 비디오 관련 응용 프로그램이라는 점에서 약간의 처리를 덜어줍니다.

희망이 있습니다.

+0

감사합니다. 나는 그것을 시도하고 돌아올거야 –

+0

DoubleBuffered = 사실; 나를 위해 일했다. 감사 –