AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

eigenes Event programmieren?

Ein Thema von alleinherrscher · begonnen am 25. Mai 2006 · letzter Beitrag vom 25. Mai 2006
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#1

eigenes Event programmieren?

  Alt 25. Mai 2006, 11:57
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.
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#2

Re: eigenes Event programmieren?

  Alt 25. Mai 2006, 12:03
ein Event wird wie folgt defniert:
Delphi-Quellcode:
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;
Anstelle eines eigenen EventTypes kannst du natürlich auch bereits vorhandene wie TNotifyEvent etc. nutzen wenn dir diese von den Parametern her zusagen.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#3

Re: eigenes Event programmieren?

  Alt 25. Mai 2006, 12:26
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...)

lanfs_system.OnReceivedData:= Form2.test; Das ganze sieht jetzt so aus:

Delphi-Quellcode:
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.
Liebe Grüße und VIELEN VIELEN DANK schonmal!!!!!!

//edit ich den Fehler, den xaromz gefunden hat, mal fix korrigiert, damit er keine Verwirrungen mehr macht! THX to xaromz
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#4

Re: eigenes Event programmieren?

  Alt 25. Mai 2006, 12:43
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
  Mit Zitat antworten Zitat
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#5

Re: eigenes Event programmieren?

  Alt 25. Mai 2006, 12:50
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.
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#6

Re: eigenes Event programmieren?

  Alt 25. Mai 2006, 12:58
Zitat von alleinherrscher:
Uuuuuppps...okay, sau dummer Fehler, gebe ich zu....
Wann erzeugst du die Instanz von TLANFS_KERNAL, der du in FormCreate etwas zuweist?

Gruß Hawkeye
  Mit Zitat antworten Zitat
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#7

Re: eigenes Event programmieren?

  Alt 25. Mai 2006, 13:07
Zitat von Hawkeye219:
Wann erzeugst du die Instanz von TLANFS_KERNAL, der du in FormCreate etwas zuweist?

Gruß Hawkeye
Wenn ich doch ne Unit habe die ich unter USES deklariere, wird die automatisch beim start erzeugt oder?
Jedenfalls kann ich auf lanfs_system zugreifen, *g* oder was meinst du genau mit Instanz

Ich muss doch jedenfalls kein .create mehr aufrufen?!
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#8

Re: eigenes Event programmieren?

  Alt 25. Mai 2006, 13:11
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
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#9

Re: eigenes Event programmieren?

  Alt 25. Mai 2006, 13:15
desweiteren solltest du folgende Zeile abändern von:
lanfs_system.OnReceivedData:= Form2.test; nach
lanfs_system.OnReceivedData:= test;
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#10

Re: eigenes Event programmieren?

  Alt 25. Mai 2006, 13:22
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:
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;
Warum kann ich dann also auf die Proceduren Start, ReceiveStream, Stop SendStream zugreifen aber nicht auf das OnReceived Data?

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*
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:17 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz