Verständnisfrage zu Messageverteilung innerhalb der Klassenhierarchie!

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Mario Peters
Beiträge: 37
Registriert: Sa 26. Apr 2025, 22:41

Verständnisfrage zu Messageverteilung innerhalb der Klassenhierarchie!

Beitrag von Mario Peters »

Hallo!

In den Objectpascal Klassen finde ich funktionen/Prozeduren wie

TAnyClass = class(anywhat)
private
public
....
procedure MsgAnyAction() message MSG_ANYACTION;
end;


Bisher glaubte ich, dass diese Logik auf Windows beschränkt sei. Nun gibt es aber innerhalb der TObject Klasse die Methode Dispatch. Hat etwa diese Methode irgendwas mit den Messages zu tun? Indem sie die Messages an die jeweiligen Klassen verteilt, die mit hier MSG_ANYACTION die Message empfangen sollen? Sicher hat die Direktive "message da auch ihre spezifische Aufgabe. (Kennzeichen der Methode als Message)?

Wie also erfolgt die Verteilung der Messages in Objectpascal. Ohne diese Message Logik würde ich einfach im Hauptporogramm Erignisse definieren und bei deren Auftreten die vorgesehen Aktion auslösen:

Code: Alles auswählen

repeat
    case action of
        mouseDown: DoTheAction;
        mouseMove: DoMouseMove;
        KeyDown: DoAnywhat;
    end;

until Terminated;

Weche Methoden sind in der Objectpascal Klassenhierarchie für die Verteilung der Messages zuständig? Wo gibt es dazu Dokus?

Benutzeravatar
theo
Beiträge: 11102
Registriert: Mo 11. Sep 2006, 19:01

Re: Verständnisfrage zu Messageverteilung innerhalb der Klassenhierarchie!

Beitrag von theo »

Hier gibt es ein Delphi Beispiel, welches auch auf Lazarus funktioniert.
Vielleicht hilft es:
https://docwiki.embarcadero.com/CodeExa ... h_(Delphi)

Benutzeravatar
Zvoni
Beiträge: 489
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: Verständnisfrage zu Messageverteilung innerhalb der Klassenhierarchie!

Beitrag von Zvoni »

Oder direkt in der Doku schauen
https://www.freepascal.org/docs-html/re ... 080006.6.7

So wie ich es verstehe, dient dieser Mechanismus dazu, dass man eine Prozedur/Methode aufrufen kann, ohne vorher zu wissen, wo in der Klassenhierarchie diese sich befindet,
und viel wichtiger: Man muss nicht wissen, wie die Methode heisst!
In this example, the Dispatch method will look at the object and all its ancestors (starting at the object, and searching up the inheritance class tree), to see if a message method with message MSGID has been declared. If such a method is found, it is called, and passed the Msg parameter.
Auf deine Frage bezogen:
TObject.Dispatch verteilt NICHT die "Message" als solches per se, sondern sucht die Methode, welche mit dieser "Message" als "Kurz-/Alternativbezeichnung" versehen ist, und falls gefunden, wird diese Prozedur ausgeführt inkl. Übergabe des "Message"-Records
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Mario Peters
Beiträge: 37
Registriert: Sa 26. Apr 2025, 22:41

Re: Verständnisfrage zu Messageverteilung innerhalb der Klassenhierarchie!

Beitrag von Mario Peters »

Uiiii, da werd ich einige Zeit brauchen um diese Dinge zu verstehen und ich befürchte dass ich danach weitere Fragen haben werde. Ich guck mir aber zuerst diese Links gründlich an. Danke also ert mal für die schnelle Antwort.

Benutzeravatar
Zvoni
Beiträge: 489
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: Verständnisfrage zu Messageverteilung innerhalb der Klassenhierarchie!

Beitrag von Zvoni »

Anbei mal ein kleines Beispiel-Programm

Code: Alles auswählen

program Project1;
{$mode ObjFPC}{$H+}
Uses Classes, Sysutils;

Const
  MSG_ZERO=0;
  MSG_ONE = 1;
  MSG_TWO = 2;
  MSG_THREE=3;
  MSG_FOUR=4;

Type
  TMsg = Record
    MSGID:Cardinal;
    Data:Pointer;
  end;
  TGrossVater = Class
    Public
      Procedure Proc1(Var M:TMsg);virtual;MESSAGE MSG_ZERO;
  end;
  TVater=Class(TGrossvater)
    Public
      Procedure Proc2(Var M:Tmsg);virtual;MESSAGE MSG_TWO;
  end;
  TKind=Class(TVater)
    Public
      Procedure Proc1(Var M:TMsg);override;MESSAGE MSG_ONE;  //Gleicher Prozedurname wie in Grossvater
  end;
  TEnkel=Class(TKind)
    Public
      Procedure Proc1(Var M:Tmsg);Override;MESSAGE MSG_THREE; //Gleicher Prozedurname wie in Kind
  end;
  TUrEnkel=Class(TEnkel)
    Public
      Procedure Proc2(Var M:Tmsg);Override;MESSAGE MSG_FOUR;  //Gleicher Prozedurname wie in Vater
  end;

procedure TGrossVater.Proc1(var M: TMsg);
begin
  Writeln('Grossvater='+PChar(M.Data));
end;
procedure TVater.Proc2(var M: Tmsg);
begin
  Writeln('Vater='+PChar(M.Data));
end;
procedure TKind.Proc1(var M: TMsg);
begin
  Writeln('Kind='+PChar(M.Data));
end;
procedure TEnkel.Proc1(var M: Tmsg);
begin
  Writeln('Enkel='+PChar(M.Data));
end;
procedure TUrEnkel.Proc2(var M: Tmsg);
begin
  Writeln('UrEnkel='+PChar(M.Data));
end;

Var
  o:TUrEnkel;
  msg:TMsg;
begin
  o:=TUrenkel.Create;
  msg.MSGID:=MSG_ONE;
  msg.Data:=PChar('MSG_ONE');
  o.Dispatch(msg);
  msg.MSGID:=MSG_TWO;
  msg.Data:=PChar('MSG_TWO');
  o.Dispatch(msg);
  msg.MSGID:=MSG_THREE;
  msg.Data:=PChar('MSG_THREE');
  o.Dispatch(msg);
  msg.MSGID:=MSG_FOUR;
  msg.Data:=PChar('MSG_FOUR');
  o.Dispatch(msg);
  msg.MSGID:=MSG_ZERO;
  msg.Data:=PChar('MSG_ZERO');
  o.Dispatch(msg);
  o.Free;
  Readln;
end.
Wie du siehst, benutze ich kein einziges Mal den Prozedurnamen!!
Und denk dran: der M-Parameter in den Prozeduren ist "var":
Heisst: Änderungen innerhalb der Prozeduren kommen wieder zurück zum Aufrufer!
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Antworten