背景が大きなビットマップである (OnPaint から呼び出される) 自分自身を描画する多くのオブジェクトの完全にカスタム描画されたグラフィックスを持つユーザー コントロールがあります。ズームとパン機能が組み込まれており、キャンバスに描画されるオブジェクトのすべての座標はビットマップ座標です。
したがって、ユーザー コントロールの幅が 1000 ピクセルで、ビットマップの幅が 1500 ピクセルで、200% ズームでズームしている場合、いつでもビットマップの幅の 1/3 しか見えません。また、ビットマップのポイント 100,100 から始まる長方形を持つオブジェクトは、画面の左端までスクロールすると、ポイント 200,200 に表示されます。
基本的に私がする必要があるのは、再描画が必要なものだけを再描画する効率的な方法を作成することです。たとえば、オブジェクトを移動する場合、そのオブジェクトの古いクリップ四角形を領域に追加し、そのオブジェクトの新しいクリップ四角形を同じ領域に結合してから、Invalidate(region) を呼び出してこれら 2 つの領域を再描画できます。
ただし、この方法では、オブジェクトを 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();
}