Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Form2 soll auf das ClientSocket von Form1 zugreifen (https://www.delphipraxis.net/93711-form2-soll-auf-das-clientsocket-von-form1-zugreifen.html)

sk0r 10. Jun 2007 03:49


Form2 soll auf das ClientSocket von Form1 zugreifen
 
Tag.

Ich mache gerade ein Programm mit mehreren Forms.
In Form1 habe ich ein ClientSocket. Nun muss aber
Form2 auch darauf zugreifen können, um etwas ins
Internet zu senden. Ich habe eine extra Funktion
geschrieben, welche ich in der Klassendefinition
von Form1 in den public Bereich gemacht habe.
Ich kann aber leider nicht darauf zugreifen,
weil ich ja zu erst die Unit von Form1 inkludieren
muss. Das geht aber nicht, da Form1 die Form2 schon
inkludiert und es so zu einem Fehler kommt. :(
Die Form1 muss die Form2 inkludieren, da sie die
Form per Button anzeigt.

Meine Frage: Gibt es irgendeinen Weg, dass ich von Form2 auf das
ClientSocket der Form1 zugreifen kann? Bitte um Hilfe!!

Danke im Vorraus!

MfG: sk0r

marabu 10. Jun 2007 08:05

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Guten Morgen.

Forms sind in erster Linie Bausteine der Benutzeroberfläche. Sobald du eine Überkreuznutzung entdeckst, gibt es ein einfaches Hilfsmittel: Verlagere die nicht-visuelle Komponente in eine eigene Unit, die du dann in die Uses-Klauseln der betroffenen Forms aufnimmst.

Sollte dieser Ansatz einmal nicht möglich sein, dann gibt es die hier vereinfachte Regel, die dennoch helfen kann: Überkreuznutzung ist möglich, wenn die Units nicht beide in der Uses-Klausel des interface Abschnitts aufgeführt werden. Siehe dazu OH - Uses-Klausel - Zirkuläre Referenzen.

Grüße vom marabu

SirThornberry 10. Jun 2007 09:03

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
da form2 nach form1 erstellt wird fände ich es am sinnvollsten das du TForm2 von TForm1 aus kreierst und der TForm2-Instanz den Clientsocket übergibst. Alles andere (zum Beispiel TForm2 greift auf die Instanz Form1 zu) ist keine sauber Objektorientierung weil auf bestimmte Instanzvariablen zu gegriffen wird und ein mehrfach erzeugen der Forms dann nicht fehlerfrei funktioniert.
Delphi-Quellcode:
TForm2 = class(TForm)
[...]
private
  fSocket: TClientSocket;
public
  property Clientsocket: TClientSocket read fSocket write fSocket;
Delphi-Quellcode:
TForm1 = class(TForm)
private
  fForm2: TForm2;
[...]
procedure TForm1.FormCreate(Sender: TObject);
begin
  fForm2 := TForm2.Create(Self);
  fForm2.ClientSocket := Self.fClientSocket;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  fForm2.Free;
end;

sk0r 10. Jun 2007 14:04

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Hallo, danke erstmal für die Hilfe.

Ich will es dann jetzt erstmal so machen, dass ich das CLientSocket
in einer eigenen Unit habe. Leider kommt da schon der Fehler, denn
wenn ich auf Werte zugreifen will, bekomme ich eine AV.

Zitat:

Im Projekt Project1.exe ist Exception der Klasse EAccessViolation aufgetreten
Meldung: Zugriffverletzung bei Adresse 0045522E im Modul Project1.exe.
Lesen von Adresse 00000004' Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
Meine Unit sieht so aus:

Delphi-Quellcode:
unit dClientSock;

interface

uses ScktComp, Windows, Sysutils;

type
  TCLSocket = class
  tClientSck: TClientSocket;
  procedure ConnectClient(lpHost: String; iPort: Integer);
  procedure Send(lpTextMsg: String);
  function ReturnValue:String;
  procedure SetValue(lpNewValue: String);
  function ReturnConnect:Boolean;
  procedure tClientSckConnecting(Sender: TObject; Socket: TCustomWinSocket);
  procedure tClientSckConnect(Sender: TObject; Socket: TCustomWinSocket);
  procedure tClientSckDisconnect(Sender: TObject; Socket: TCustomWinSocket);
  procedure tClientSckRead(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Privat }
  public
    { Publik }
end;

implementation

var
  gCurrentVal: String;
  bIsConnected: Boolean;
  gCurrentHost: String;

function TCLSocket.ReturnValue:String;
begin
  result := gCurrentVal;
end;

procedure TCLSocket.SetValue(lpNewValue: String);
begin
  gCurrentVal := '';
end;

function TCLSocket.ReturnConnect:Boolean;
begin
  result := bIsConnected;
end;

procedure TCLSocket.tClientSckConnecting(Sender: TObject; Socket: TCustomWinSocket);
begin
  bIsConnected := false;
  gCurrentVal := 'Connecting to ' + gCurrentHost;
end;

procedure TCLSocket.tClientSckConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  bIsConnected := true;
  gCurrentVal := 'Connected to ' + gCurrentHost;
end;

procedure TCLSocket.tClientSckDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  bIsConnected := false;
  gCurrentVal := 'Connection lost from ' + gCurrentHost;
end;

procedure TCLSocket.tClientSckRead(Sender: TObject; Socket: TCustomWinSocket);
var
  gServerText: String;
begin
  gServerText := Socket.ReceiveText;
end;

procedure TCLSocket.ConnectClient(lpHost: String; iPort: Integer);
begin
  gCurrentHost := lpHost;
  tClientSck.Port := iPort; //Access Violation
  //tClientSck.Host := lpHost;
  //tClientSck.Active := true;
end;

procedure TCLSocket.Send(lpTextMsg: String);
begin
  tClientSck.Socket.SendText(lpTextMsg);
end;

end.
Vielleicht keine schöne Lösung, aber wenn es klappt, reicht es erstmal. Wisst ihr was ich falsch gemacht habe?

Danke schon mal!

marabu 10. Jun 2007 14:09

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Du kapselst eine Komponente TClientSocket, statt davon abzuleiten. Okay, aber du musst die gekapselte Komponente auch instanzieren.

Freundliche Grüße

sk0r 10. Jun 2007 14:14

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Ok, es scheint nun zu funktionieren, indem ich es einfach instanziiere. Danke für eure Hilfe.

sk0r 10. Jun 2007 17:43

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Hallo, ich brauche doch noch mal eure Hilfe.!!

Ich habe es so versucht wie SirThornberry gesagt hat.

In der Form1 verbinde ich mich mit dem Server.

Wenn ich aber dann in Form2 oder Form3 etwas senden
will bekommen ich einen AV:

Zitat:

Zugriffverletzung bei Adresse 00458BC0 im Modul 'Project1.exe'. Lesen von Adresse 00000090
Weiß jemand warum das so ist?

SirThornberry 10. Jun 2007 17:56

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Die Adresse verrät das du entweder wieder etwas nicht instanziert hast oder du bei fForm2 den Socket gar nicht zugewiesen

sk0r 10. Jun 2007 18:10

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Naja, eigentlich habe ich das (habe auf der Form1 nicht selbst Instanziiert, sondern von der Komponentenleiste
auf die Form1 plaziert)..

Delphi-Quellcode:
//Form1
uses [...], clMessages, [...];
//clMessages ist die .pas Datei von der Form2.

type
  TForm1 = class(TForm)
    ClientSock: TClientSocket;
    procedure FormDestroy(Sender: TObject);
    procedure ClientSockConnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientSockConnecting(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSockDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSockRead(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  fForm2: TForm2;
  fForm3: TForm3;
  fForm4: TForm4;
  fForm5: TForm5;
  fForm6: TForm6;
  fForm7: TForm7;
  fForm8: TForm8;
  fForm9: TForm9;
  fForm10: TForm10;
  fForm11: TForm11;

procedure TForm1.FormCreate(Sender: TObject);
begin
    Form2.Show;
     fForm2 := TForm2.Create(Self);
  fForm2.Clientsocket := Self.ClientSock;
  fForm3 := TForm3.Create(Self);
  fForm3.Clientsocket := Self.ClientSock;
  fForm4 := TForm4.Create(Self);
  fForm4.Clientsocket := Self.ClientSock;
  fForm5 := TForm5.Create(Self);
  fForm5.Clientsocket := Self.ClientSock;
  fForm6 := TForm6.Create(Self);
  fForm6.Clientsocket := Self.ClientSock;
  fForm7 := TForm7.Create(Self);
  fForm7.Clientsocket := Self.ClientSock;
  fForm8 := TForm8.Create(Self);
  fForm8.Clientsocket := Self.ClientSock;
  fForm9 := TForm9.Create(Self);
  fForm9.Clientsocket := Self.ClientSock;
  fForm10 := TForm10.Create(Self);
  fForm10.Clientsocket := Self.ClientSock;
  fForm11 := TForm11.Create(Self);
  fForm11.Clientsocket := Self.ClientSock;
    ClientSock.Port := 7000;
    ClientSock.Host := gHostAddr;
    currentHost := gHostAddr;
    ClientSock.Active := true;
end;

//Form2
type
    TForm2 = class(TForm)
    procedure cmdSendClick(Sender: TObject);
    procedure cmdCloseClick(Sender: TObject);
  private
    fSocket: TClientSocket;
    { Private-Deklarationen }
  public
    property Clientsocket: TClientSocket read fSocket write fSocket;
    { Public-Deklarationen }
  end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  fSocket.Socket.SendText('Hallo Server');
end;

sk0r 10. Jun 2007 20:09

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Naja, das Problem ist, wo muss ich sie denn instanziieren? In der Form2 selber doch nicht, oder?

Delphi-Quellcode:
fForm2 := TForm2.Create(Self);
fForm2.Clientsocket := TSocket.Create(Form1);
fForm2.Clientsocket := Self.ClientSock;
So funktioniert es leider nicht.

SirThornberry 10. Jun 2007 20:59

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
weißt du überhaupt was du machst :shock: Du instanzierst zur Zeit einen Socket und weißt dann einen anderen zu. Somit ist die erste Instanz im Nirvana und du kannst nicht mehr drauf zugreifen. Es ist nicht böse gemeint aber du solltest dir erstmal die Grundlagen zur Objectorientierten Programmierung anschauen

marabu 10. Jun 2007 21:00

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Hallo,

ich habe den Eindruck, dass du die in diesem Thread gemachten Lösungsvorschläge gar nicht bewerten kannst. Es besteht jetzt die Gefahr, dass wir dir ein Detailproblem lösen und dich damit auf einem Holzweg begleiten.

Wenn du eine Komponente aus der Palette auf eine Form (Form1) ziehst, dann werden ihre wesentlichen Eigenschaften in der DFM-Datei (letzten Endes ein resource file) gespeichert und beim Erzeugen der Form wird die Komponente zusammen mit dieser instanziert. Die Form ist dabei der Eigentümer dieser Komponente und der Lebenszyklus der Komponente ist an den Lebenszyklus der Form gebunden. Wird die Form zerstört, dann wird auch die Komponente zerstört.

Übergibst du eine solche Komponente an eine andere Form (Form2), so wird dort eine Referenz gespeichert. Eigentümer bleibt die andere Form (Form1) und es ergeben sich Zugriffsprobleme, wenn Form1 zerstört wird, denn dann wird auch die Komponente zerstört und die Referenz in Form2 wird ungültig. Es ist deine Aufgabe dann dafür zu sorgen, dass die Referenz auf nil gesetzt wird.

Solange du also den Vorschlag von Jens aus Beitrag #3 umsetzt, hast du in Form2 eine Referenz und kein eigenständiges Objekt. Also musst du dort auch keine Instanzierung durchführen, das geschieht ja schon in Form1 - wie oben erläutert. Dein Fehler hat eine andere Ursache.

Deiner Klasse in Beitrag #4 fehlt übrigens ein Konstruktor, der die Objektvariable vom Typ TClientSocket instanziert - und eine entsprechender Destruktor, der sie wieder zerstört.

Gute Nacht.

sk0r 10. Jun 2007 21:16

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Ich habe es auch ohne von der komponenteleiste zu ziehen versucht. klappt auch nicht.
ich weiß jetzt gar net ob mein code richtig ist oder net.

naja jedenfalls wüsste ich halt gerne wie ich an die ursache komme.

tutorials dazu gibts afaik auch nicht hab auf dsdt schon gesucht aber da gibts nur einzelne bröckelige
sachen.

marabu 11. Jun 2007 11:04

Re: Form2 soll auf das ClientSocket von Form1 zugreifen
 
Hallo,

du solltest dein Projekt etwas zurückfahren, damit es klein und überschaubar wird. Es nützt nichts, dass du bereits ein Dutzend Forms entworfen und eingebunden hast, wenn die Basisfunktionalität noch nicht implementiert und ausgetestet ist. Ein kleines Projekt, befreit von unnützem Ballast und hier eingestellt, am Besten mit einer groben Beschreibung der Projektidee - du wirst sehen, dann bekommst du auch zielführende Lösungsvorschläge.

Freundliche Grüße


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz