2010-06-24 6 views
8

저는 C#/Net에서 간단한 벡터 드로잉 앱을 만들고 있습니다. 드로잉은 패널에서 수행되지만 OnPaint() 이벤트를 사용하지는 않습니다. 실제로 OnPaint()는 실제로 문서의 모든 내용을 실제로 그리는 다른 메서드를 호출하기도합니다.OnPaint()에서 그리지 않을 때 이중 버퍼링 : 왜 작동하지 않습니까?

이중 버퍼링을 추가하려고했지만 DoubleBuffered를 true로 설정하면 깜박임 문제가 더욱 심각해졌습니다. 왜 이런거야? 컨트롤을 두 번 버퍼링하려면 Panel.CreateGraphics()를 사용하는 대신 제공된 Graphics 객체를 사용하여 OnPaint() 이벤트에서 모든 드로잉을 수행해야합니다.

편집 : 이것은 내가 사용하고있는 기본 코드입니다.

private void doc_Paint(object sender, PaintEventArgs e) 
{ 
    g = doc.CreateGraphics(); 
    Render(ScaleFactor, Offset); 
}  

private void Render(float ScaleFactor, PointF offset) 
{ 
    foreach (Line X in Document.Lines) { DrawLine(X.PointA, X.PointB, X.Color, X.LineWidth); } 
} 
private void DrawLine(PointF A, PointF B, Color Color, float Width) 
{ 
    Pen p = new Pen(Color, Width); 
    PointF PA = new PointF(((A.X + Offset.X) * ScaleFactor), ((A.Y + Offset.Y) * ScaleFactor)); 
    PointF PB = new PointF(((B.X + Offset.X) * ScaleFactor), ((B.Y + Offset.Y) * ScaleFactor)); 
    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; 
    g.DrawLine(p, PA, PB); 
} 

일반적인 아이디어는 두 개의 변수, scaleFactor와 및 오프셋은 UI에서 줌 레벨과 팬 수준을 참조한다는 것입니다. g는 Graphics 객체입니다.

+0

패널의 페인트 이벤트 핸들러에 코드를 게시 할 수 있으며 함수를 호출 할 수 있습니까? – Brandi

+0

예, 글로벌 Graphics 객체를 갖는 대신 글로벌 비트 맵을 사용하십시오. 또한 PaintEventArgs e를 사용하면 "doc.CreateGraphics();"라고 말할 필요가 없습니다. 당신은 단지 "e.Graphics"라고 말할 수 있습니다. – Brandi

+0

만약 당신이 unmanaged 솔루션을보세요 신경 : http://stackoverflow.com/questions/2682025/disable-painting-of-the-vscrollbar-in-a-system-windows-forms-richtextbox (허용 대답) 그것은 종종 나를 위해 일했습니다. –

답변

28
g = doc.CreateGraphics(); 

. 이중 버퍼링은 버퍼에 그릴 경우에만 작동합니다. e.Graphics가 참조하는 것. 수정 :

g = e.Graphics; 

더블 버퍼링이 기본적으로 설정하지 않는 패널을 조심하십시오. 당신은 당신 자신의 것을 끌어 내야 할 것입니다. 이것을 새로운 클래스에 붙여 넣으십시오 :

using System; 
using System.Windows.Forms; 

class BufferedPanel : Panel { 
    public BufferedPanel() { 
     this.DoubleBuffered = true; 
     this.ResizeRedraw = true; 
    } 
} 

컴파일. 도구 상자의 맨 위에서 놓습니다.

+0

+1'BufferedPanel' 클래스에 대해. 필자는 똑같은 코드를 독자적으로 작성한 프로그래머 두 명 이상을 알고 있습니다. 이것은 실제로 프레임 워크의 일부가되어야합니다. – Niki

+0

+1, 또한 그것을 유지하기위한 최선의 아이디어가 아니라 렌더링으로 전달하는 것이 더 좋습니다. – user7116

+1

우리는 어디에서 맥주를 ​​보냅니 까 ...?여기에 두통 많이 구해 줬어. –

2

개인적으로 나는 DoubleBuffered 설정에 신경 쓰지 않습니다. 저는 비트 맵에 모든 것을 그려 넣은 다음 페인트 이벤트에서 비트 맵을 화면에 그립니다. 실수의

Bitmap BackBuffer; 

private void MainFormSplitContainerPanel1Paint(object sender, PaintEventArgs e) 
{ 
    e.Graphics.Clear(MainFormSplitContainer.Panel1.BackColor); 
    if (BackBuffer != null) 
     e.Graphics.DrawImage(BackBuffer, positionX, positionY, SizeX, SizeY); 
} 
+0

쉽게 변경할 수 있습니까? Panel.Graphics에 대한 참조가있는 곳이면 비트 맵에 대한 참조를 바꿀 수 있습니까? – ian93

+0

그렇게 생각하십시오. 기본적으로 내 애플 리케이션에서, 나는 페인트 기능과 관련되지 않은 것들을 비트 맵에 할당하거나 그리는 기능을 가지고있다. 페인트 기능이 호출 될 때까지 변경 사항을 볼 수 없으므로 이미지를 "새로 고침"하려면 MainFormSplitContainer.Panel1.Invalidate();를 호출하십시오. – Brandi

+2

이것은 좋은 생각이 아닙니다. Windows Forms에서 제공하는 버퍼는 훨씬 더 효율적입니다. –

관련 문제