2009-10-15 5 views
0

그래픽을 렌더링하는 사용자 지정 컨트롤을 작성했습니다. 그래픽 자체는 렌더링하는 데 상당히 비싸지 만 렌더링 된 후에는 거의 변경되지 않습니다.C# OnPaint mousemove 높은 CPU 사용량

개인 무효 UserControl1_Paint (개체를 보낸 사람,있는 PaintEventArgs 전자)

: 내가 가진 문제는 그래픽을 통해 정말 빠르게 마우스를 이동하면 그 다음 높은 CPU 페널티를 초래 컨트롤의 오버라이드 (override) 페인트 메소드를 호출 유지 표면이다

마우스 포인터 아래의 그래픽/이미지가 실제로 변경되지 않기 때문에 이러한 상황을 피하거나 불필요한 다시 그리기를 최소화하는 데 사용할 수있는 기법은 무엇입니까?

+0

지금까지 답변 해 주셔서 감사합니다. 나는 내가 무언가가 변경되었다는 것을 알 때 control.Invalidate를 사용한다고 덧붙여 야했다. Paint 메서드는 마우스가 움직일 때 .NET (나!가 아님)에 의해 호출됩니다. –

+2

마우스가 컨트롤 위로 이동하면 OnPaint가 호출되지 않고 다른 것이 계속 발생합니다. –

+1

나는 단순한 프로젝트로 테스트를했고, OnMouseMove에서 Invalidate를 호출하지 않으면 마우스 이동에 의해 그림판이 호출되지 않는다. 코드를 호출 할 때 호출을 무효화하는 다른 조건이 코드에없는 것은 확실합니까? 일부 로깅 코드를 추가하여 무효화 및 마우스 이동 호출을 기록하고 의도 한대로 호출되었는지 확인하십시오. – rslite

답변

3

편집 : 편집을보고 나면 마우스가 컨트롤 위로 이동할 때 기본적으로 OnPaint가 호출되지 않는다는 것을 확인할 수 있습니다. 귀하의 코드에있는 뭔가가 확실히 다시 페인트를 일으키는 것입니다. 아직 보지 못했습니다. 일부 코드를 게시하면 문제를 찾는 데 도움이됩니다.

MouseMove에 대한 컨트롤이 무효화 되었습니까? 이는 잘못된 생각 일 수 있습니다. 실제로 작업해야하는 경우 (예 : 그래픽 편집기 또는 기타 작업을하는 경우), 실제로 얼마나 큰 영역을 다시 그리는 지에 대해 똑똑해야합니다. 그래서, 해결책; MouseMove에서 컨트롤을 페인트하지 마십시오.

그렇지 않으면 마우스가 컨트롤 위로 이동할 때 OnPaint가 실행되지 않을 것이라고 생각합니다. 이미지를 한 번 생성 한 다음 다시 생성해야 할 때까지 blt을 사용하여 Graphics 객체에 blt 할 수도 있습니다.

+0

. 당신은 정확해야합니다. 실제로 다른 컨트롤의 동작을 무시하고 있으므로 mousemove가 무효화하는 원인이되는 시트 아래에서 장난 꾸러기를하고있을 수도 있습니다. –

2

변경된 사항이있는 버퍼 이미지를 사용할 수 있으며 Paint 메서드는 이미지를 화면에 복사하기 만하면됩니다. 꽤 빠르다. 또한 클립 영역을 사용하여 업데이트가 필요한 부분 만 복사 할 수 있습니다. 이렇게하면 CPU 사용량이 줄어 듭니다.

필요할 경우 IsDirty 플래그를 사용하여 버퍼 이미지를 업데이트 할시기를 알 수 있습니다 (즉, 완전히 다시 그려야 함).

+0

이것은 현재 내가하는 일입니다. 그러나 마우스가 움직일 때 Paint를 호출하는 환경을 막을 수있는 방법이 있는지 궁금합니다. –

+0

커서가 컨트롤 위로 이동하면 OnPaint가 호출되지 않습니다. 덕분에 –

-1

이 코드를 사용하여 컨트롤의 다시 그리기를 억제하고 다시 시작할 수 있습니다.] 행운을 빈다.

using System; 
    using System.Windows.Forms; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Runtime.InteropServices; 

namespace pl.emag.audiopc.gui { 
    // ************************************************************************ 
//`enter code here` 
    // ************************************************************************ 
    public class PaintingHelper { 
     // ******************************************************************** 
// 
     // ******************************************************************** 
     public static void SuspendDrawing(Control parent) { 
      SendMessage(parent.Handle, WM_SETREDRAW, false, 0); 
     } 
     // ******************************************************************** 
// 
     // ******************************************************************** 
     public static void ResumeDrawing(Control parent) { 
      SendMessage(parent.Handle, WM_SETREDRAW, true, 0); 
      parent.Refresh(); 
     } 
     // ******************************************************************** 
// 
     // ******************************************************************** 
     [DllImport("user32.dll")] 
     private static extern int SendMessage(IntPtr hWnd, Int32 wMsg, 
      bool wParam, Int32 lParam); 
     // ******************************************************************** 
     // 
     // ******************************************************************** 
     private const int WM_SETREDRAW = 11; 
    } 
} 
2

Paint으로 직접 전화하지 마십시오.

대신 Invalidate (Control.Invalidate)으로 전화하십시오. 이렇게하면 다시 칠할 필요가 없으며 Windows에서 호출 자체를 처리합니다. 이렇게하면 Paint 번으로 신속하게 무효화 (재 칠판 요청) 할 수 있습니다.

1

Paint 메서드에서 높은 CPU로드를 유발할 수있는 요소 중 하나는 부적절한 (관리되지 않는) 리소스 릴리스입니다. 모든 펜, 브러쉬 등을 Dispose()해야합니다 (아마도 모든 System.Drawing 클래스 인스턴스에 관리되지 않는 리소스가 연결되어있을 수 있습니다). 기본적으로 개체 작업을 마치면 즉시 Dispose()를 수행해야합니다. 캐시하지 마십시오. - GDI + 리소스는 시스템 리소스이므로 최대한 빨리 시스템에 반환해야합니다. 그것들을 얻으면 (예를 들어 새로운 Brush 클래스 인스턴스를 생성하는 것) 꽤 빠르지 만, 지금은이 문장을 되돌릴 아무 것도 없습니다.