Autor Beitrag
rochus
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416

Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
BeitragVerfasst: So 17.08.03 20:29 
Hallo,

mein Problem könnte man auch ins Netzwerke schieben, hat aber - denke ich - mehr mit dem hier zu tun.. ich fang dann mal an:

ich hab nen server und nen client, der client kann support anfragen schicken, durch die dann ein bestimmtes fenster (abgeleitet von TfrmSupport) erstellt werden soll. nun ist ja natürlich klar, dass dieses Fenster dynamisch erstellt werden soll. dies geschieht (da ich die INdy komponenten verwende) aus der procedure OnExecute des IDTCPServers heraus. Mal ein kleiner code-ausschnitt:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
procedure TCPServerexecute(..)
var
    strClient,
    strTemp: string;
    strSupport: TStringList;
begin
   strTemp := AThread.connection.readln;
   if strTemp = '&support' then
   begin
      strSupport := TStringList.create;
      strClient := Athread.connection.readln;
      AThread.connection.readstring(strSupport);
      Application.CreateForm(TfrmSupport,frmSupport);
      frmSupport.show;
      frmSupport.FillWithData(strClient,strSupport);
      strSupport.Free;
   end;
end;


das ist ein ausschnitt der onexecute, die fillwidthdata funktion tut nichts anderes als ein label.caption mit strClient füllen und ein memo mit strSupport.

sobal dieses frmSupport.show aufgerufen wird, hängt mein programm! die form wird nichtmal ganz gezeichnet, nur di flächen (also grau für normal, weiß für memo und edit-felder..)

woran liegt das?

gruß
rochus
worm
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 135


D6 Prof
BeitragVerfasst: So 17.08.03 23:35 
Wahrscheinlich nicht an dem von Dir geposteten Code. Erstmal würde ich vorschlagen, frmSupport.FillWithData vor frmSupport.Show aufzurufen, und dann solltest Du mal gucken, ob in frmSupport.FillWithData oder frmSupport.OnShow irgendwo eine Endlosschleife läuft. Das würde nämlich das Fenster davon abhalten, die Botschaften von Windows zu empfangen und sich zu zeichnen :).
Cya, f0k

_________________
In the beginning, the universe was created. This has made a lot of people very angry, and is generally considered to have been a bad move.
rochus Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416

Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
BeitragVerfasst: So 17.08.03 23:57 
naja, in der newsgroup hab ich gehört, dass das daran liegt, dass indy in nem gesonderten thread abläuft und in dem vcl nix zu suchen hat..

deine methode hatte ich zuvor so:

frmsupport.showwithdata(...)

wobei ich dort die daten übergeben hab und dann in der showwithdata nach dem zuweisen der daten show; ausgeführt hab. selber effekt.. in der onshow der frmsupport ist nichts, also keine deklaration für onshow..
worm
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 135


D6 Prof
BeitragVerfasst: Mo 18.08.03 00:46 
Hmm, sehr merkwürdig... im Moment fällt mir nichts andres ein als: Poste mal deine FillWidthData-Prozedur. Allerdings: Wäre da eine Endlosschleife drin, wäre das Fenster bei deiner ersten Variante nie angezeigt worden. Also muss der Fehler eigentlich woanders liegen.
Was passiert, wenn Du das Fenster nach dem FillWidthData nicht mit Show, sondern mit ShowModal anzeigst?

_________________
In the beginning, the universe was created. This has made a lot of people very angry, and is generally considered to have been a bad move.
rochus Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416

Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
BeitragVerfasst: Mo 18.08.03 10:47 
hmm, mit showmodal funktioniert es ohne weiteres!!!!

hier aber mal die procedure, die ich nun verwende zum datenfüllen und anzeigen (ist ganz wenig!)

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TfrmSupport.ShowWithData(strClient: string; strText: TStringList);
begin
  FClient := AnsiUpperCase(strClient);
  lblClient.Caption := FCLient;
  edtQuestion.Lines := strText;
  ShowModal;
end;
worm
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 135


D6 Prof
BeitragVerfasst: Mo 18.08.03 23:58 
Ah, ich glaube hier liegt der Fehler: Durch "edtQuestion.Lines := strText;" kopierst Du die Daten nicht, sondern edtQuestion.Lines zeigt dann auf die selbe Instanz der TStringList wie strText. Diese Stringlist gibst du aber im aufrufenden Thread direkt nach ShowWithData wieder frei. Folge ist, dass FrmSupport.edtQuestion.Lines auf ein ungültiges (da freigegebenes) Objekt zeigt.
Mit ShowModal ging es, weil dann der aufrufende Thread warten muss, bis Du das Fenster wieder geschlossen hast. Dadurch kann er die StringList auch erst danach wieder freigeben.
Lange Rede, kurzer Sinn: Versuch's mal mit "edtQuestion.Lines.Assign(strText);" und dem normalen Show, das müsste eigentlich dann gehen. Wenn ich mich jetzt nicht irgendwo verplant hab.

Cya, worm

_________________
In the beginning, the universe was created. This has made a lot of people very angry, and is generally considered to have been a bad move.
rochus Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416

Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
BeitragVerfasst: Di 19.08.03 01:21 
hi,

schön, wenn es das wäre :/ ich hab es so gemacht, wie du meintest.. warte, ich häng mal meine onexecute hier rein:

ausblenden volle Höhe Delphi-Quelltext
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:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
procedure TfrmCManServer.IDTCPSCManServerExecute(AThread: TIdPeerThread);
var
   strTemp  : string;
  strClient: string;
  strLog   : string;
  strLogType : string;
  strSupport: TStringList;
  intSupport : integer;
  strMsg : string;
  i  : integer;
  filestream : TFileStream;
  filesize : int64;
  strExeDir,
  strFullDir : string;
begin
  strTemp := AThread.Connection.ReadLn();

  strTemp := AnsiUpperCase(strtemp);
  if strTemp = AnsiUpperCase('&@connect'then
  begin
    {..}
  end;


  
  if strTemp = AnsiUpperCase('&@log'then
  begin
    { .. }
  end;



  // client-datei kommt -> abspeichern im dazugehörigen ordner!
  if strTemp = AnsiUpperCase('&@clientfile'then
  begin
    {..}
  end;

  


  (* SUPPORT MELDUNG KOMMT AN.. *)
  if strTemp = AnsiUpperCase('&@support'then
  begin
    // jetzt kommt ne support-anfrage
    strSupport := TStringList.Create;
    strClient := AThread.Connection.ReadLn();
    intSupport := Athread.connection.ReadInteger;

    for i:=0 to intSupport-1 do
      strSupport.Add(AThread.Connection.ReadLn);
    Application.CreateForm(TfrmSupport,frmSupport);
    frmSupport.ShowWithData(strClient,strSupport);
  end;




  
  if strTemp = AnsiUpperCase('&@msg'then
  begin
    // jetzt kommt ne einfache nachricht..
    strClient := AThread.connection.readlN;
    strMsg   := Athread.connection.readln;
    ShowMessage(strClient + ': ' + strMsg);
  end;

end;



achja, was mir noch aufgefallen ist: wenn ich den client dann disconnecte, dann gibt sich das programm wieder frei! mithilfe von dem, was du mir gesagt hast, wird zumindest die form korrekt aufgebaut und dann bleibt sie stehen... :/ ich probiers mal eben über nen extra thread für das fenster.
Aya
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: Di 19.08.03 01:49 
Hi,

wie du schon richtig gesagt hast läuft Indy Thread basiert ab, und da mußt du deinen Thread erst mit dem MainThread deines Programmes Synchronisieren.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure OpenForm;
begin
  strSupport := TStringList.create; 
  strClient := Athread.connection.readln; 
  AThread.connection.readstring(strSupport); 
  Application.CreateForm(TfrmSupport,frmSupport); 
  frmSupport.show; 
  frmSupport.FillWithData(strClient,strSupport); 
  strSupport.Free; 
end;

procedure TCPServerexecute(..) 
var 
    strClient, 
    strTemp: string
    strSupport: TStringList; 
begin 
   strTemp := AThread.connection.readln; 
   if strTemp = '&support' then 
   begin 
     Synchronize(OpenForm); //Wichtig!!
   end
end;


So sollte das ganze klappen, is allerdings ungetestet.. ansonsten schau dir mal in der Hilfe an was da zu Synchronize steht.

Au'revoir,
Aya~

_________________
Aya
I aim for my endless dreams and I know they will come true!
rochus Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416

Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
BeitragVerfasst: Di 19.08.03 14:25 
Danke für eure Bemühungen

also, ich hab das jetzt wie folgt:

ausblenden volle Höhe Delphi-Quelltext
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:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
SupportStrings: TStringList;
SupportClient : String;
aSupportCS : TCriticalSection;


form.create;
begin
    SupportStrings := TStringList.create;
    aSupportCs := TCriticalSection.Create;
end;


formdestroy;
begin
    aSupportCS.Destry;
end;



ServerExecute;
begin
    (* SUPPORT MELDUNG KOMMT AN.. *)
    if strTemp = AnsiUpperCase('&@support'then
    begin
        // jetzt kommt ne support-anfrage
        strSupport := TStringList.Create;
        strClient := AThread.Connection.ReadLn();
        intSupport := Athread.connection.ReadInteger;

        for i:=0 to intSupport-1 do
            strSupport.Add(AThread.Connection.ReadLn);
        aSupportcs.Enter;
        try
            SupportStrings.Clear;       
            SupportClient  := strClient;
            SupportStrings := strSupport;
        finally
            aSupportCs.Leave;
        end;

        Athread.Synchronize(SupportForm);
    end;
end;



SupportForm;
var
    myList : TStringList;
    myClient: string;
begin
    myList := TStringList.Create;

    aSupportCS.Enter;
    try
        myClient := SupportClient;
        myList := SupportStrings;
        SupportStrings.clear;
        SupportClient := '';
    finally
        aSupportCS.Leave;
    end;
    Application.CreateForm(TfrmSupport,frmSupport);
    frmSupport.ShowWithData(myClient,myList);
    myList.Free;
end;



aber irgendwie scheint es nicht zu wollen. zumindest bekomme ich zwar die frmSupport angezeigt, doch der inhalt fehlt.. leider. und wenn der client disconnected und dann wieder connected und schließlich ne anfrage sendet wird er gracefull disconnected und wenn ich versuche, den server zu schließen, kommt ne fehlermeldung..

woran kann das noch liegen?? gruß
rochus
rochus Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416

Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
BeitragVerfasst: Di 19.08.03 17:57 
hallöchen. ich denke, ich bin zu einer lösung gekommen :) endlich.. wenn die MODs das wollen, können sie es auch irgendwie in die FAQ einbauen unter -> "aus einem Indy-Thread heraus dynamisch eine Form erstellen und dynamisch mit Daten füllen".

also, das sieht nun folgendermaßen aus:
es wird eine Unit erstellt, in der der Typ TfrmSupport deklariert wird. die muss natürlich in der Hauptunit eingebunden werden..

ausblenden volle Höhe Delphi-Quelltext
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:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
  TForm1 = class(TForm)
    { .. }
    public
      procedure CreateNewSupportWin(Sender: TObject);
  end;

  TSupportThread = class(TThread)
    private
      FClient : string;
      FText    : string;
    public
      constructor Create(AClient, AText: string);
      procedure Execute; override;
  end;


{ Implementation des ganzen: }

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
  strTemp : string;
  strClient: string;
  strLog : string;
begin
  strtemp := AThread.Connection.ReadLn();
  if strTemp = '&@support' then
  begin
    with TSupportThread.Create('abc','def'do
      FreeonTerminate := true;
  end;
end;

constructor TSupportThread.Create(AClient, AText: string);
begin
  inherited Create(False);
  FClient := AClient;
  FText   := AText;
end;

procedure TSupportThread.Execute;
begin
  OnTerminate := form1.CreateNewSupportWin;
end;

procedure TForm1.CreateNewSupportWin(Sender: TObject);
begin
  Application.CreateForm(TfrmSupport,frmSupport);
  with TSupportThread(Sender) do
  begin
    frmSupport.memo1.lines.add(FText);
    frmSupport.label1.Caption := FClient;
  end;
  frmSupport.Show;
end;


so, das ganze wird jetzt noch ausgiebig getestet..

falls jemand einen denkfehler darin entdeckt, der melde sich bitte :)

gruß
rochus