我有一个用户控件,其中包含许多自己绘制的对象的完全自定义绘制的图形(从 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();
}