![]() |
eigenes Event programmieren?
Hi und sorry, dass ich schon wieder einen neuen Thread auf machen...ist erstmal der letzte, versprochen.
Folgendes: Ich habe eine Unit programmiert, welche für mich per Indy Dateien verschickt und empfängt. Hierbei sage ich einfach meiner Unit, welcher filestream verschickt werden soll und an welche IP. Um den rest (Server und Client verwaltung etc) kümmert sich dann die Unit. In dieser Unit benutzte ich den IDTCPServer. Der hat ein Event "OnExecute" das ja genau dann aufgerufen wird, wenn Daten "ankommen" also eine clientverbindung besteht. Jetzt stellt euch folgendes vor: Die Daten werden von der Unit empfangen. D.h. ich jetzt jetzt da in irgendeiner form z.B. in einem Memorystream die Daten vorliegen, will sie jetzt aber von der Unit in mein Hauptprogramm übergeben. Will die Unit selber aber so allgemein halten, dass ich nicht irgendwie das Hauptprogramm damit verwebe... Daher hatte ich mit gedacht, es wäre sinnvoll so eine Art weiteres OnEvent zu haben, sodass man im Hauptprogramm z.B. eine OnDATARECEIVED Procedur schreiben kann, welche als Parameter den Memorystream an das Hauptprogramm übergibt... Ich hoffe ihr wisst, was ich meine?! ;) Habe die Suche bemüht, aber nichts gefunden was wirklich zu diesem Problem passt?! Vorsichtshalber schicke ich euch nochmal den sourcecode mit
Delphi-Quellcode:
unit LANFS_KERNAL; interface uses SysUtils, Classes, IdBaseComponent,IdStreamVCL, IdComponent, IdTCPServer,IdTCPConnection,IdTCPClient,IdContext; type TLANFS_KERNAL = class public procedure ReceiveStream(Acontext:TidContext); procedure Start(port:integer); procedure Stop(); procedure SendStream(Stream: TFilestream;Host:String); end; var LANFS_SYSTEM :TLANFS_KERNAL; TCPClient1: TIdTCPClient; TCPServer1: TIdTCPServer; implementation procedure TLANFS_KERNAL.Start(port:integer); { +Aktiviert TCPClient und TCPServer +Sollte immer am Start des Programms aufgerufen werden. +zuletzt editiert: 24.05.06 } begin TCPClient1:= TIdTCPClient.Create; TCPClient1.Port:=Port; with TCPClient1 do begin ReadTimeout:=5000; ConnectTimeout:=5000; end; TCPServer1:= TIdTCPServer.Create; TCPServer1.OnExecute := LANFS_SYSTEM.ReceiveStream; with TCPServer1 do begin MaxConnections:=1; DefaultPort:=Port; Active:=True; end; end; procedure TLANFS_KERNAL.Stop(); {Stopt Server und Client, gibt Speicher frei. zuletzt editiert: 24.06.05} begin TCPClient1.Free; TCPServer1.Active:=False; TCPServer1.Free; end; procedure TLANFS_KERNAL.SendStream(Stream: TFilestream;Host:String); { +Versendet vom TCPClient an TCPServer einen Filestream +Dieser wird als Parameter übergeben, und muss vorher erzeugt worden sein. +zuletzt editiert: 24.05.06 } var IndyStream: TidStreamVCL; begin TCPClient1.Host:=Host; try IndyStream := TidStreamVCL.Create(Stream); try { Senden } with TCPClient1 do begin Connect; try Socket.Write(IndyStream, 0, true); finally Disconnect; end; end; finally FreeAndNil(IndyStream); end; finally FreeAndNil(Stream); end; end; procedure TLANFS_KERNAL.ReceiveStream(Acontext:TidContext); { +Empfängt vom TCPClient an TCPServer einen Filestream +zuletzt editiert: 25.05.06 } var FSTream: TFileStream; SizeOfIncomingStream: Integer; IDS: TidStreamVCL; begin FStream := TFileStream.Create('C:\test.tmp', fmCreate); //Hier soll der Filestream nicht mehr als try //Datei gespeichert werden, sondern an das IDS := TidStreamVCL.Create(FStream); //Hauptprogramm übergeben werden! try { Empfangen } with AContext.connection do begin try SizeOfIncomingStream := Socket.ReadInteger; Socket.ReadStream(IDS, SizeOfIncomingStream); finally Disconnect; end; end; { Damit der Inhalt von IDS in FStream übertragen wird } IDS.VCLStream.Position := 0; finally FreeAndNil(IDS); end; finally FreeAndNil(FStream); end; end; end. |
Re: eigenes Event programmieren?
ein Event wird wie folgt defniert:
Delphi-Quellcode:
Anstelle eines eigenen EventTypes kannst du natürlich auch bereits vorhandene wie TNotifyEvent etc. nutzen wenn dir diese von den Parametern her zusagen.
type
TNameDeinesEventTypes = procedure(Sender: TObject; AParameterXYZ: String) of Object; TDeineKlasse = class(TIrgendwas) [...] fDeinEvent: TNameDeinesEventTypes; [...] property OnDeinEvent: TNameDeinesEventTypes read fDeinEvent write fDeinEvent; [...] end; implementation [...] procedure TDeineKlasse.LoeseEventAus(MitZuGebenderParameter); begin if Assigned(fDeinEvent) then fDeinEvent(Self, MitZuGebenderParameter); end; |
Re: eigenes Event programmieren?
Vielen Dank, ich habe es mal soweit eingebaut.
Allerdings gibts leider eine exception, wenn ich im Hauptprogramm diese zuweisung mache: (Sorry, da ich mich mit diesem Teil von Delphi nicht auskenne, mute ich euch hier etwas viel zu...)
Delphi-Quellcode:
Das ganze sieht jetzt so aus:
lanfs_system.OnReceivedData:= Form2.test;
Delphi-Quellcode:
Liebe Grüße und VIELEN VIELEN DANK schonmal!!!!!!
unit LANFS_KERNAL;
interface uses SysUtils, Classes, IdBaseComponent,IdStreamVCL, IdComponent, IdTCPServer,IdTCPConnection,IdTCPClient,IdContext; type TRECEIVEDDATA = procedure(Sender: TObject; MemStream: TMemoryStream) of Object; TLANFS_KERNAL = class fReceivedData: TRECEIVEDDATA; public procedure ReceiveStream(Acontext:TidContext); procedure Start(port:integer); procedure Stop(); procedure SendStream(Stream: TFilestream;Host:String); property OnReceivedData: TRECEIVEDDATA read fReceivedData write fReceivedData; end; var LANFS_SYSTEM :TLANFS_KERNAL; TCPClient1: TIdTCPClient; TCPServer1: TIdTCPServer; implementation procedure TLANFS_KERNAL.Start(port:integer); { +Aktiviert TCPClient und TCPServer +Sollte immer am Start des Programms aufgerufen werden. +zuletzt editiert: 24.05.06 } begin TCPClient1:= TIdTCPClient.Create; TCPClient1.Port:=Port; with TCPClient1 do begin ReadTimeout:=5000; ConnectTimeout:=5000; end; TCPServer1:= TIdTCPServer.Create; TCPServer1.OnExecute := LANFS_SYSTEM.ReceiveStream; with TCPServer1 do begin MaxConnections:=1; DefaultPort:=Port; Active:=True; end; end; procedure TLANFS_KERNAL.Stop(); {Stopt Server und Client, gibt Speicher frei. zuletzt editiert: 24.06.05} begin TCPClient1.Free; TCPServer1.Active:=False; TCPServer1.Free; end; procedure TLANFS_KERNAL.SendStream(Stream: TFilestream;Host:String); { +Versendet vom TCPClient an TCPServer einen Filestream +Dieser wird als Parameter übergeben, und muss vorher erzeugt worden sein. +zuletzt editiert: 24.05.06 } var IndyStream: TidStreamVCL; begin TCPClient1.Host:=Host; try IndyStream := TidStreamVCL.Create(Stream); try { Senden } with TCPClient1 do begin Connect; try Socket.Write(IndyStream, 0, true); finally Disconnect; end; end; finally FreeAndNil(IndyStream); end; finally FreeAndNil(Stream); end; end; procedure TLANFS_KERNAL.ReceiveStream(Acontext:TidContext); { +Empfängt vom TCPClient an TCPServer einen Filestream +zuletzt editiert: 25.05.06 } var FSTream: TMemoryStream; SizeOfIncomingStream: Integer; IDS: TidStreamVCL; begin FStream := TMemoryStream.Create; // FStream := TFileStream.Create('C:\test.tmp', fmCreate); try IDS := TidStreamVCL.Create(FStream); try { Empfangen } with AContext.connection do begin try SizeOfIncomingStream := Socket.ReadInteger; Socket.ReadStream(IDS, SizeOfIncomingStream); finally Disconnect; end; end; { Damit der Inhalt von IDS in FStream übertragen wird } IDS.VCLStream.Position := 0; finally FreeAndNil(IDS); end; finally {Event losschicken} if Assigned(fReceivedData) then fReceivedData(Self, FStream); FreeAndNil(FStream); end; end; end. //edit ich den Fehler, den xaromz gefunden hat, mal fix korrigiert, damit er keine Verwirrungen mehr macht! THX to xaromz |
Re: eigenes Event programmieren?
Hallo,
Du zerstörst den Stream (Zeile 130) und schickst dann den nil-Pointer an Deine Event-Methode. Vielleicht ist das das Problem. Ansonsten wäre es hilfreich, zu wissen, welche Exception kommt. Gruß xaromz |
Re: eigenes Event programmieren?
Uuuuuppps...okay, sau dummer Fehler, gebe ich zu....
Allerdings ist das nicht der Fehler den ich meine... Es kommt folgende Exception: EAccessViolation, und zwar genau dann wenn ich im Hauptprogramm dem neuen Event eine Procedur zuweisen will. Die Hauptprocedur sieht so aus:
Delphi-Quellcode:
unit Unit2;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdTCPServer; type TForm2 = class(TForm) [...] private { Private-Deklarationen } public procedure test(Sender: TObject; MStream: TMemoryStream); { Public-Deklarationen } end; var Form2: TForm2; implementation uses LANFS_KERNAL; {$R *.dfm} procedure TForm2.test(Sender: TObject; MStream: TMemoryStream); begin MStream.SaveToFile('C:\neuertest.tmp'); end; procedure TForm2.FormCreate(Sender: TObject); begin lanfs_system.OnReceivedData:= Form2.test; //hier passiert der Fehler!!! end; procedure TForm2.Button1Click(Sender: TObject); var stream:TFilestream; begin stream:=TFileStream.Create(edit1.text, fmOpenRead); lanfs_system.SendStream(stream,edit2.text); end; [...] end. |
Re: eigenes Event programmieren?
Zitat:
Gruß Hawkeye |
Re: eigenes Event programmieren?
Zitat:
Jedenfalls kann ich auf lanfs_system zugreifen, *g* oder was meinst du genau mit Instanz ;) Ich muss doch jedenfalls kein .create mehr aufrufen?! |
Re: eigenes Event programmieren?
Das ist nicht ganz richtig, eine Unit wird nicht "erzeugt". Das was du meinst, gilt nur für Formulare. In Beitrag #3 hast du TLANFS_KERNAL als "Class" vereinbart, es handelt sich also nicht um ein Formular. In diesem Falls mußt du das Objekt erzeugen und auch wieder freigeben.
Gruß Hawkeye |
Re: eigenes Event programmieren?
desweiteren solltest du folgende Zeile abändern von:
Delphi-Quellcode:
nach
lanfs_system.OnReceivedData:= Form2.test;
Delphi-Quellcode:
lanfs_system.OnReceivedData:= test;
|
Re: eigenes Event programmieren?
Danke für die kleine Nachhilfekunde in sachen Classen und Units!
Was ich dann nur nicht so ganz verstehe... Im LANFS_KERNAL hab ich doch folgendes deklariert unter VAR: var LANFS_SYSTEM :TLANFS_KERNAL; auf Lanfs_system kann ich ohne create zugreifen, also auch auf die Proceduren in lanfs_system. Das OnReceiveData ist doch genau da deklariert wo auch die Proceduren deklariert sind, die in lanfs_system funktionieren....
Delphi-Quellcode:
Warum kann ich dann also auf die Proceduren Start, ReceiveStream, Stop SendStream zugreifen aber nicht auf das OnReceived Data?
unit LANFS_KERNAL;
interface uses [...] type TRECEIVEDDATA = procedure(Sender: TObject; MemStream: TMemoryStream) of Object; TLANFS_KERNAL = class fReceivedData: TRECEIVEDDATA; public procedure ReceiveStream(Acontext:TidContext); procedure Start(port:integer); procedure Stop(); procedure SendStream(Stream: TFilestream;Host:String); property OnReceivedData: TRECEIVEDDATA read fReceivedData write fReceivedData; //nämlich genau hier end; var LANFS_SYSTEM :TLANFS_KERNAL; TCPClient1: TIdTCPClient; TCPServer1: TIdTCPServer; Würdest du eigentlich generell sagen, dass die Unit so ziemlich unstrukuriert etc ist? //edit: Ich meine wäre es vielleicht sinnvoller einfahch alles in eine Klasse zu schreiben ohne Unit? *keine ahnung hab* |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:26 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