Ok, also praktisch mal ein Backtrace was bis dahin passiert.
(Ich kann schonmal von vorneherein sagen: in meinem Code kommt weder eine Schleife noch eine absichtliche Rekursion vor... das mit den Gettern...nicht das es mir aufgefallen wäre)
Das ganze ist extrem gekürzt...
aber alles relevante sollte drin sein.
So, der ButtonClick
Delphi-Quellcode:
TForm_Main = class(TForm)
public
I: TChatInterface;
C: TChatClient;
end;
procedure TForm_Main.FormCreate(Sender: TObject);
begin
C.OnSleep:=Application.ProcessMessages;
end;
procedure TForm_Main.Btn_ConnectClick(Sender: TObject);
var ID: Integer;
req: TChatDataPackage;
begin //Wir wollten unsern Client mit einem Server Verbinden
if C.Connected then
//Kommt nicht vor, wir sind noch nicht Connected...
else
begin
ID:=I.ServerHistory.Add(Cmb_Hostname.Text); // Erstmal Servername speichern
try
C.Connect(I.ServerHistory[ID].Host,I.ServerHistory[ID].Port); //Verbinden
req :=TChatDataPackage.Create('LOGIN',I.Profile.Nick,I.Profile.Passwd); //Login-Request Erstellen
C.OnUserInput(req); //und absenden
req.Free; //und wieder freigeben
except
on E: EConnectException do I.AddServer('Connection Failed'); //Wenns schiefgeht Fehlermeldung machen
end;
end;
I.ServerHistory.Export2Strings(Cmb_HostName.Items); //Liste mit den Servern Updaten
end;
Aufgerufen wird zunächst C.Connected:
Delphi-Quellcode:
TChatClient =class
private
Fidtcp: TIdTCPClient;
FOnSleep: TOnSleep;
public
procedure Connect(Host: String; Port: Integer);
function Connected: Boolean;
property OnSleep: TOnSleep write FOnSleep;
end;
procedure TChatClient.Connect(Host: String; Port: Integer);
var CT: TConnectThread;
T: Cardinal;
TT: TThread;
begin
if FIdTCP.Connected then Exit;
try
CT:=TConnectThread.Create(True);
CT.FreeOnTerminate:=True;
CT.TCP:=Fidtcp;
CT.Host:=Host;
CT.Port:=Port;
T:=GetTickCount+5000;
CT.Resume;
while (not CT.Terminated) do
begin
FOnSleep;
if (T-GetTickCount<0) or (Fidtcp.Connected) then Break;
Sleep(50);
end;
CT.Terminate;
if not Fidtcp.Connected then raise EConnectException.Create('');
FListeningThread.Resume;
except
raise EConnectException.Create('');
end;
end;
function TChatClient.Connected: Boolean;
begin
Result:=FIdTCP.Connected;
end;
Dann I.ServerHistory.Add
Delphi-Quellcode:
TChatInterface = class (TObject)
private
FServerHistory: TServerHistory;
public
property ServerHistory: TServerHistory read FServerHistory;
end;
type
TServer = record
Name: String;
Host: String;
Port: Integer;
end;
TServers = array of TServer;
TServerHistory = class(TObject)
private
FItems: TServers;
function Cmp(V1,V2: TServer): Integer;
public
function Add(S: String): Integer; overload;
function Add(Name,Host: String; Port: Integer): Integer; overload;
procedure Export2Strings(S: TStrings);
property Items[ID: Integer]: TServer read GetItem; default;
end;
function TServerHistory.Add(S: String): Integer;
var Name,Host: String;
begin //Ungeparsten Server in Liste schmeissen
S:=Trim(S);
if Pos('(',S)>0 then
begin // "Name (Host:Port)"
Name:=Copy(S,1,Pos(' (',S)-1);
S:=Copy(S,Pos(' (',S)+2,Length(S)-Pos(' (',S));
end;
Host:=Copy(S,1,Pos(':',S)-1);
Delete(S,1,Pos(':',S));
Result:=Add(Name,Host,StrToInt(S));
end;
function TServerHistory.Add(Name, Host: String; Port: Integer): Integer;
var i, Akt, Hi, Lo: Integer;
S: TServer;
begin //Server an sortierter Position einfügen
S.Name:=Name;
S.Host:=Host;
S.Port:=Port;
Hi:=High(FItems);
Lo:=Low(FItems);
if Hi<0 then Hi:=0;
Akt:=Abs(Hi+Lo) div 2;
while Hi-Lo<2 do
begin //Richtige Stelle suchen
i:=Cmp(FItems[Akt],S);
case i of
1: Hi:=Akt;
0: Exit;
-1: Lo:=Akt;
end;
Akt:=(Hi+Lo) div 2;
end;
SetLength(FItems,Length(FItems)+1);
for i:=Akt to Length(FItems)-1 do
FItems[i+1]:=FItems[i];
FItems[Akt]:=S;
Result:=Akt;
end;
Dann kommt C.Connect(I.ServerHistory[ID].Host,I.ServerHistory[ID].Port)
der Zugriff auf I.ServerHistory und C.Connect steht ja oben schon