Problem mit TImage / Thread / Synchronize
-
Hallo,
ich habe folgendes Problem:
in meiner Anwendung gibt es ein TImage, 400x320 Pixel gross. Dieses dient als Oszilloskop, wo entsprechende Messungen angezeigt werden.
Während der Laufzeit erzeuge ich zum Programmstart ein zweites (unsihctbares)TImage, das ich als Buffer benutze: zuerst zeichne ich alle Linien in den Buffer, wenn dies fertig ist kopiere ich den Inhalt des Buffers in das eigentliche TImage.
So weit so gut. Dies funktioniert prinzipiell. Das TImage befindet sich auf dem Hauptfenster der Anwendung, das zeichnen bzw. das kopieren in das TImage erfolgt jedoch aus einem anderen Thread. Also benutze ich dazu Synchronize.
Leider habe ich jetzt folgenden Effekt: wenn ich während des Zeichnens/Kopierens den Mauszeiger auf dem TImage bewege, so führt dies zum beenden(!) des Threads! Wenn ich aus dem Hauptthread in das TImage zeichne ist alles ok.zur Laufzeit in MainWin::FormCreate() erzeugtes TImage:
OsziBuffer = new TImage(NULL); OsziBuffer->Width = 400; OsziBuffer->Height = 320; OsziBuffer->Visible = false;OsziBuffer ist in Main.h deklariert, FNewPruef ist der Thread der Probleme macht:
TThread* FNewPruef; TThread* FNewWatch; TImage *OsziBuffer;im Thread FNewPruef mache ich folgendes:
Synchronize(WriteOszi);void __fastcall TTdsPruefen::WriteOszi() { MainWin->Oszi->Picture->Bitmap->Assign(MainWin->OsziBuffer->Picture->Bitmap); }Was mache ich falsch?
Danke,
Jochen
-
Verwende doch statt eines weiteren TImage als buffer eine TBitmap-Instanz welche dem Thread alleine gehört. Eventuell hilft das....
-junix
-
Nein, leider nicht. Andere Idee?
Jochen
-
Beide Images gehoeren dem Hauptfenster???
Dann mach doch nen Messagehandler in der Form und sende aus dem Thread ne Message!
Das Zeichnen macht dann der Messagehandler der Hauptform.
-
DerAltenburger schrieb:
Beide Images gehoeren dem Hauptfenster???
Dann mach doch nen Messagehandler in der Form und sende aus dem Thread ne Message!
Das Zeichnen macht dann der Messagehandler der Hauptform.Danke, das war schon mal ein guter Ansatz. Leider noch nicht wirklich perfekt.
Ich habe jetzt folgendes gemacht:
Das Senden aus dem anderen Thread:PostMessage(MainWin->Handle, WM_USER, 0, 0);Im Hauptfenster
void __fastcall TMainWin::MyMessage(tagMSG &Msg, bool &Handled) { if (Msg.message == WM_USER) { Oszi->Picture->Bitmap->Assign(OsziBuffer->Picture->Bitmap); Handled = true; } /* Für alle anderen Botschaften bleibt Handled false, damit andere Botschaftsroutinen antworten können */ }So, das bringt noch gar nichts. Beim Bewegen des Mauszeigers auf dem Image wird der Thread immer noch beendet, das Image verschwindet.
Jetzt habe ich einfach mal versuchsweise meinen Buffer gelöscht und neu eingerichtet, also so (PD.SysData.MessageHandled verhindert, dass der aufrufende Thread weiterläuft solange die Message noch nicht verarbeitet wird.):
void __fastcall TMainWin::MyMessage(tagMSG &Msg, bool &Handled) { if (Msg.message == WM_USER) { Oszi->Picture->Bitmap->Assign(OsziBuffer->Picture->Bitmap); delete OsziBuffer; OsziBuffer = new TImage(NULL); OsziBuffer->Width = 400; OsziBuffer->Height = 320; OsziBuffer->Visible = false; PD.SysData.MessageHandled = true; Handled = true; } /* Für alle anderen Botschaften bleibt Handled false, damit andere Botschaftsroutinen antworten können */ }Jetzt wird der Thread nicht mehr beendet wenn der Mauszeiger auf dem Image bewegt wird. Allerdings kommt es ab und zu vor, dass das Image verschwindet und erst wieder aufgebaut wird, wenn eine neue Messung und somit ein neues Zeichnen des Image erfolgt. Auch ein regelmässiges Refresh() oder Repaint() in OnIdle ändert da nichts.
Jochen
-
Hast Du auch mal SendMessage probiert?
Bei PostMessage arbeitet der Thread weiter und kann den BildInhalt aendern/zerstoeren bevor der Hauptthread reagiert.
-
DerAltenburger schrieb:
Hast Du auch mal SendMessage probiert?
Ja, habe ich. Leider geht das bei mir nicht, d.h. mit SendMessage wird die Message nicht gesendet. Mit PostMessage geht es.
Bei PostMessage arbeitet der Thread weiter und kann den BildInhalt aendern/zerstoeren bevor der Hauptthread reagiert.
Deshalb habe ich die Variable PD.Sys.... benutzt, die ich im Thread so lange abfrage, bis diese von Hauptfenster wieder auf true gesetzt wird.
Jochen
-
Mach mal statt
Oszi->Picture->Bitmap->Assign(OsziBuffer->Picture->Bitmap);
ein
Oszi->Picture->Bitmap->CanvasDraw(0,0,OsziBuffer->Picture->Bitmap);
PS: Hoehe und Breite muessen (am Anfang ) selber gesetzt werden!
-
DerAltenburger schrieb:
ein
Oszi->Picture->Bitmap->CanvasDraw(0,0,OsziBuffer->Picture->Bitmap);
wenn ich daraus ein:
Oszi->Canvas->Draw(0,0,OsziBuffer->Picture->Bitmap);bekomme ich zumindest vom Compiler keine Fehlermeldungen mehr

Das Bild verschwindet jetzt auch nicht mehr, allerdings wird es bei Mausbewegungen auch nicht mehr aktualisiert. Erst bei einem erneuten Zeichnen nach Mausstillstand geht das wieder. Hmmm, damit könnte ich fast leben, wäre "nur" ein Schönheitsfehler. Für weitere Anregungen bin ich natürlich trotzdem dankbar

Eigentlich wollte ich doch nur ein paar Linien zeichnen...vielleicht sollte ich mal ganz von vorne anfangen so nach dem Motto "wat isse ne Dampfmaschien"Jochen