11

コントロールをビットマップにオフスクリーンでレンダリングして、すばやくアクセスできるようにしたいと考えています。

残念ながらControl.DrawToBitmap、それが呼び出されるすべての子コントロールを含むコントロール全体を描画するようです。内部的には、自己提供の DC を含む WM_PRINT メッセージをビットマップに発行します。この一時的なビットマップは、ユーザー提供のビットマップにブリットされます。私には受け入れられません。必要に応じてこのビットマップを更新して、ビットマップが必要なときのパフォーマンスの低下を最小限に抑えたいと思います。

理想的なシナリオでは、フォームが画面に表示されているかのように動作するようにしたいと思います (ただし、表示することはできません)。これは、たとえば、一部の Control のTextプロパティが変更された場合、フォームが部分的に無効になることを意味します。関連するメッセージ/イベントをキャッチすると、フォームを描画するために独自の DC を指定するか、フォーム DC を自分自身に単純に BitBlt することができます。

私が見たいくつかの方向:

  • PaintEventArgsパラメーターはOnPaintメンバーsavedGraphicsStateを保持しているようです。おそらく、無効にする必要がないものを把握するために使用できます
  • フォームは表示されますが、画面領域の外にあります。ただし、コントロールは描画されません。
  • ウィンドウで RedrawWindow() を手動で呼び出す、同じ話
4

3 に答える 3

1

次の 2 つの問題があると思います。

  1. コントロールの無効な領域を見つける (Windows の助けなしで)
  2. 無効化された部分のみをレンダリングします。

最初の問題については、あなたは主にあなた自身であると思います。どのコントロールが変更されたかを追跡し、更新が必要な簿記を保持する必要があります。

2 番目の問題については、自分で WM_PRINT メッセージを送信して、小さなビットマップのみを参照する DC を提供することができます。元の DC API では、HDC の有効な描画領域をオフセットしてクリップすることができました。運が良ければ、Windows は HDC からレンダリング領域を推測します。そうでない場合は、変更する必要のあるピクセルがないため、ビットマップから完全に外れるレンダリング コマンドのほとんどは非常に安価です。

これは、1x1 ビットマップに出力して高速かどうかをテストすることで確認できます。また、WM_PAINT で送信されたクリップ領域がビットマップ サイズに縮小されているかどうかを確認することもできます。

于 2012-01-21T19:59:31.983 に答える
0

いくつかの onPaint イベントを示したサンプル プロジェクトを作成しました。その方法で解決できない場合は、例を更新してください。

よろしく! オンペイントの例

ここからダウンロード: http://www.goldengel.ch/temp/OnPaintExample.zip

Private Sub Button1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles Button1.Paint
    Dim bm As New Bitmap(Me.Button1.Width, Me.Button1.Height, PixelFormat.Format32bppRgb)

    Button1.DrawToBitmap(bm, New Rectangle(0, 15, bm.Width -5, bm.Height+2))
    Using gr As Graphics = Graphics.FromImage(bm)
        gr.DrawString(DateTime.Now.ToLongTimeString, Me.Font, Brushes.Lime, 0, 0)
    End Using
    Me.PictureBox1.BackgroundImageLayout = ImageLayout.Tile
    Me.PictureBox1.BackgroundImage = bm

End Sub
    Public Class myTextBox
        Inherits System.Windows.Forms.TextBox


        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            MyBase.OnPaint(e)
            e.Graphics.Clear(Color.Yellow)
            e.Graphics.DrawString(DateTime.Now.ToLongTimeString, Me.Font, Brushes.Gray, 0, 0)
        End Sub

        Public Sub New()
            SetStyle(ControlStyles.UserPaint, True)
        End Sub
    End Class
于 2011-12-21T13:11:46.430 に答える
0

コントロールが複製されている場合は、フォーム上になく、子コントロールを持たないコントロールを取得できると思います。

Control ctrl = ControlFactory.CloneCtrl(this.button3);
Bitmap bmp = new Bitmap(ctrl.Width, ctrl.Height);
ctrl.DrawToBitmap(bmp, new Rectangle(0, 0, ctrl.Width, ctrl.Height));
bmp.Save(@"C:\Users\Oli\Desktop\test.bmp");

The Code Projectにある lxwde によって書かれたControlFactoryを使用しました。

ControlFactory は完璧ではありませんが、十分に単純であり、簡単に改善できます。

于 2011-12-17T22:33:42.263 に答える