배경이 커다란 비트 맵인 자체 개체 (OnPaint에서 호출 됨)의 사용자 지정 그리기 그래픽이있는 사용자 정의 컨트롤이 있습니다. 확대/축소 및 이동 기능이 내장되어 있으며 캔버스에 그려진 개체의 모든 좌표는 비트 맵 좌표입니다.OnPaint, 무효화, 클리핑 및 영역에 대한 모범 사례
따라서 사용자 컨트롤이 1000 픽셀 너비라면 비트 맵의 너비는 1500 픽셀이고 200 % 확대/축소가 가능하며 주어진 시간은 비트 맵 너비의 1/3 정도입니다. 비트 맵에서 점 100,100에서 시작하는 직사각형을 가진 객체는 맨 왼쪽으로 스크롤 한 경우 화면의 점 200,200에 나타납니다.
기본적으로 내가 그릴 필요가있는 것은 다시 그려야하는 것만 다시 그리는 효율적인 방법을 만드는 것입니다. 예를 들어 객체를 이동하면 해당 객체의 이전 클립 사각형을 영역에 추가하고 해당 객체의 새 클립 사각형을 해당 영역에 결합한 다음 Invalidate (region)를 호출하여 해당 두 영역을 다시 그리도록 할 수 있습니다.
그러나 이렇게하면 무효화하기 위해 화면 좌표로 개체 비트 맵 좌표를 끊임없이 변환해야한다는 것을 의미합니다. 나는 항상 PaintEventArgs의 ClipRectangle이 다른 윈도우가 나의 것을 무효화 할 때 화면 좌표에 있다고 가정해야합니다.
Region.Transform 및 Region.Translate 기능을 사용하여 비트 맵에서 화면 좌표로 변환 할 필요가없는 방법이 있습니까? 화면 좌표에서 PaintEventArgs 수신을 방해하지 않는 방식으로? 여러 지역을 사용해야합니까 아니면 더 좋은 방법이 있을까요? 내가 지금 뭘하는지에 대한
샘플 코드 :
invalidateRegion.Union(BitmapToScreenRect(SelectedItem.ClipRectangle));
SelectedItem.UpdateEndPoint(endPoint);
invalidateRegion.Union(BitmapToScreenRect(SelectedItem.ClipRectangle));
this.Invalidate(invalidateRegion);
그리고 OnPaint를()에 ... 많은 사람들이 이후
protected override void OnPaint(PaintEventArgs e)
{
invalidateRegion.Union(e.ClipRectangle);
e.Graphics.SetClip(invalidateRegion, CombineMode.Union);
e.Graphics.Clear(SystemColors.AppWorkspace);
e.Graphics.TranslateTransform(AutoScrollPosition.X + CanvasBounds.X, AutoScrollPosition.Y + CanvasBounds.Y);
DrawCanvas(e.Graphics, _ratio);
e.Graphics.ResetTransform();
e.Graphics.ResetClip();
invalidateRegion.MakeEmpty();
}
수행 할 필요가없는 작업을 수행하고 있습니다. Windows는 이미 클리핑에서 매우 효율적이므로 도움을받을 필요가 없습니다. 퍼프 (perf) 문제가있는 경우 비트 맵의 픽셀 형식을 사용하십시오. 32bppPArgb는 다른 어떤 것보다 10 배 빠릅니다. –
페인트 클리핑이 어떻게 작동하는지 이해하지 못합니다. GDI +를 사용하여 이동, 크기 조정, 회전 등의 개체를 그립니다. MouseMove와 같은 이벤트에서 다시 그리기가 필요하며 실제로 업데이트해야하는 부분 만 다시 그려야합니다. 예를 들어 객체를 변경하면 자체적으로 다시 그려지지 않을 것이므로 Invalidate()를 호출해야합니다. 클립 할 클립 영역을 지정하지 않으면 전체 장면을 다시 그립니다. 예를 들어 MouseMove 이벤트에서 전체 장면을 다시 그리지 않으려 고합니다. –
와우! Hans Passant에게 Windows가 어떻게 작동하는지 이해하지 못한다고 말하는 것은 Jon Skeet에게 그가 C# 작동 방식을 이해하지 못한다고 말하는 것과 같습니다! :-) –