概要現在、キャンバス領域にクリッピングを適用する方法をどのように改善できますか?
私は、この場合TPaintBox
キャンバスには、キャンバスにグラフィックスの多くを描画する必要があります。 paintboxはTScrollBox
の子であり、paintboxのサイズは高さと幅が非常に大きくなる可能性があります(例:5000x5000)。
私は自分自身のオブジェクトを保持するTList
を持っています。各オブジェクトには独自のXプロパティとYプロパティと独自のグラフィックがあります。ペイントボックスのOnPaint
メソッドでは、リスト内の各オブジェクトを反復処理し、オブジェクトXとYの位置に格納されている座標でペイントボックスキャンバスに各オブジェクトのグラフィックを描画します。
これをすべて描画するとアプリケーションが遅くなり、非常に重くなるので、これを最適化する方法が必要でした。
明白なやり方は、CPUではなくGPUを何とか利用することですが、それははるかに複雑です.Firemonkeyは助けになるかもしれませんが、FMXではなくVCLタイプのプロジェクトで厳密に実行しています。
考えられる解決策?
私はCreateRectRgn
に遭遇し、正しく理解していれば、スクロールボックスの可視領域などのペイントボックスにペイントボックスをペイントできれば、パフォーマンスが大幅に向上するはずだと考えました。私が最初に仮定し、何よりも私がペイントボックスキャンバスにペイントかをどのように最適化するための、これはでも良い方法かどうかである
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
MyRgn: HRGN;
begin
// iterate and draw objects onto FBuffer (offscreen bitmap) first,
// note: FBuffer size is the same as the scrollboxes clientwidth
// and clientheight
//begin
// ...
//end;
// create and paint on a region (visible area of the scrollbox) on
// the paintbox rather than painting the whole paintbox.
MyRgn := CreateRectRgn(0, 0, ScrollBox1.ClientWidth, ScrollBox1.ClientHeight);
try
SelectClipRgn(PaintBox1.Canvas.Handle, MyRgn);
PaintBox1.Canvas.Draw(ScrollBox1.HorzScrollBar.Position,
ScrollBox1.VertScrollBar.Position, FBuffer);
SelectClipRgn(PaintBox1.Canvas.Handle, HRGN(nil));
finally
DeleteObject(MyRgn);
end;
質問
:だから、このことを念頭に置いて、私はの線に沿って何かを試してみました他にどのようなオプションがありますか?私が行うメモの唯一の他の事は、各オブジェクトのXとYをチェックすることです。スクロールボックスの可視領域の外にあれば、私はそれをペイントしません。
私はまだクリッピング領域を作成するという考えに慣れていますが、上記のコードサンプルは間違っています。私は、特にペイント方法の中で、地域を絶えず作成し、削除するという考えが嫌いです。
私のプロジェクトはかなり大きくなっていますが、実際にはこれをカスタムコントロールに入れていますが、何百ものオブジェクトを処理してペイントボックスキャンバスにペイントすると徐々に減速し、私がクリッピング領域を正しく実装していないか、あるいは私が常時作成している方法で、OnPaint
メソッドから領域を描画してから削除してください。
これを実現するためのより現実的な方法がありますか?おそらく、フォーム作成時にリージョンを作成し、フォームdestroy(またはカスタムコントロールのコンストラクタ/デストラクタから)で破棄することは可能でしょうか?しかし、フォームやコントロールのサイズを変更した場合、どのようにクリッピング領域のサイズを変更するのですか?
私は本当にいくつかのアドバイスを使用して、私がより良いやり方をすることができるかもしれないことを理解するのを助けるために直面しているこの問題にいくつかの明快さを得ることができます。
ありがとうございました。
GraphicControl(PaintBox)は、その親(ScrollBox)に対して取得されたDCで動作します。つまり、ペイントは既にスクロールボックスのクライアント領域にクリップされています。詳細は 'TWinControl.PaintControls'を参照してください。 –
@SertacAkyuzうわー私は決してそれを知らなかった。その場合、私は自分自身のクリッピング領域を追加しようとする前に、それがもっと遅くなったと確信しているので、絵を最適化する別の方法を見つける必要があります。これに関係なく、私は実際にペイントボックスの親が私のためにこれを行うかどうかに関係なく、クリッピング領域を正しく設定していたかどうかにかかわらず、この疑問と疑問が残ります。私の仕事はより良い方法でアプローチできると確信していますが、途中で間違いを覚えたり修正したりするのはいつでも歓迎します。 – Craig
@SertacAkyuzまた、私が実際にカスタムコントロールにすべてを入れたら、スクロールボックスにキャンバスをパブリッシュして直接ペイントして、子ペイントボックスを使うのではなく、また、スクロールボックスキャンバスのクリッピング領域が必要ですか? – Craig