canvas-routinen zu langsam
-
Hi, ich progge grad ne eigene Kompo die auf einem TGraphicControl basiert.
Auf dessen Canvas zeichne ich ein Viereck. (die Kompo machst später noch mehr, aber mir geht es hier um ein grundlegendes Problem).
Wenn ich die Kompo nun auf ein Formular ziehe (align = alClient) und die Fenstergröße zur laufzeit ändere, so blingt das Viereck meiner Kompo.Später hab ich sehr viele dieser Komponente auf einer Form und dass ist bisher ein schöner blinkender Haufen.
Nun meine Frage: Gibt es schnellere Routinen, um ein Viereck auf ein Canvas zu Zeichnen? Also ich habs bisher mit Rectangle gemacht.
Das blinken der Kompo könnte man auch mit DoubleBuffered verhindern, nur ist dann der gesamte Aufbau langsam.
thx im vorraus
-
Vielleicht mit LockWindowUpdate (Win-API)?
Gruß,
Alexander
-
Das blinken der Kompo könnte man auch mit DoubleBuffered verhindern, nur ist dann der gesamte Aufbau langsam.
ehh..???
-
wenn man die eigenschaft DoubleBuffered des formulars auf true setzt, dann werden die visuellen elemente der form erst in einem zwischenspeicher "gemalt" und dann auf die form gesetzt.
das verhindert das blinken, aber bei vielen elementen ist der aufbau spürbar langsamer
-
Jester2000 schrieb:
aber bei vielen elementen ist der aufbau spürbar langsamer
glaub ich nicht
doublebufferd ist nur ne verdopplung .. du hast .. e.g. 2 TImage .. wenn nu ne veänderung machst lädt es in die 2 Timage hinter der 1sten Zeichnung und wenns fertig geladen hat .. wird das vordere in den hintergrund gestellt ...
bei aufwändigen Bildern und schlechten Routinen wirds dann extrem langsam ...
Edit:
Zitate bitte auf das Notwendigste beschränken. Danke!
-
also ich habe die erfahrung gemacht, dass wenn ich doublebuffered einschalte und viele objekte auf der form rumschwirren, dass ich dann beim aufbau zuschauen konnte
aber dass ist ja nicht mein eigentliches problem
ich suche eine möglichkeit, meine Kompo zu beschleunigen (schnellere Grafikroutinen, wenns sowas gibt)
-
ich weiß zwar nicht wie das Borland macht aber
es gibt DoubleBuffering Routinen, die für jedes
Element einen neuen temporären DeviceContext erstellen.
Dieser wird nach dem Zeichnen eines Elements wieder
zerstört. Das ist natürlich langsam.
Daher kannst du ja mal probieren einen eigenen DoubleBuffering
Algorithmus schreiben, welcher nur einen großen temporären
DeviceContext nutzt. Dann würdest du die das viele
Erstellen und Zerstören sparen.PS: Wenn die VCL von Borland das jedoch genau
so macht nehme ich natürlich alles zurückBye Peter.
-
ich nochmal. Du kannst ja mal probieren was passiert
wenn du statt VCL Zeichenfunktionen direkt auf die
Win32 API Funktionen zurück greifst.
Normalerweise sollte der Unterschied nicht
spürbar sein. Aber vielleicht bringt es dir
ja etwas.Bye Peter.
-
ok, ist nen versuch wert, thx
-
hmm.... ich weiss nicht, ob (und wieviel) schneller das wie das DoubleBuffered aus der VCL ist, aber ich hab selber mal eine Art DoubleBufferung geschrieben. (ich les in diesem Thread grad zum 1. mal dass ein Canvas schon von vorn herein DoubleBuffer unterstuetzt
)
Wie auch immer, vielleicht hilfts dir ja:
Wie jemand schon gesagt hat: beim DoubleBuffering werden 2 statt nur 1 Framebuffer gezeichnet... noch waehrend der erste Framebuffer auf den Schirm gezeichnet wird, wird der zweite berechnet... anschliessend werden die beiden Schirme getauscht (d.h. der 2. wird gezeichnet und der 1. vorbereitet)
Definieren der 2 Oberflaechen:
class TMainForm : public TForm { private: // Anwender-Deklarationen // .... Graphics::TBitmap* mDrawSurface[2]; int mActualSurface;
Erstellen der Oberflaechen
__fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner), mActualSurface(0) { // erstelle die Oberflaeche for (int i = 0; i < 2; ++i) { mDrawSurface[i] = new Graphics::TBitmap(); mDrawSurface[i]->Width = Surface->Width; mDrawSurface[i]->Height = Surface->Height; } // ...... }
in der Hauptschleife des Programmes wird immer wieder auf die Bitmaps gezeichnet:
{ // mSim::draw() veraendert die aktuelle Oberflaeche mSim.draw(mDrawSurface[mActualSurface]); // kopiere die bearbeitete Oberflaeche auf das Canvas Surface->Canvas->CopyRect(Surface->Canvas->ClipRect, mDrawSurface[mActualSurface]->Canvas, mDrawSurface[mActualSurface]->Canvas->ClipRect); // switche Oberflaeche mActualSurface = !mActualSurface; } Surface->Canvas->Refresh();
Ich bin ziemlicher VCL-Anfaenger (oder war's, mitterweile auf anderen Compiler gewechselt), und weiss nicht, wieviel Speed (wenn ueberhaupt) dir das bringt, aber 'n Versuch ists vielleicht wert....
EDIT: Code-Cleanup