Entwickler-Ecke

Sonstiges (Delphi) - TImage im TThread werden nicht gezeichnet


Martin1966 - Mi 15.06.05 11:12
Titel: TImage im TThread werden nicht gezeichnet
hallo!

ich habe da ein kleines problem was ich nicht lösen kann. ich habe ein delphi projekt mit einem hauptform (Unit mainform.pas) und einen zweiten Form (threadform.pas). das hauptform besitzt nur einen button. das zweite fenster besitzt nur ein timage mit einem bild.

über den button des hauptfesters starte ich einen Thread, dieser ist in threadform.pas implementiert, der nichts anderes macht als das zweite Form mit showmodal anzuzeigen.

klicke ich öfters auf den button so wird auch mehrmals das zweite form angezeigt. und jetzt kommt das problem: wenn ich z. B. drei forms geöffnet habe, diese dann hin und her verschiebe und diese sich überlagern so kommt es vor, dass das Image nicht mehr neugezeichnet wird. Wie kommt das? Ich hab auch schon das ShowModal durch Show ersetzt aber das hat auch nicht geholfen.

Hier mal der Sourcecode... vielleicht könnt ihr mir dann besser helfen. ;-)


mainform.pas
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
unit MainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Uses
  ThreadForm;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThreadTest.Create (False);
end;

end.



ThreadForm.pas
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
unit ThreadForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TThreadTest = Class (TThread)
  Public
    Procedure Execute;  override;
  End;

  TForm2 = class(TForm)
    Image1: TImage;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

implementation

{$R *.dfm}

Procedure TThreadTest.Execute;
Begin
  With TForm2.Create (nilDo
    ShowModal;
End;

end.


vielen dank schon mal für die hilfe!!!

lg martin


maxk - Mi 15.06.05 13:00
Titel: Re: TImage im TThread werden nicht gezeichnet
user profile iconMartin1966 hat folgendes geschrieben:
klicke ich öfters auf den button so wird auch mehrmals das zweite form angezeigt. und jetzt kommt das problem: wenn ich z. B. drei forms geöffnet habe, diese dann hin und her verschiebe und diese sich überlagern so kommt es vor, dass das Image nicht mehr neugezeichnet wird.
Hast du das Problem immer erst bei drei Fenster, oder ist das Problem auch bei einem Fenster schon erkennbar? Eine richtige Lösung kann ich dir nicht vorschlagen, aber vllt. kann ich dir ja helfen die Ursache des Problems einzugrenzen: Pack mal auf das Form des Threads noch einen Buttons, der ein Invalidate; bzw. Image1.Invalidate; (falls es das gibt) ausführt, wenn es dann immernoch nicht geht, probiere mal ein Repaint; (für beide). Ich vermute, dass die Windowsnachricht nicht richtig an das Form übertragen wird.

Gruß,
maxk


Martin1966 - Mi 15.06.05 13:43

hallo!

danke für deine antwort.

user profile iconmaxk hat folgendes geschrieben:
Hast du das Problem immer erst bei drei Fenster, oder ist das Problem auch bei einem Fenster schon erkennbar?

Das Problem ist ab zwei Fenstern zu erkennen. Bei einem Fenster geht alles ohne Probleme. Nur soblad sich zwei oder mehrere Fenster (ThreadForm.pas) gegenseitig überlagern werden diese nicht neugezeichnet.

user profile iconmaxk hat folgendes geschrieben:
Pack mal auf das Form des Threads noch einen Buttons, der ein Invalidate; bzw. Image1.Invalidate; (falls es das gibt) ausführt, wenn es dann immernoch nicht geht, probiere mal ein Repaint; (für beide).

Das habe ich mal ausprobiert. Alle Varianten (jeweils die Aufrufe invalidate und repaint jeweils bei Form und Image) zeigen keine Wirkung.

Hm... weiß einfach keinen Rat mehr... :gruebel:

noch mal danke für deine hilfe!!

lg Martin


Lossy eX - Mi 15.06.05 14:35

Doch sie werden wahrscheinlich neu gezeichnet. Zu mindest wird es versucht. Aber ich glaube, dass deine Bilder kaputt sind. Ich habe derzeit ein sehr sehr (erschreckend) ähnliches Problem. Allerdings kommen bei mir die Fenster aus einer DLL. Habe es aber auch ohne DLLs ausprobiert.

Ich vermute, dass es daran liegt, dass der erstellte Thread und der VCL Thread auf ein und das selbe Applicationobjekt zugreifen. Beide arbeiten zur gleichen Zeit die einkommenden Messages ab und zeichnen dann neu. Das kann dazu führen, dass beide gleichzeitig neuzeichnen oder die gleiche message abarbeiten. Und anscheind geht dabei dann das Bild kaputt. (warum auch imer).

Eine Lösung dafür suche ich derzeit allerdings auch noch. Das einfachste ist du startest die Fenster aus dem Haupthread heraus und rufst lediglich Show auf. Alle anderen Lösungen dürften wohl ein wenig verzwickter werden, da es anscheind so ist, dass jedes Fenster dann anscheinend ein eigenes Applicationobjekt benötigt.


maxk - Mi 15.06.05 21:44

user profile iconMartin1966 hat folgendes geschrieben:
user profile iconmaxk hat folgendes geschrieben:
Pack mal auf das Form des Threads noch einen Buttons, der ein Invalidate; bzw. Image1.Invalidate; (falls es das gibt) ausführt, wenn es dann immernoch nicht geht, probiere mal ein Repaint; (für beide).

Das habe ich mal ausprobiert. Alle Varianten (jeweils die Aufrufe invalidate und repaint jeweils bei Form und Image) zeigen keine Wirkung.
Von user profile iconLossy eX inspiriert könntest du mal versuchen den Aufruf in einer CriticalSection zu machen, dann kann man Probleme beim gleichzeitigen Zugriff auf das Applicationobjekt ausschließen.


Martin1966 - Mo 20.06.05 16:14

Hallo!

danke für eure hilfe!!!

Aber worum soll ich denn dann die Criticalsection packen? denn schließlich passiert dieser "fehler" ja schon beim simplen verschieben von Fenstern? ich kann ja schlecht auf das verschieben von fentern reagieren und dann in invalidate in einer criticalsection aufrufen.

ist das ein fehler in der vcl? denn schließlich mache ich ja nichts anderes als zwei threads zu starten in denen ein modales fenster geöffent wird. da kann man doch kaum was falsch machen. :nixweiss:

lg Martin


Lossy eX - Mo 20.06.05 16:55

Weder die VCL noch GDI sind wohl Threadsave. Das hat zur Folge, dass wenn zwei Threads jeweils ShowModal aufrufen diese sich ein und das selbe ApplicationObjekt teilen. Und damit die selben Messages abarbeiten. Was wiederum zu leichten Problemen führen kann. Das einzige was halbwegs etwas bringen würde ist wenn man es schaft das jeder Thread ein eigenes Applicationobjekt bekommt. Dummerweise traten bei mir immer noch unerklärliche Fehler auf. Accessviolations an den wildesten Stellen. Das kann man unmöglich mit CriticalSections etc sichern.


Martin1966 - Mi 22.06.05 09:09

hm... schade das ich keinen fehler gemacht habe und dadurch Problem leichter zu lösen wäre ;-)

danke auf jeden fall für deine/eure hilfe!!!

lg martin