0

私はWinFormアプリケーション'バウンス ボール'bitmapを持っており、このフォームにボールをペイントし、ビットマップを提示する必要があります。

新しいボールを追加する があり、plusButton新しいボールをそれぞれリストに保存しています。

現在、Form_Paintメソッドは各ボールに自分自身を描画するように指示しています。多くのボールがあり、すべてのアプリケーションが非常に遅くなるまでは正常に機能します..

ここに私のコードがあります:

フォーム コードのペイント メソッド:

 private void Form1_Paint(object sender, PaintEventArgs e)
 {
     ballsArray.drawImage(bmp,e, ClientRectangle);
 }

注: ballsArray type からのものですAllBalls。これは、ボール メソッドをラップするクラスです。彼の c'tor 内で、各ボールを保持するリストを作成しています。はbmp、フォームのロード時に作成されます-onForm_Load()メソッド。

ballsArrayコードの drawImage :

 public void drawImage(Bitmap bmp,PaintEventArgs e, Rectangle r)
 {
     foreach (Ball b in allBalls)
     {
         b.drawImage(bmp,e, r);
     }
 }

ボールのdrawImageコード:

  public void drawImage(Bitmap bmp, PaintEventArgs e, Rectangle r)
  {
      using (Graphics g = Graphics.FromImage(bmp))
      {
          e.Graphics.FillEllipse(brush, ballLocation);
          g.DrawImage(bmp, 0, 0);
      }
  }

注: ballLocationは、動きの各ステップでのボールの位置を表す四角形です.

それで、私は何を間違っていますか?アプリケーションが遅くなる原因は何ですか?

ビットマップにすべてを描画してフォームに表示するという制約があります。また、フォームの読み込み時に作成したビットマップも渡します。これは、それぞれを描画する必要があるためです。

4

3 に答える 3

3

これを高速化するためのいくつかの基本的なテクニック:

  • 自分でダブルバッファリングしないでください。特に、2回ダブルバッファリングしないでください。フォームのDoubleBufferプロパティをtrueに設定することで得られるダブルバッファリングは、自分で行うほとんどのダブルバッファリングよりも優れています。バッファは、ビデオアダプタの設定で効率的に機能するように高度に最適化されています。したがって、変数を完全に削除bmpして、Paintイベントハンドラー引数から取得したe.Graphicsに描画します。

  • r渡された引数を使用していません。おそらく、目に見えないボールのクリッピングをサポートすることを目的としています。渡したいのはe.ClipRectangleで、この長方形の完全に外側にあるボールのペイントをスキップできます。これは最適化ですが、Aeroテーマを使用するときに一般的に役立つものではなく、再描画率に一貫性がないため、それをスキップすることをお勧めします。

  • ボールを描くときにGraphics.FillEllipseとGraphics.DrawImageの両方を使用する理由はあまり明確ではありません。画像は円と重なるはずなので、FillEllipseを削除するだけです。

  • ボールのグラフィックを格納するBitmapオブジェクトに多くの注意を払ってください。最初に確認したいのは、画像の正確なサイズで描画されるため、再スケーリングする必要がないことです。再スケーリングは非常にコストがかかります。DrawImage()呼び出しに再スケーリングはありませんが、ビットマップの解像度がビデオアダプターの解像度と同じでない場合は、再スケーリングを取得できます。次のステップはそれを解決します

  • ボールビットマップのピクセルフォーマットは非常に重要です。フォーマット変換なしでビットマップをビデオメモリに直接コピーできるものが必要です。最近のマシンでは、そのフォーマットはPixelFormat.Format32bppPArgbです。違いは非常に大きく、他のどの製品よりも10倍速く描画されます。追加した画像リソースからこの形式を取得することはできません。プログラムの起動時にそのビットマップを作成する必要があります。必要なコードについては、この回答を確認してください。

これらのガイドラインに従うと、少なくとも15倍速くレンダリングできるはずです。それでも十分な場合は、DirectXを使用する必要があります。ボールのグラフィックをビデオメモリに保存できるという無敵の利点があるため、メインメモリからビデオメモリに高価なbltを取得する必要はありません。

于 2013-01-13T13:22:20.160 に答える
0

DrawImageon Paint(またはさらに言えば on MouseMove) は非常に悪い設計です。

Graphics.DrawImageはコストのかかる操作であり、画面にとっては余分なコストがかかります。ユーザー エクスペリエンス (速度低下) を改善するには、MouseDown/MouseUp イベントをペイントする必要があります。

さらに、まずメソッドで MemoryBuffer に描画しdrawImage、最終的な画像を準備した後、UI で 1 回描画します。この手法は、ダブル バッファリングと呼ばれます。

ちらつくな!ダブルバッファ!-コードプロジェクト

さらに、画面への色/画像の高速転送用のBitBlitネイティブ API も参照できます。

ミニマルなC#の例はこちら

于 2013-01-13T12:25:43.970 に答える
0

フォームでダブルバッファリングを有効にします ( DoubleBuffered = true)。

于 2013-01-13T12:32:16.833 に答える