我有一個用戶控件,具有完全自定義繪製圖形的許多繪製自己的對象(從OnPaint調用),背景是一個大的位圖。我內置了縮放和平移功能,並且畫布上繪製的對象的所有座標都位於位圖座標中。OnPaint,失效,剪切和區域的最佳實踐
因此,如果我的用戶控件寬度爲1000像素,位圖寬度爲1500像素,並且我以200%縮放縮放,那麼在任何給定時間,我只會查看位圖寬度的1/3。並且在位圖上的點100,100處有一個矩形的對象將顯示在屏幕上的點200,200處,只要您將其滾動到最左側。
基本上我需要做的是創建一個有效的方式重繪只需要重繪。例如,如果我移動一個對象,則可以將該對象的舊剪輯矩形添加到某個區域,然後將該對象的新剪切矩形與同一區域合併,然後調用Invalidate(region)重繪這兩個區域。
但是這樣做意味着我必須在將對象位圖座標提供給Invalidate之前不斷地將其轉換爲屏幕座標。我必須始終假設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比其他任何產品快十倍。 –
我不認爲你明白油漆裁剪是如何工作的。我使用GDI +繪製可以移動,調整大小,旋轉等的對象。我需要重繪像MouseMove這樣的事件,並且我需要確保只重繪實際需要更新的部分。例如,如果我更改一個對象,它不會自己重繪,我必須調用Invalidate()。如果我沒有指定要剪輯的剪輯區域,則會重新繪製整個場景。例如,您不想在MouseMove事件上重新繪製整個場景。 –
哇!告訴Hans Passant,他不明白窗口剪裁的工作方式,就像告訴Jon Skeet他不瞭解C#是如何工作的! :-) –