Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Meldungen aus einer Unit an ein Formular senden (https://www.delphipraxis.net/178356-meldungen-aus-einer-unit-ein-formular-senden.html)

LarsSchwencke 3. Jan 2014 14:58

Meldungen aus einer Unit an ein Formular senden
 
Hallo,

weiß jemand wie ich Informatione aus einer Unit(ohne Formular) an eine andere Unit mit Formular übergeben kann.
Ich habe ein VCL-Formularanwendung geschieben in der es ein Memofeld gibt.
Diese Formularanwendung ruft eine Unit(hier Unit2 genannt) auf, die Meldungen in das Memofeld der Formularanwendung schreiben soll.
Die Unit2 möchte ich in unterschiedlichen Programmen immer wieder verwenden können.
Wie kann ich dies Realisieren ohne die Formularanwendung unter uses der Unit2 anzugeben.

Würde mich über jeden Lösungsvorschlag sehr freuen.
MfG
Lars

Dalai 3. Jan 2014 15:02

AW: Meldungen aus einer Unit an ein Formular senden
 
Du brauchst irgendeinen gemeinsamen Nenner. Ich würde das so machen: Unit2 beinhaltet Funktionen/Methoden, die StringListen (entweder TStrings oder TStringList) als Parameter bekommen. Die Formular-Unit übergibt dann die Eigenschaft TMemo.Lines (vom Typ TStrings) an die Funktionen/Methoden von Unit2.

MfG Dalai

DeddyH 3. Jan 2014 15:08

AW: Meldungen aus einer Unit an ein Formular senden
 
Oder Unit2 enthält eine schnuckelige kleine Klasse, der man die zu befüllenden TStrings als Property zuweist.

Perlsau 3. Jan 2014 15:22

AW: Meldungen aus einer Unit an ein Formular senden
 
@ LarsSchwencke:

Das Ereignis, das das Schreiben von Text in dein Memo auslösen soll, stammt ja vermutlich aus deiner Formular-Unit. Da wäre es irgendwie mit der Kirche ums Dorf und durch die Brust ins Auge geschossen, hier den Umweg über eine zweite Unit zu gehen. Wenn es einfach nur darum geht, eine bestimmte Methode, die Text in ein Memo schreibt, in anderen Anwendungen wiederverwenden zu können, würde ich das erstmal grundsätzlich nicht über eine zweite Unit machen, sondern mir die Methode einfach irgendwo abspeichern. Ich mache das mit meiner Codeverwaltung, die ich im Rahmen einer kompletten Projektverwaltung etnwickelt hatte. Du kannst z.B. Warnecke's Code-Orakel verwenden, falls er sein Programm noch als Freeware anbietet. Oder du schaffst dir ein Verzeichnis, wo du Methoden, die du ständig wieder benötigst oder zu benötigen glaubst, als Textdateien abspeicherst.

Natürlich gibt es auch Fälle, in denen es sinnvoll ist, eine Methode in einem Formular von einer anderen Unit/einem anderen Formular aus anzustoßen, z.B. wenn im Hauptformular ich auf das Verschieben des Datensatz-Zeigers einer Tabelle (AfterScroll) aus einem Datenmodul reagieren möchte oder wenn ich z.B. in einem eigenen Thread in einer anderen Unit meine Postfächer abrufe, dem zuständigen Formular mitzuteilen, wenn eine neue Email eingegangen ist usw. In diesen Fällen erzeugt man Ereignisse selbst und reagiert darauf in der entsprechenden Unit.

ngott2 3. Jan 2014 15:29

AW: Meldungen aus einer Unit an ein Formular senden
 
Wenn ich das richtig verstehe!
Dann kannst einfach eine Funktion in der Unit2 schreiben die eine String liste zurück gibt.

Beispiel
Code:
MeinMemo.text := ObjectFromUnit2.DoSomethingfunction;

Wenn ich dein Problem falsch verstanden habe, dann sorry.

p80286 3. Jan 2014 15:57

AW: Meldungen aus einer Unit an ein Formular senden
 
Zitat:

Zitat von ngott2 (Beitrag 1241954)
Wenn ich das richtig verstehe!
Dann kannst einfach eine Funktion in der Unit2 schreiben die eine String liste zurück gibt.

Beispiel
Code:
MeinMemo.text := ObjectFromUnit2.DoSomethingfunction;

Wenn ich dein Problem falsch verstanden habe, dann sorry.

Das ist nicht so optimal. Wenn Du (String)Listen befüllen willst, dann solltest Du diese an eine prozedure übergeben (siehe #2) und nicht durch eine Funktion erstellen lassen. Du könntest Dir ein Speicherleck einhandeln.

Gruß
K-H

LarsSchwencke 8. Jan 2014 13:57

AW: Meldungen aus einer Unit an ein Formular senden
 
Hallo,

vielen Dank für die schnellen Antworten.
Wenn ich es mit einer StringList mache, dann muß ich in der Unit1
über eine Pollingfunktion immer nachschauen ob neue Meldungen in der StringList stehen,
da ich ja nicht weiß wann die Unit2 neue Mitteilungen in die StringList schreibt, oder?

Gibt es eine Möglichkeit das Pollen zu vermeiden.

MfG
Lars

DeddyH 8. Jan 2014 14:05

AW: Meldungen aus einer Unit an ein Formular senden
 
Wie gesagt: ich würde mir eine kleine Klasse schreiben, die die Mitteilungen intern in einer Stringliste verwaltet und über ein Event samt zugehöriger Property verfügt, das bei Hinzufügen einer Mitteilung gefeuert wird.

Der schöne Günther 8. Jan 2014 14:07

AW: Meldungen aus einer Unit an ein Formular senden
 
Zitat:

Zitat von p80286 (Beitrag 1241962)
Wenn Du (String)Listen befüllen willst, dann solltest Du diese an eine prozedure übergeben (siehe #2) und nicht durch eine Funktion erstellen lassen. Du könntest Dir ein Speicherleck einhandeln.

Verstehe ich nicht. Wie das denn? Ich möchte bitte eine StringList haben. Entweder die Funktion gibt mir eine, oder sie gibt mir keine. Wenn ich eine haben wollte, ist es auch meine Verantwortung, die Liste später ordentlich in den Müll zu tun.

baumina 8. Jan 2014 14:09

AW: Meldungen aus einer Unit an ein Formular senden
 
Wie wärs denn so?

In der Unit ohne Formular:
Delphi-Quellcode:
procedure SchreibeInMemo(MyStrings : TStrings);
begin
  MyStrings.Add('noch ne Zeile');
end;
Und der Aufruf in der Unit mit Formular wäre dann so:
Delphi-Quellcode:
  SchreibeInMemo(memo1.Lines);

DeddyH 8. Jan 2014 14:15

AW: Meldungen aus einer Unit an ein Formular senden
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1242683)
Zitat:

Zitat von p80286 (Beitrag 1241962)
Wenn Du (String)Listen befüllen willst, dann solltest Du diese an eine prozedure übergeben (siehe #2) und nicht durch eine Funktion erstellen lassen. Du könntest Dir ein Speicherleck einhandeln.

Verstehe ich nicht. Wie das denn? Ich möchte bitte eine StringList haben. Entweder die Funktion gibt mir eine, oder sie gibt mir keine. Wenn ich eine haben wollte, ist es auch meine Verantwortung, die Liste später ordentlich in den Müll zu tun.

Wahrscheinlich meint er so etwas: http://www.detlef-heibing.de/program...rueckgabe.html

Hobby-Programmierer 8. Jan 2014 14:18

AW: Meldungen aus einer Unit an ein Formular senden
 
Zitat:

Zitat von DeddyH (Beitrag 1242681)
Wie gesagt: ich würde mir eine kleine Klasse schreiben, die die Mitteilungen intern in einer Stringliste verwaltet und über ein Event samt zugehöriger Property verfügt, das bei Hinzufügen einer Mitteilung gefeuert wird.

Hallo DeddyH,
könntest du vielleicht kurz ein Code-Beispiel dazu schreiben. Ich sitze vor einem ähnlichen Problem und mich würde interessieren wie man dies universal handhaben könnte.

Danke und Lg

DeddyH 8. Jan 2014 14:38

AW: Meldungen aus einer Unit an ein Formular senden
 
Ganz minimale Klasse ohne eigene Stringliste:
Delphi-Quellcode:
unit MsgManager;

interface

uses Classes;

type
  TNewMessageEvent = procedure(Sender: TObject; const NewMsg: string) of object;

  TMessageManager = class
  private
    FOnNewMessage: TNewMessageEvent;
  public
    procedure AddMessage(const NewMessage: string);
    property OnNewMessage: TNewMessageEvent read FOnNewMessage write FOnNewMessage;
  end;

implementation

{ TMessageManager }

procedure TMessageManager.AddMessage(const NewMessage: string);
begin
  if Assigned(FOnNewMessage) then
    FOnNewMessage(self, NewMessage);
end;

end.
Diese Unit wird nun in beiden Formularunits eingebunden. Form1 erstellt die Instanz im FormCreate und weist einen Eventhandler zu:
Delphi-Quellcode:
type
  TfrmMitMemo = class(TForm)
    mmoMessages: TMemo;
    btnShowInput: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnShowInputClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
    FManager: TMessageManager;
    procedure AddMessage(Sender: TObject; const NewMsg: string);
  public
    { Public-Deklarationen }
  end;

...

procedure TfrmMitMemo.AddMessage(Sender: TObject; const NewMsg: string);
begin
  mmoMessages.Lines.Add(NewMsg);
end;

procedure TfrmMitMemo.FormCreate(Sender: TObject);
begin
  FManager := TMessageManager.Create;
  FManager.OnNewMessage := AddMessage;
end;
Die andere Formularunit verfügt über eine Property vom Typ TMessageManager, der man dann einfach diese Instanz zuweist:
Delphi-Quellcode:
type
  TfrmInput = class(TForm)
    edtMessage: TEdit;
    btnAdd: TButton;
    procedure btnAddClick(Sender: TObject);
  private
    { Private-Deklarationen }
    FManager: TMessageManager;
  public
    { Public-Deklarationen }
    property Manager: TMessageManager read FManager write FManager;
  end;
Delphi-Quellcode:
procedure TfrmMitMemo.btnShowInputClick(Sender: TObject);
begin
  frmInput.Manager := FManager;
  frmInput.Show;
end;
Der Code innerhalb des Innput-Formulars ist dann recht überschaubar:
Delphi-Quellcode:
procedure TfrmInput.btnAddClick(Sender: TObject);
begin
  if Assigned(FManager) then
    FManager.AddMessage(edtMessage.Text);
end;
Nun noch bei Freigabe des Memo-Formulars ordentlich aufräumen:
Delphi-Quellcode:
procedure TfrmMitMemo.FormDestroy(Sender: TObject);
begin
  FManager.Free;
end;
und fertig ist die Laube. Man muss lediglich sicherstellen, dass man anschließend nicht mehr aus dem Input-Formular auf diesen Manager zugreift, da wir zugegebenermaen dort nun einen dangling pointer lauern haben.

Hobby-Programmierer 8. Jan 2014 15:41

AW: Meldungen aus einer Unit an ein Formular senden
 
Oi, des ging ja schnell. Vielen Dank, werde mir das mal zu Gemüte führen.

LG

LarsSchwencke 10. Jan 2014 13:18

AW: Meldungen aus einer Unit an ein Formular senden
 
Hallo DeddyH,

klasse, das war genau das was ich brauchte.
Da ich aber nur ein Formular und eine Unit ohne Formulat habe
mußte ich es nur etwas anpassen aber jetzt funktioniert es
super.

Danke.

p80286 10. Jan 2014 13:29

AW: Meldungen aus einer Unit an ein Formular senden
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1242683)
Verstehe ich nicht. Wie das denn? Ich möchte bitte eine StringList haben. Entweder die Funktion gibt mir eine, oder sie gibt mir keine. Wenn ich eine haben wollte, ist es auch meine Verantwortung, die Liste später ordentlich in den Müll zu tun.

Kann ich gut nachvollziehen, so hab ich es auch gesehen, bis ich prompt mal das Aufräumen "vergessen" habe, seitdem "wo es (die Liste erstellt wird) wird es auch wieder entsorgt". Hier gab es auch irgendwann mal eine heftige Diskussion darüber, aber ich finde Sie z.Zt. nicht wieder.

Gruß
K-H

DeddyH 10. Jan 2014 13:40

AW: Meldungen aus einer Unit an ein Formular senden
 
Die hier? http://www.delphipraxis.net/104839-w...ekte-frei.html

Sigi55 18. Apr 2015 19:09

AW: Meldungen aus einer Unit an ein Formular senden
 
Hallo DeddyH,

Superteil, löppelt prima, nur im Gegensatz zum Lars bekomm ich's nicht gebacken
den Messagemanager in eine unit OHNE Formular einzubinden. :-(

Zitat:

Zitat von LarsSchwencke (Beitrag 1243024)
Hallo DeddyH,

klasse, das war genau das was ich brauchte.
Da ich aber nur ein Formular und eine Unit ohne Formulat habe
mußte ich es nur etwas anpassen aber jetzt funktioniert es
super.

Danke.


Delphi-Quellcode:
type
  TfrmInput = class(TForm)
    edtMessage: TEdit;
    btnAdd: TButton;
    procedure btnAddClick(Sender: TObject);
  private
    { Private-Deklarationen }
    FManager: TMessageManager;
  public
    { Public-Deklarationen }
    property Manager: TMessageManager read FManager write FManager;
  end;
Kannst Du (oder jemand anders :-)) mir das bitte anpassen ??
Ich raff das nicht ...

In einem Datamodul hab ichs zum Laufen bekommen :-)
Delphi-Quellcode:
unit Unit4;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, MsgManager, ExtCtrls;

type
  TDataModule4 = class(TDataModule)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
  private
    FManager: TMessageManager;
    { Private declarations }
  public
    { Public declarations }
    property Manager: TMessageManager read FManager write FManager;
  end;

  procedure test;

var
  DataModule4: TDataModule4;

implementation

{$R *.dfm}

procedure test;
begin
 if Assigned(DataModule4.FManager) then
    DataModule4.FManager.AddMessage('hallo test aus datamod');
end;

procedure TDataModule4.Timer1Timer(Sender: TObject);
begin
 if Assigned(FManager) then
  FManager.AddMessage('hallo timer aus datamod');
end;

end.

Vielen Dank schomal ...
Gruß

Sigi

DeddyH 18. Apr 2015 22:42

AW: Meldungen aus einer Unit an ein Formular senden
 
Hilft Dir dieses Beispiel weiter? Die Klasse TMsgManager steht in einer eigenen Unit und ist unverändert, das Formular hat wieder ein Memo, erzeugt eine Instanz des Managers und weist ihr den EventHandler zu, innerhalb dessen ins Memo geschrieben wird, alles genau wie oben gezeigt. Neu ist die 2. Unit, die kein Formular besitzt, sondern nur eine Klasse deklariert.
Delphi-Quellcode:
unit MessageSend;

interface

uses SysUtils, MsgManager;

type
  TMessageGenerator = class
  private
    FManager: TMessageManager;
  public
    procedure CountTo1000;
    property Manager: TMessageManager read FManager write FManager;
  end;

implementation

{ TMessageGenerator }

procedure TMessageGenerator.CountTo1000;
var
  Number: integer;
begin
  for Number := 1 to 1000 do
    if Number mod 10 = 0 then
      if Assigned(Manager) then
        Manager.AddMessage(IntToStr(Number));
end;

end.
Der ButtonClick des Formulars sieht dann so aus:
Delphi-Quellcode:
procedure TfrmMitMemo.Button1Click(Sender: TObject);
var
  Generator: TMessageGenerator;
begin
  Generator := TMessageGenerator.Create;
  try
    Generator.Manager := FManager;
    Generator.CountTo1000;
  finally
    Generator.Free;
  end;
end;
Gedacht habe ich mir das Ganze letztes Jahr so: der "Konsument" der Nachrichten erzeugt den Manager und weist ihm einen OnNewMessage-Handler zu. Die benachrichtigende Klasse besitzt eine Property vom Typ des Managers, erstellt aber keine eigene Instanz, sondern bekommt diese vom Konsumenten zugewiesen. Sobald sie etwas mitzuteilen hat, ruft sie einfach die AddMessage-Methode ihres zugewiesenen Managers (so vorhanden) auf.

Sigi55 19. Apr 2015 07:00

AW: Meldungen aus einer Unit an ein Formular senden
 
Moin Detlef,

perfekt, super, löppelt wunderbar ... Vielen Dank :hi::hi:

Zitat:

Zitat von DeddyH (Beitrag 1298370)
Gedacht habe ich mir das Ganze letztes Jahr so: der "Konsument" der Nachrichten erzeugt den Manager und weist ihm einen OnNewMessage-Handler zu ...

Genau mein Ansatz, bin gerade dabei möglichst alle hardcodierten Abhängigkeiten von unit zu unit auszumerzen ...

Zitat:

Zitat von DeddyH
Man muss lediglich sicherstellen, dass man anschließend nicht mehr aus dem Input-Formular auf diesen Manager zugreift, da wir zugegebenermaen dort nun einen dangling pointer lauern haben.

Das hab ich nicht verstanden, was soll das bedeuten ?

Und, Da kommen auch gleich weitere Ideen auf: :-)
Ich habe meistens mit Datenumschaufeln oder Prüfroutinen zu tun die über etliche Datensätze iterieren und da verwende ich gern eine Progressbar. Kann man das so umbauen oder erweitern das der Fortschritt in unit2 auf der Hauptform angezeigt wird ?

Ich denke, das Thema ist noch nicht durch und sollte auch als Beispiel in die Codelib.

Vielen Dank schonmal und Gruß

Sigi

DeddyH 19. Apr 2015 09:22

AW: Meldungen aus einer Unit an ein Formular senden
 
Das mit dem Dangling Pointer bedeutet, dass wir bei dieser Vorgehensweise ja 2 Verweise auf dieselbe Instanz haben. Wird das Formular, das diese anlegt, zerstört, gibt es sie wieder frei, somit zeigt der Verweis in der sendensen Klasse dann ins Leere.

Sigi55 19. Apr 2015 09:43

AW: Meldungen aus einer Unit an ein Formular senden
 
Moin nochmal ...

Zitat:

Zitat von DeddyH (Beitrag 1298380)
Das mit dem Dangling Pointer bedeutet, dass wir bei dieser Vorgehensweise ja 2 Verweise auf dieselbe Instanz haben. Wird das Formular, das diese anlegt, zerstört, gibt es sie wieder frei, somit zeigt der Verweis in der sendensen Klasse dann ins Leere.

Ok, verstanden, aber ich wollt eh nix kaputt machen :-)

Und mit der Progressbar ?
Ich hab mir überlegt, ich könnte das ja so machen wie bei z.B. einer Stringliste mit "name" and "value" ('Hans=12'), also quasi als Parameter übergeben und dann in der Hauptform ausgeben oder auch ignorieren, oder ist das blö.. ?

Gruß

Sigi

Sir Rufo 19. Apr 2015 10:09

AW: Meldungen aus einer Unit an ein Formular senden
 
Eigentlich bringt doch diese MessageManager-Klasse keinen Vorteil gegenüber dem einfachen Zuweisen eines Callbacks/einer Event-Methode. Gut es fügt noch ein wenig mehr Code hinzu - macht es also aufwendiger/komplizierter ohne einen wirklichen Mehrwert zu schaffen.

Sigi55 19. Apr 2015 10:50

AW: Meldungen aus einer Unit an ein Formular senden
 
Moin Sir,

Zitat:

Zitat von Sir Rufo (Beitrag 1298386)
Eigentlich bringt doch diese MessageManager-Klasse keinen Vorteil gegenüber dem einfachen Zuweisen eines Callbacks/einer Event-Methode. Gut es fügt noch ein wenig mehr Code hinzu - macht es also aufwendiger/komplizierter ohne einen wirklichen Mehrwert zu schaffen.

.. also, für mich (NICHT OOPler, Anfang 80er=BASIC, 90er=CLIPPER(dBase), 20Jahre Pause, seit 2 Jahren DELPHI (TopDown Progging [prozedural], so mal als Background :duck:) ist das einfach und verständlich, oder geht's noch einfacher ?

Mir ist wichtig, die festverdrahteten unit2unit Verbindungen aufzulösen ..

Gruß

Sigi

Sir Rufo 19. Apr 2015 11:03

AW: Meldungen aus einer Unit an ein Formular senden
 
Nehmen wir mal das Beispiel von oben und designen das mal ohne den MessageManager:
Delphi-Quellcode:
type
  TfrmMitMemo = class(TForm)
    mmoMessages: TMemo;
    btnShowInput: TButton;
    procedure btnShowInputClick(Sender: TObject);
  private
    { Private-Deklarationen }
    procedure AddMessage(Sender: TObject; const NewMsg: string);
  public
    { Public-Deklarationen }
  end;

...

procedure TfrmMitMemo.AddMessage(Sender: TObject; const NewMsg: string);
begin
  mmoMessages.Lines.Add(NewMsg);
end;
Delphi-Quellcode:
type
  TfrmInput = class(TForm)
    edtMessage: TEdit;
    btnAdd: TButton;
    procedure btnAddClick(Sender: TObject);
  private
    { Private-Deklarationen }
    FNewMessageCallback: TNewMessageEvent;
  public
    { Public-Deklarationen }
    property NewMessageCallback: TNewMessageEvent read FNewMessageCallback write FNewMessageCallback;
  end;
Delphi-Quellcode:
procedure TfrmMitMemo.btnShowInputClick(Sender: TObject);
begin
  frmInput.NewMessageCallback := AddMessage;
  frmInput.Show;
end;
Delphi-Quellcode:
procedure TfrmInput.btnAddClick(Sender: TObject);
begin
  if Assigned(FNewMessageCallback) then
    FNewMessageCallback(Self, edtMessage.Text);
end;
Das macht jetzt exakt das Gleiche ohne eine weitere Instanz da irgendwo noch reinzubasteln.

Sigi55 19. Apr 2015 12:44

AW: Meldungen aus einer Unit an ein Formular senden
 
Moin Sir;

Zitat:

Zitat von Sir Rufo (Beitrag 1298390)
... Das macht jetzt exakt das Gleiche ohne eine weitere Instanz da irgendwo noch reinzubasteln.

Yes, Sir, hab ich getestet, macht es, prima :-) Schlanker ist immer gut :-)


Nur ...
Delphi-Quellcode:
procedure TfrmMitMemo.FormCreate(Sender: TObject);
begin
  TMessageManager.Create; // OK, geht
end;

procedure TfrmMitMemo.FormDestroy(Sender: TObject);
begin
  //TMessageManager.Free; // Fehler ??
end;
Hmm??

Und wie mach ich das z.B. mit der Progressbar ?

Danke und Tschüss

Sigi

Sigi55 19. Apr 2015 17:28

AW: Meldungen aus einer Unit an ein Formular senden
 
Hi,

also, habs nach längerem Hinsehen und vergleichen und try & error selbst
rausgefunden :duck: :

Ich muss nix 'createn', also auch nix zerstören :-)

Hat sich erledigt, Danke.

Was mir noch durch den Kopf geht, ist:

Delphi-Quellcode:
procedure TfrmMitMemo.Button3Click(Sender: TObject);
var
  Generator: TMessageGenerator;
  s : string;
begin
  s := 'test2';
  Generator := TMessageGenerator.Create;
  try
    Generator.NewMessageCallback := AddMessage;
    Generator.OutPut(s);
  finally
    Generator.Free;
  end;
end;
Muss ich dieses Konstrukt immer anwenden wenn ich eine Procedure/Function aus
einer formlosen unit aufrufe, oder kann man das vereinfachen ??

Vielen Dank für eure Nachhilfe :-)

Gruß

Sigi


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:28 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