AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Messages zwischen Objekten austauschen?
Thema durchsuchen
Ansicht
Themen-Optionen

Messages zwischen Objekten austauschen?

Ein Thema von Zottel · begonnen am 15. Sep 2006 · letzter Beitrag vom 16. Sep 2006
Antwort Antwort
Zottel
(Gast)

n/a Beiträge
 
#1

Messages zwischen Objekten austauschen?

  Alt 15. Sep 2006, 20:22
Moin zusammen,
wie würdet Ihr folgendes problem lösen:

Ich habe eine Form in meinen Programm. In der werden Objekte erzeugt (TPersistent), die aber kein Fensterhandel haben, und somit keine nachrichten über PostMessage oder SendMessage empfangen können. Auch WMCopyData geht net

Wie bekomme ich es hin, das ich eine Nachricht an diese Objekte sende, und die je nach belieben diese Nachricht verarbeiten können.
Allerdings können auch mehrere Objekte diese Nachrichten empfangen sollen.

Die schnellste methode wäre, das ich bei jeder nachricht die Liste mit den Objekten durchgehe und in jedem Objekt eine entsprechende Procedure aufrufe mit den Nachrichten-Parametern. Aber das scheint mir bei einigen hundert Objekten zu umständlich zu sein und auch zu lange zu dauern.

Von den Objekten kann ich ja jederzeit eine Nachricht an das Formular schicken. Das kann ich ja mit Postmessage machen. Aber umgekehrt?
Oder habe ich da jetzt einen denkfehler?

vielen dank schonmal

grüße
Zottel
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#2

Re: Messages zwischen Objekten austauschen?

  Alt 15. Sep 2006, 20:32
wieso sollen die keine Messages empfangen können ? das geht schon mit TObject.

Delphi-Quellcode:

type
  TTest = class(TObject)
    procedure WMPaint(var Msg: TMessage); message wm_Paint;
  end;

procedure TTest.WMPaint(var Msg: TMessage);
begin
  ShowMessage('Test');
end;

var
  Msg: TMessage;
begin
  Msg.Message := wm_Paint;
  Obj := TTest.Create;
  Obj.Dispatch(Msg);
  Obj.Free;
end;
Gruß Hagen
  Mit Zitat antworten Zitat
delphirocks

Registriert seit: 14. Aug 2004
Ort: Salzburg
64 Beiträge
 
#3

Re: Messages zwischen Objekten austauschen?

  Alt 15. Sep 2006, 20:36
Hallo, damit (Multicast-Events) sollte es gehen.
  Mit Zitat antworten Zitat
Zottel
(Gast)

n/a Beiträge
 
#4

Re: Messages zwischen Objekten austauschen?

  Alt 15. Sep 2006, 22:03
Danke.

@negaH
Die funktion kannte ich noch nicht. setzt aber vorraus, das man dann trotzdem alle Objekte einzeln durchgehen muss, wenn in der Anwendung ein ereignis auftritt. Wenn man das ganze mit Broadcast machen könnte, wäre das genial.....

@delphirocks
Wäre ne möglichkeit, die Objekte, die man durchgehen muss einzuschränken. danke dir erstmal
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#5

Re: Messages zwischen Objekten austauschen?

  Alt 16. Sep 2006, 01:12
Korrekt, .Dispatch() leitet die Message erstmal NUR an das eine Objekt. Aber das ist ja auch kein Problem, denn so ist es konzeptonell vorgesehen. Denn je nachdem WAS du daraus machst kannst du es so implementieren wie es bei Fenster Handles möglich ist.
Hast du zb. nur ein TForm und sendest dem einen Broadcast dann empfängt das auch nur 1 Fenster, nämlich das TForm.

Ergo: willst DU eine Message broadcasten (hm also einfach verteilen) und DU hast die Struktur der Objekt und deren Verwaltung kontrolliert dann bist auch du dafür verantwortlich.

Dazu hast du folgende Möglichkeiten:

1.) das Root Objekt bekommt eine Message an eine Funktion die diese Message verteilt indem es alle .Dispatch() Methoden der verlinkten Objekte aufruft

2.) ein Objekt das NICHT auf eine Message reagiert, also keine dynamsiche Methode enthält die als message Integer_Konstant, deklariert wurde, wird in .Dispatch() die Methode .DefaultHandler() aufrufen. Überschreibst du diese Methode so bekommst du alle Nachrichten die das Objekt selber nicht abarbeitet. In .DefaultHandler() kanst du solche Nachrichten weiter verteilen an verlinkte Objekte.

Message Methoden sind ein grundsätzliches Konzept das auf dynamischen Methoden basiert. Wenn du zb. nicht mit dem Paramter Msg: TMessage arbeiten möchtest dann kannst du sogar deine eigene .Dispatch() Methode coden die eben mit allen möglichen Params arbeiten kann. Eine dynamische Methode in enem Objekt ist im Grunde eine Methode deren Addresse in der DMT=Dynamic Method Table unter einem Index vom Typ Word gespeichert wird. .Dispatch nimmt nun unseren Message-Code, zb. wm_Paint, als Index in diese DMT einer Klasse. Wurde eine Methode in diesem objekt als dynamic wm_Paint; deklariert so steht in der DMT am Index wm_Paint ein Zeiger auf diese dynamische Methode, so einfach. Der Bezeichner "message wm_Paint" ist also gleichzusetzen mit "dynamic wm_Paint" eben nur mit explizerter Angabe der Slotnummer in der DMT. Da ja nun im Wertebereich WORD 2^16 =65535 mögliche Einträge drinnen sein können kann eine solche DMT sehr viel Speicherplatz wegnehmen, wenn man diese DMT statisch konstruiert. Um das zu vermeiden besteht die DMT aus Einträgen der Form

Delphi-Quellcode:

  DMT_Count: Word;
  DMT_Table: array[DMT_Count] of packed record
              SlotID: Word; // ID der Methode, bei message wm_Paint also SlotID = wm_Paint
              MethodAddress: Pointer;
             end;
Dh. zu jeder Methode in der DMT wird deren SlotID gespeichert. Nur die Klasse die diese Methode real implementiert wird einen solchen Eintrag in ihrer DMT enthalten. Die Methode Dispatch() geht nun TopDown in der Vererbungshierarchie vor um die Methode zu finden die sie aufrufen muß. Enthält also die Klasse die zu oberst in .Dispatch() aufgerufen wurde KEINE entsprechende Methode in iherer DMT dann geht .Dispatch() indie DMT der Parent Klasse und sucht dort weiter. Das geht dann runter bis TObject. Und wenn dann immer noch keine Methode gefunden wurde, dann wird .DefaultHandler aufgerufen.

In der VMT == virtual Method Table sieht es anders aus. Dort wird tatsächlich eine 1 zu 1 Tabelle aller virtuellen Methoden benutzt und jede descend Klasse erbt quasi die komplette VMT der Parent Klasse und fügt die neu eingeführten virtuellen Methoden an diese VMT KOpie noch hinten dran.

An Hand dieses Verhaltens der DMT im Vergleich zur VMT ergibt sich folgendes:

VMT ist schneller als die DMT beim Aufruf.
DMT kostet weit weniger Speicherplatz als die VMT.
dynamische Methoden müssen nicht durch implementiert sein in einer Klassenhierarchie. Ist dies der Fall wird bei einem Aufruf von Dispatch() die Methode .DefaultHandler() aufgerufen.

DMTs werden von alle Klassen unterstützt und wenn die Methoden die als "message XYZ" deklariert wurden nichts anders als "dynamic" deklariert Methoden darstellen, mit der Besonderheit das man die SlotID explizit angeben kann, dann heist die das alle Klassen auch Windows-Botschaften verarbeiten können.

Ich persnlich nutze in meinen TNode Baum Strukturen exakt dieses Verhalten. TNode ist abgeleitet von TObject und ist ein interaktives Datenobjekt das als hierarisch und strukturierter Baum Daten verwalten kann. Zusätzlich gints aber auch visuelle Komponneten wie zb. ein TNodeGrid. Diese Komponenten können nun Windows Botschaften die es empfängt weitereiten zu den TNOde Baum. D.h. zb. Mouse/Keyboard/Paint Botschaften die sich auf eine Zeile im Grid beziehen werden zu der dahinterliegenden TNode weitergeleitet. Je nachdem wie und ob diese TNode reagiert kann also diese TNode zb. ihren eigenen grafischen Bereich in deisem Control selber zeichnen, auf Editierungen, Maus/Keyereignisse reagieren.
Defakto kapselt man also in solchen TNode OBjekten nicht nur die Datenhaltung sondern auch deren Visualisierung und Bearbeitung in diesen Objekten. Das visuelle Control TNodeGrid stellt nur eine Schnittstelle im GUI zu diesen Datenobjekten dar.
Diese Bibliothek habe ich schon seit Delphi 1 lauffähig und wurde mit der Zeit bis nach Delphi 7 portiert. Die allerersten Vorfahren dieser TNode Objekte habe ich aber schon in Borland Pasal 7 erzeugt.

Damit will ich nur aufzeigen das das was du möchtest sehr gut zu implementieren geht und das es auch schon andere Programmierer real gecodet haben (ich zb. )

Der Link den delphirocks angebegeben hat beschreibt dagegen eine Lösung die viel zu wenig die Hauseigene Möglichkeiten der Delphi Klassen ausnutzt (meiner Meinung nach)

Ein sehr sehr großer Vorteil dieser Methodik im Vergleich zum obigen Link ist deren direkte Intergration in das OOP Klassenkonzept. Also so wie du es gewohnt bist bei TWinControls Message-Methoden zu überschreiben, deren inherited Implemetierungen aufrufen zu können usw. kannst auch du damit arbeiten und musst nicht zwangsläufig Windows-Botschaften damit verarbeiten.

Du kannst also sowas machen:
Delphi-Quellcode:

const
  msg_One = $1000;
  msg_Two = $1001;
  msg_Three = $1002;

type
  TTest = class
    procedure DefaultHandler(var Msg: Tmessage); override;
  end;
 
  TTest_1 = class(TTest)
    procedure msgOne(var Msg: TMessage); message msg_One;
  end;

  TTest_2 = class(TTest_1)
    procedure msgTwo(var Msg: TMessage); message msg_Two;
  end;
Rufst du TTest_2.Disptach(msg_Two) auf wird also direkt die Methode TTest_2.msgTwo() aufgerufen da TTest_2 diese implementiert. Rufst du in TTest_2.msgTwo() nun inherited auf so geht der Aufruf bis zu TTest.DefaultHandler() durch da ja keine weitere Vorfahrklasse eine Methode mit SlotID msg_Two mehr implementiert.

Rufst du TTest_2.Disptach(msg_One) auf wird TTest_1.msgOne() aufgerufen da ja in der DMT von TTest_2 keine Methode mit SlotID msg_One deklariert wurde.

Rufst du TTest_2.Dispatch(msg_Three) auf wird TTest.DefaultHandler aufgerufen da ja TTest_2 und auch TTest_1 diese Methode nicht deklariert haben.

Du hast also die Möglichkeit in deiner Objekthirarchie solche Methoden zu überschrieben, deren Vorfahr-Implementierungen aufzurufen und kannst auch frei neue Message Konstanten deklarieren ohne das du schon im Vorhinein eine Implementierung dazui bauen musst. Du baust also Basisfunktionalität die erst in abgeleiteten Klassen, die du nicht kennen musst, benutzt wird.

Das sind entscheidende Argumente die den Vorteil gegenüber der im Link angegebenen Lösung aufzeigen.

Gruß Hagen

Hier siehst du ein par Besipeile der TNode und TNodeGrid

http://www.dinosgmbh.de/produkte/care/b_ambulant3.htm
http://www.dinosgmbh.de/produkte/care/b_dpl1.htm
http://www.dinosgmbh.de/produkte/care/b_dpl2.htm

Alle Gitter in diesem Screenshots sind TNodeGrids und TNode als Datenkontainer die sich selber zeichnen, auf Mau/Keabord reagieren und natürlich Daten speichern,laden, berechen und visuaiseren.
  Mit Zitat antworten Zitat
Zottel
(Gast)

n/a Beiträge
 
#6

Re: Messages zwischen Objekten austauschen?

  Alt 16. Sep 2006, 19:55
Uff... ok. das ist mal ne ausfühliche Erklärung. hmmm... Also wenn ich das jetzt richtig verstanden habe, ist es das, was ich gesucht habe. Somit kann ich einen Nachrichtenfluss zum Objekt und zur Oberfläche bauen, in der nur die nachrichten von den Objekten bearbeitet werden, die diese auch benötigen.

Vielen Dank
viele grüße
jens
  Mit Zitat antworten Zitat
Antwort Antwort


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 06:44 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