Re: GDI+ Performance sehr schlecht (?)
- From: "Stefan Uhlemann" <stefan@xxxxxxxxxxxxxx>
- Date: Fri, 7 Mar 2008 13:36:17 +0100
Hallo Peter,
also warum das abstürzen sollte weiß ich jetzt nicht.
Habe das ganze Projekt mal gepackt, den Download gibt's hier:
http://www.addware.de/UserControlDrawTests.zip
Gut, Redim hin oder her. Das geht alles im Vergleich zum reinen Rechnen noch
echt flott.
Ich bin auch sicher das man hier und da noch einiges optimieren kann - das
war einfach nur ein Quick-And-Dirty Test.
Allerdings zeigt sich genau das Zeichnen der Rechtecke als "Engpass" dar.
Ich habe schon alles mögliche Probiert, das mit dem DoubleBuffer war auch
nur ein Test. Das Ergebnis ist aber auch das gleiche wenn ich direkt im
Paint-Eregnis auf e.graphics zeichne (bis auf das dann auftretende Flackern
welches ich durch den DoubleBuffer beseitigt habe).
Würde gerne in vb2005 mal ein API-Test machen, aber das kann ja nicht im
Sinne des Erfinders sein.
Ich will ja auch die schönen Vorteile von GDI+ nutzen können.
Gruss
Stefan
"Stefan Uhlemann" <stefan@xxxxxxxxxxxxxx> schrieb im Newsbeitrag
news:fqr964$96s$1@xxxxxxxxxxxxxxx
Hallo,
Ich habe in VB6 früher viele UserControls entwickelt welche alle über
API-Zeichenroutinen liefen.
Jetzt bin ich auf vb 2005 umgestiegen und würde manche Controls gerne
umschreiben oder neue entwerfen.
Allerdings stoße ich dabe mit gdi+ ständig auf Probleme mit der
Performance.
Routinen die in vb6 mittels API gezeichnet haben zeichnen in GDI+ zigmal
langsamer so das sie völlig uninteressant sind.
Ich habe mich schon durch sämtliche Seiten gegoogelt, verschiedene
Lösungen probiert aber es hilft nix - gdi+ scheint untragbar langsam zu
sein.
(z.B. Rechtecke ausfüllen)
Jetzt meine Frage: Ist die Performance da wirklich so schlecht oder liegt
es an mir?
Folgend ein UserControl-Beispiel was meiner Meinung nach eigentlich rasend
schnell sein sollte (jedenfall mittels API in vb6), man in vb2005 den
einzelnen Kästchen beim Aufbau quasi zuschauen kann... Ich versteh die
Welt nicht mehr...
Hier der VB-Code:
-----------------------------------------------------------------------------
buffereddraw.vb
-----------------------------------------------------------------------------
Imports System.Drawing.Drawing2D
Public Class BufferedDraw
Inherits System.Windows.Forms.UserControl
Public Sub New()
InitializeComponent()
Me.DoubleBuffered = True
Me.CreateGraphicBuffer()
End Sub
' Wird vom Windows Form-Designer benötigt.
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.SuspendLayout()
'
'BufferedDraw
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.Name = "BufferedDraw"
Me.ResumeLayout(False)
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing Then
If components IsNot Nothing Then
components.Dispose()
End If
If _buffGraphics IsNot Nothing Then
_buffGraphics.Dispose()
End If
If _buffContext IsNot Nothing Then
_buffContext.Dispose()
End If
End If
Catch ex As Exception
' Wenn wir das Projekt Debuggen, sollen uns Fehler im Dispose
' auf jeden Fall erreichen.
#If DEBUG Then
MsgBox(ex.ToString)
#End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
Private _buffContext As BufferedGraphicsContext
Protected ReadOnly Property BufferContext() As BufferedGraphicsContext
Get
Return _buffContext
End Get
End Property
Private _buffGraphics As BufferedGraphics
Protected ReadOnly Property BufferedGraphics() As BufferedGraphics
Get
Return _buffGraphics
End Get
End Property
<System.ComponentModel.Browsable(False)> _
Public ReadOnly Property Graphics() As Graphics
Get
If _buffGraphics IsNot Nothing Then
Return _buffGraphics.Graphics
End If
Return Nothing
End Get
End Property
Private _lastSize As Size
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
' Testen, ob wir auch in der Laufzeit sind
If Me.DesignMode Then
MyBase.OnResize(e)
Return
End If
' Testen, ob Form auf dem das
' Control ist gerade mimimiert ist
If Me.Size.Width <= 0 Or Me.Size.Height <= 0 Then
MyBase.OnResize(e)
Return
End If
' wir merken uns die Größe
If Not _lastSize.Equals(Me.Size) Then
_lastSize = Me.Size
' und erzeugen die Buffer-Objekte
Me.CreateGraphicBuffer()
End If
' und rufen die Basisklasse auf,
' damit der Resize-Event geworfen wird
MyBase.OnResize(e)
End Sub
Protected Overridable Sub CreateGraphicBuffer()
Try
' neuen BufferContext erzeugen
Dim newCtx As BufferedGraphicsContext
newCtx = New BufferedGraphicsContext
' Größe festlegen
newCtx.MaximumBuffer = New Size( _
Me.DisplayRectangle.Width + 1, _
Me.DisplayRectangle.Height + 1)
' neue BufferedGraphics erzeugen
Dim newBuff As BufferedGraphics
newBuff = newCtx.Allocate(Me.CreateGraphics, _
Me.DisplayRectangle)
' Die Hintergrundfarbe zuweisen
newBuff.Graphics.Clear(Me.BackColor)
' Todo: eine bestehende Hintergrundgrafik in
' Buffer blitten.
' Wenn schon ein Grafik-Puffer da ist ->
' in neuen Puffer rendern und freigeben
If _buffGraphics IsNot Nothing Then
' Die alte Transformations-Matrix übertragen
newBuff.Graphics.Transform = _
_buffGraphics.Graphics.Transform.Clone
_buffGraphics.Render(newBuff.Graphics)
_buffGraphics.Dispose()
End If
' alten BufferedGraphicsContext ggf. freigeben
If _buffContext IsNot Nothing Then
_buffContext.Dispose()
End If
' Context und Puffer an Member zuweisen
_buffContext = newCtx
_buffGraphics = newBuff
Catch ex As Exception
Debug.WriteLine(ex.TargetSite)
Throw
End Try
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
' Debug.WriteLine("OnPaint")
' den Buffer nur Rendern, wenn auch tatächlich einer
' vorhanden ist.
If Me.DesignMode OrElse Me.BufferedGraphics Is Nothing Then
Debug.WriteLine("DesignMode od. kein Buffer vorhanden")
Stop
MyBase.OnPaint(e)
Return
End If
Try
Me.BufferedGraphics.Render(e.Graphics)
Catch ex As Exception
Debug.WriteLine(ex.ToString)
Throw
Finally
' Zum Schluß sollten wir das Paint-Ereignis
' auslösen. Dies machen wir aber nicht mit
' MyBase.OnPaint(e), da dies sonst
' wieder über unseren gerenderten Inhalt
' zeichnen würde.
RaisePaintEvent(Nothing, e)
End Try
End Sub
Private m_ColWidth As Integer = 18
Private m_RowHeight As Integer = 18
Private Rectangles() As Rectangle
Private CurHoverIndex As Integer
Private Sub Draw(ByVal g As Graphics)
Dim RowIndex As Integer
Dim ColIndex As Integer
Dim Rect As Rectangle
Dim Counter As Integer
Dim CurX As Integer
Dim CurY As Integer
Graphics.SmoothingMode = Drawing2D.SmoothingMode.None
CurX = 0
CurY = 0
ReDim Rectangles((Int(Height / m_RowHeight) + 1) * (Int(Width /
m_ColWidth) + 1))
For RowIndex = 1 To (Int(Height / m_RowHeight) + 1)
CurX = 0
For ColIndex = 1 To (Int(Width / m_ColWidth) + 1)
Counter += 1
Rect = New Rectangle
Rect.X = CurX
Rect.Y = CurY
Rect.Width = m_ColWidth
Rect.Height = m_RowHeight
Rectangles(Counter) = Rect
If CurHoverIndex = Counter Then
g.FillRectangle(Brushes.Black, Rect)
Else
g.FillRectangle(Brushes.White, Rect)
g.DrawRectangle(SystemPens.ControlDark, Rect)
End If
CurX += m_ColWidth
Next ColIndex
CurY += m_RowHeight
Next RowIndex
End Sub
Private Sub BufferedDraw_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
Dim Index As Integer
For index = 1 To UBound(Rectangles)
If Rectangles(Index).Contains(New Point(e.X, e.Y)) Then
If Not CurHoverIndex = Index Then
'Beep()
CurHoverIndex = Index
Draw(Graphics)
Me.Invalidate()
End If
Exit Sub
End If
Next
End Sub
Private Sub BufferedDraw_Resize(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Resize
Draw(Graphics)
Me.Invalidate()
End Sub
Private Sub BufferedDraw_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
End Sub
End Class
-----------------------------------------------------------------------------
Danke,
Stefan
.
- References:
- GDI+ Performance sehr schlecht (?)
- From: Stefan Uhlemann
- GDI+ Performance sehr schlecht (?)
- Prev by Date: GDI+ Performance sehr schlecht (?)
- Next by Date: Re: GDI+ Performance sehr schlecht (?)
- Previous by thread: GDI+ Performance sehr schlecht (?)
- Next by thread: Re: GDI+ Performance sehr schlecht (?)
- Index(es):
Relevant Pages
|