Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden? (https://www.delphipraxis.net/156290-wie-kann-ein-zeiger-auf-eine-funktion-als-paramater-uebergeben-werden.html)

FriendOfDelphi 26. Nov 2010 15:08

Delphi-Version: 5

Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Wie kann ich beim Instanziieren eines Objekts dem Konstruktor einen Zeiger auf eine Funktion übergeben?
Delphi-Quellcode:
constructor TMyClass.Create(AOwner: TComponent; Zeiger auf Klasse);
begin
  inherited Create(AOwner);
  //...
end;
Aufruf:
Delphi-Quellcode:
procedure TForm1.Test();
begin
  ShowMessage('Test');
end;

Test:=TMyObj.Create(self, Zeiger auf Test);

DeddyH 26. Nov 2010 15:20

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Ungetestet:
Delphi-Quellcode:
type
  TFunc = function(Parameter): Rückgabewert of object;

constructor Create(AOwner: TComponent; aFunc: TFunc);

himitsu 26. Nov 2010 15:33

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von DeddyH (Beitrag 1064296)
Ungetestet

Man hätte auch einfach mal bei den Unmassen an .OnXyz-Property der VCL abgucken können.
z.B. wie der Typ für
Delphi-Quellcode:
.OnKeyPress
einer Form deklariert ist.

Oder die .Sort-Methode einer TStringList > Delphi-Referenz durchsuchenTStrings.CustomSort

DeddyH 26. Nov 2010 15:39

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Wobei letztere eine Funktion entgegennimmt und keine Methode.

himitsu 26. Nov 2010 15:42

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Is mir och grad eingefallen und wollt's noch schnell (zu langsam) still und heimlich wegeditieren :oops:

FriendOfDelphi 26. Nov 2010 15:44

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von himitsu (Beitrag 1064298)
Zitat:

Zitat von DeddyH (Beitrag 1064296)
Ungetestet

Man hätte auch einfach mal bei den Unmassen an .OnXyz-Property der VCL abgucken können.
z.B. wie der Typ für
Delphi-Quellcode:
.OnKeyPress
einer Form deklariert ist.

Oder die .Sort-Methode einer TStringList > Delphi-Referenz durchsuchenTStrings.CustomSort

Das verstehe ich nicht. Dafür bin ich wohl noch zu sehr Delphi-Anfänger.
Wenn ich in einem Fenster einen Button erzeuge und auf das Ereignis OnKeyPress reagieren möchte, erhalte ich folgenden Quellcode:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1KeyPress(Sender: TObject; var Key: Char);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1KeyPress(Sender: TObject; var Key: Char);
begin
//...
end;

end.
Ich kann leider den Zusammenhang mit meinem Vorhaben nicht daraus erkennen...:(

DeddyH 26. Nov 2010 15:50

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Wie himi schon sagte: wirf doch einmal einen Blick in die VCL-Sourcen. Dort werden Methodentypen deklariert (siehe mein Beispiel) und als Felder in den Objekten definiert. Über eine Property können diese dann zugewiesen werden.

FriendOfDelphi 26. Nov 2010 16:01

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von DeddyH (Beitrag 1064306)
Wie himi schon sagte: wirf doch einmal einen Blick in die VCL-Sourcen. Dort werden Methodentypen deklariert (siehe mein Beispiel) und als Felder in den Objekten definiert. Über eine Property können diese dann zugewiesen werden.

Wo finde ich denn die VCL-Sourcen?

DeddyH 26. Nov 2010 16:11

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Die müssten unterhalb Deines Delphi-Ordners zu finden sein. Oder Du gehst auf die uses-Klausel Deiner Formularunit, drückst STRG und klickst z.B. auf "Controls". Ob das unter Delphi 5 schon ging, weiß ich leider auch nicht mehr.

himitsu 26. Nov 2010 16:55

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Eigentlich ist es recht einfach.

mögliche Funktionen/Methoden:
Delphi-Quellcode:
type
  TMyClass = class
    function Test2(...): ...;
    class function Test3(...): ...;
  end;

function Test1(...): ...;
begin
end;
und die zugehörigen Deklarationen für entsprechende Funktions-/Methoden-Zeiger, an welche man Diese übergeben könnte:
Delphi-Quellcode:
type
  TTest1 = function(...): ...;
  TTest2 = function(...): ... of object;
  TTest3 = function(...): ... of class;
  TMegaTest = reference to function(...): ...;
1: normale Funktionen/Prozeduren
2: Objekt-Methoden (Funktionen eines instantiierten Objekts)
3: Klassen-Methoden (Funktionen einer Klasse ohne Objektinstanz)

Ob man diese Typen jetzt für Property oder für Parameter nimmt, ist dabei egal.

Das TCustomsort war mir nur eingefallen, weil es da mal als Parameter genutzt wird, aber leider war das nur ein Beispiel für eine "normale" Funktion.


[edit]
die 3 ist falsch: für Klassenmethoden nimmt man auch das
Delphi-Quellcode:
of Object
, nur daß dann der interne Objektzeiger als Zeiger auf die Klasse mißbraucht wird. :shock:



TMegaTest nimmt eigentlich fast alles auf, was es irgendwie gibt ... sogar die anonymen Methoden.
Aber dieses gibt es erst seit Delphi 2010 (oder so).

DeddyH 26. Nov 2010 17:03

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Im Profil steht Delphi 5, da kann man die Hälfte Deiner Ausführungen wieder vergessen (Klassenmethoden, anonyme Methoden, ...) :tongue:

himitsu 26. Nov 2010 17:07

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von DeddyH (Beitrag 1064320)
Im Profil steht Delphi 5,

Ja, hab ich gesehn.

Man kann ihm ja auch mal was Neueres schmackhaft machen?

Und dann gibt es auch sehr Viele, mit anderen Delphi-Versionen (und sogar einige Fremdgänger ohne Delphi :stupid: ) und vorallem für die, mit neueren Versionen, kann man doch auch mal gleich was mit sagen.
> Falls sie hier mitlesen, entdecken sie vierleicht auch noch was für sich. :angel:

DeddyH 26. Nov 2010 17:09

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
[OT]
Zitat:

Zitat von himitsu (Beitrag 1064323)
Man kann ihm ja auch mal was Neueres schmackhaft machen?

Bist Du auf Provision aus? :twisted: [/OT]

himitsu 26. Nov 2010 17:35

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Dafür kann man Geld bekommen? :shock:

Nja, aktuell bekomm ich wieder mal mit, wie sehr ich einige neuere Features mag.
Die Generics sind zwar teilweise total blöde und nicht benutzbar, aber vorallem die generische TList<> ist was extrem Feines.
Und auch die Klassenvariablen seit D2006/TDE sind schon praktisch, im Kampf gegen die bösen globalen Variablen.



nochmal @Topic:
Also, wie gesagt, für diesen Fall wäre TTest2 die Lösung.

FriendOfDelphi 26. Nov 2010 17:47

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Ich habe Delphi 5 und möchte dies auch erstmal weiter verwenden...
Was gilt denn von dem Gesagten für Delphi 5?
Ich kann euch noch nicht so richtig folgen.

Ich habe eine Unit in dem das Form gemacht wird. Hier soll auch die Funktion deklariert und definiert werden, die dem Objekt beim Erstellen mitgegeben werden soll.
Der Konstruktor und alle weiteren Methoden sind in einer zweiten Unit.

DeddyH 26. Nov 2010 17:51

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Du willst doch eine Routine/Methode als Parameter deklarieren, ist das soweit richtig? Wenn ja, dann musst Du diese nur typisieren, dann geht das ohne Probleme. Der einzige Unterschied zwischen einfacher Routine und Methode ist der, dass eine Methode zu einer Klasse gehört, weshalb man bei der Typisierung dann "of object" dahinter schreiben muss (und dann natürlich auch eine Klasse braucht, die ein entsprechendes Methodenfeld besitzt).

Bummi 26. Nov 2010 17:56

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Ich hab Dir mal ein Beispiel gebastelt, der Übersicht halber alles in einer Unit
Delphi-Quellcode:
unit Unit1;

interface

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

type
  TBeispiel=Procedure(Sender:TObject) of object;

  TMyClass=Class(TButton)
    Private
      FMethode:TBeispiel;
    public
    Constructor Create(AOwner:TComponent;Methode:TBeispiel);
  End;


  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyClass }

constructor TMyClass.Create(AOwner: TComponent; Methode: TBeispiel);
begin
  inherited Create(AOwner);
  FMethode := Methode;

  //TEST
  Tag := 100;
  if Assigned(FMethode) then FMethode(Self);
  //ENDE TEST
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Showmessage(IntToStr(TComponent(Sender).Tag));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  With TMyClass.Create(Self,Button1Click) do
    begin
      Parent := self;
      Caption := 'Neuer Button';
    end;
end;

end.

FriendOfDelphi 29. Nov 2010 14:48

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Danke für den Beispielcode.
Ich habe diesen noch etwas verändert und vereinfacht, um mir die eigentliche Aufgabe noch etwas mehr zu verdeutlichen und zu überprüfen, ob ich das richtig verstanden habe:
Delphi-Quellcode:
unit Unit1;

interface

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

type
  TBeispiel=procedure() of object; //Typdefinition eigener Typ "TBeispiel"

  TBeispielKlasse=Class(TForm)
    Private
      FMethode:TBeispiel; //Deklaration Feld "FMethode" vom eigenen Typ "TBeispiel"
    Public
      constructor Create(Methode:TBeispiel); //Deklaration Konstruktor mit Methode als Übergabeparameter vom eigenen Typ "TBeispiel"
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    procedure Prozedur_1();
    procedure Prozedur_2();
  end;

var
  Form1: TForm1;
  BeispielObjekt_1: TBeispielKlasse;
  BeispielObjekt_2: TBeispielKlasse;

implementation

{$R *.DFM}

constructor TBeispielKlasse.Create(Methode:TBeispiel);
begin
  FMethode:=Methode;
end;


procedure TForm1.Prozedur_1();
begin
  ShowMessage('Prozedur_1');
end;


procedure TForm1.Prozedur_2();
begin
  ShowMessage('Prozedur_2');
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  BeispielObjekt_1:=TBeispielKlasse.Create(Prozedur_1);
  BeispielObjekt_1.FMethode;
  BeispielObjekt_2:=TBeispielKlasse.Create(Prozedur_2);
  BeispielObjekt_2.FMethode;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  BeispielObjekt_1.Free;
  BeispielObjekt_2.Free;
end;

end.
1.) Zuerst wird ein eigener Datentyp definiert:
Delphi-Quellcode:
TBeispiel=procedure() of object;
. Mit diesem kann man nun Variablen deklarieren, die eine Methode darstellen.
2.) Als nächstes wird dann eine Variable/ein Feld von diesem Typ (
Delphi-Quellcode:
FMethode:TBeispiel;
) deklariert.
3.) Dann erfolgt die Deklaration des Konstruktors, dem ein Parameter von ebenfalls diesem Typen (
Delphi-Quellcode:
FMethode:TBeispiel;
) übergeben werden muss. Innerhalb des Konstruktors wird zur Programmlaufzeit der Klassenmethode
Delphi-Quellcode:
FMethode
, die als Parameter übergebene Methode, der Klasse übergeben.
4.) Anschließend ist diese dann Teil der Klasse und und steht innerhalb der Klasse zur Verfügung.

Gut zu sehen ist das, wenn das Formluar erzeugt wird.
Hier werden die beiden Objekte erzeugt und diesen jeweils eine eigene Methode zugewiesen.
Ich hoffe, dass ich das so richtig verstanden und wiedergegeben habe.
Ansonsten können die Profis ja nochmal etwas dazu sagen.

DeddyH 29. Nov 2010 16:47

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Genau richtig. Allerdings würde ich persönlich die Methode nicht im Konstruktor übergeben lassen, sondern als Property deklarieren, damit sie sich im weiteren Programmverlauf ggf. ändern lässt, aber das hat mit der Problematik jetzt nichts zu tun.

FriendOfDelphi 1. Dez 2010 13:16

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von DeddyH (Beitrag 1064848)
Genau richtig. Allerdings würde ich persönlich die Methode nicht im Konstruktor übergeben lassen, sondern als Property deklarieren, damit sie sich im weiteren Programmverlauf ggf. ändern lässt, aber das hat mit der Problematik jetzt nichts zu tun.

Dafür wären dann die folgenden Änderungen an obigen Quellcode notwendig:
Delphi-Quellcode:
[...schnipp...]

    Public
//      constructor Create(Methode:TBeispiel); //Deklaration Konstruktor mit Methode als Übergabeparameter vom eigenen Typ "TBeispiel"
      constructor Create(); //Deklaration Konstruktor ohne Übergabeparameter
      procedure SetzeBeispielEigenschaft(mMethode: TBeispiel); //Methode für das Setzen der Property/Eigenschaft vom eigenen Typ "TBeispiel"
      property BeispielEigenschaft: TBeispiel read FMethode write SetzeBeispielEigenschaft; //Property/Eigenschaft vom eigenen Typ "TBeispiel"

[...schnipp...]

//constructor TBeispielKlasse.Create(Methode:TBeispiel);
constructor TBeispielKlasse.Create();
begin
  //mache irgendwas...
  FMethode:=nil;
end;

[...schnipp...]

procedure TForm1.FormCreate(Sender: TObject);
begin
//  BeispielObjekt_1:=TBeispielKlasse.Create(Prozedur_1);
  BeispielObjekt_1:=TBeispielKlasse.Create();
  BeispielObjekt_1.SetzeBeispielEigenschaft(Prozedur_1);
  BeispielObjekt_1.FMethode;
//  BeispielObjekt_2:=TBeispielKlasse.Create(Prozedur_2);
  BeispielObjekt_2:=TBeispielKlasse.Create();
  BeispielObjekt_2.SetzeBeispielEigenschaft(Prozedur_2);
  BeispielObjekt_2.FMethode;
end;

[...schnipp...]

FriendOfDelphi 1. Dez 2010 13:44

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Ich möchte die zuvor beschriebene Lösung dahingehend erweitern, dass die übergebene Methode auf eine Windows Message reagiert.
Also in etwa so:
Es existiert eine Klasse die unter anderem Windows Messages abarbeitet.
Das Hauptprogramm, welches diese Klasse verwendet, soll der Klasse eine Methode übergeben, die dann ausgeführt wird, wenn die entsprechende Windows Message auftritt.

Wie kann ich das realisieren, bzw. wie muss der oben beschriebene Quellcode angepasst werden? :?:

DeddyH 1. Dez 2010 13:54

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Mal aus dem Kopf:
Delphi-Quellcode:
type
  TOnBestimmteMessage = procedure of object;

  TDeineKlasse = class
  private
    FOnBestimmteMessage: TOnBestimmteMessage;
    procedure SetOnBestimmteMessage(const value: TOnBestimmteMessage);
  public
    procedure MachWas;
    property OnBestimmteMessage: TOnBestimmteMessage read FOnBestimmteMessage write SetOnBestimmteMessage;
  end;

...

procedure TDeineKlasse.MachWas;
begin
  //irgendwelcher Code
  if Assigned(FOnBestimmteMessage) then
    FOnBestimmteMessage;
  //ggf. weiterer Code
end;

...

procedure TForm1.FormCreate(Sender: TObject);
begin
  DeineKlasse := TDeineKlasse.Create;
  DeineKlasse.OnBestimmteMessage := kompatible_Methode;
end;

FriendOfDelphi 1. Dez 2010 16:26

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von DeddyH (Beitrag 1065427)
Mal aus dem Kopf:
Delphi-Quellcode:
type
  TOnBestimmteMessage = procedure of object;

  TDeineKlasse = class
  private
    FOnBestimmteMessage: TOnBestimmteMessage;
    procedure SetOnBestimmteMessage(const value: TOnBestimmteMessage);
  public
    procedure MachWas;
    property OnBestimmteMessage: TOnBestimmteMessage read FOnBestimmteMessage write SetOnBestimmteMessage;
  end;

...

procedure TDeineKlasse.MachWas;
begin
  //irgendwelcher Code
  if Assigned(FOnBestimmteMessage) then
    FOnBestimmteMessage;
  //ggf. weiterer Code
end;

...

procedure TForm1.FormCreate(Sender: TObject);
begin
  DeineKlasse := TDeineKlasse.Create;
  DeineKlasse.OnBestimmteMessage := kompatible_Methode;
end;

Hmm, dass habe ich noch nicht ganz verstanden...
Ich probiers mal:

1.0) Zuerst wird wieder ein eigener Datentyp definiert:
Delphi-Quellcode:
TOnBestimmteMessage = procedure of object;
. Mit diesem kann man nun wieder Variablen deklarieren, die eine Methode darstellen. - Verstanden.
2.1) Als nächstes wird dann wieder eine Variable/ein Feld von diesem Typ (
Delphi-Quellcode:
FOnBestimmteMessage: TOnBestimmteMessage;
) und
2.2) eine Prozedur
Delphi-Quellcode:
procedure SetOnBestimmteMessage(const value: TOnBestimmteMessage);
, die die Variable/das Feld setzen kann, deklariert. - Verstanden.
3.1) Nun wird die Prozedur
Delphi-Quellcode:
procedure MachWas;
und
3.2) die Eigenschaft/Property
Delphi-Quellcode:
property OnBestimmteMessage: TOnBestimmteMessage read FOnBestimmteMessage write SetOnBestimmteMessage;
zum Lesen und Schreiben von außerhalb der Klasse deklariert. - Soweit erst einmal verstanden.
4.0) Jetzt folgt noch die Definition der Methode "MachWas":
Delphi-Quellcode:
procedure TDeineKlasse.MachWas;
begin
  //irgendwelcher Code
  if Assigned(FOnBestimmteMessage) then
    FOnBestimmteMessage;
  //ggf. weiterer Code
end;
. - Die Methode "MachWas" für sich allein gesehen, habe ich wohl auch verstanden.
Die Methode prüft, ob die entsprechende Windows Message aufgetreten ist.
Wenn dies der Fall ist, wird die zugewiesene Methode über des Feld
Delphi-Quellcode:
FOnBestimmteMessage
, das eine Methode darstellt ausgeführt, richtig?
Aber wann wird die Methode "MachWas" aufgerufen?
Übernimmt Delphi die Erkennung der Windows Message und die automatische Ausführung der Methode "MachWas"?
Wo wird Delphi das mitgeteilt?

DeddyH 1. Dez 2010 16:31

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Wann die Methode aufgerufen wird, bestimmst Du doch selbst in Deiner Klasse. Nach Deiner eigenen Aussage wäre das dann die Behandlung einer bestimmten Windows-Message, so dass "MachWas" dann ein Message-Handler sein müsste.

FriendOfDelphi 2. Dez 2010 17:46

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von DeddyH (Beitrag 1065465)
Wann die Methode aufgerufen wird, bestimmst Du doch selbst in Deiner Klasse. Nach Deiner eigenen Aussage wäre das dann die Behandlung einer bestimmten Windows-Message, so dass "MachWas" dann ein Message-Handler sein müsste.

Ja, stimmt.
Ich mache das mit einer eigenen Message-Handling-Methode.
Das ist hier ganz gut erklärt:http://www.podgoretsky.pri.ee/ftp/Do.../messages.html.

Das Ganze funktioniert für ein Objekt auch tadellos.
Wenn ich ein zweites, oder weitere Objekte erstelle (instanziiere), wird nur die Windows-Message für das zuletzt erstellte Objekt richtig verarbeitet.
Ich habe auch schon eine Vermutung worin das Problem besteht, aber nicht, wie ich es beseitigen kann.
Das Problem liegt wahrscheinlich in der Deklaration des Windows-Message-Nummer:
Delphi-Quellcode:
[...schnipp...]
const
  WM = WM_APP + 400;
[...schnipp...]
Jedes Objekt erhält in der Klasse dieselbe Windows-Message-Nummer.
Ich müßte die als Parameter mit übergeben.
In etwa so:
Delphi-Quellcode:
[...schnipp...]
const
  WM_variabel = WM_APP + iWMNr; //iWMNr soll der übergebene Parameter sein.
[...schnipp...]
Da dies aber eine Konstante sein muss und diese ganz am Anfang definiert wird, meckert der Compiler natürlich, dass er die Variable nicht kennt.
Gibt es dafür eine andere Lösungsmöglichkeit?

himitsu 2. Dez 2010 18:08

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Delphi-Quellcode:
protected
  procedure WndProc(var Message: TMessage); override;

if Message.Msg = WM_APP + x then
Notfalls kann man auch über MSDN-Library durchsuchenRegisterWindowMessage gehn.

Siehe das Bild in "Understanding the message-handling system"
WndProc ist die erste Anlaufstelle, wo alles durchkommt und (vermutlich) danach werden die entsprechenden Dispatch-Methoden ala
Delphi-Quellcode:
procedure NAME(var Message: TWM_TYPE); message WM_MESSAGE;
abgearbeitet.

FriendOfDelphi 2. Dez 2010 19:02

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von himitsu (Beitrag 1065725)
Delphi-Quellcode:
protected
  procedure WndProc(var Message: TMessage); override;

if Message.Msg = WM_APP + x then
Notfalls kann man auch über MSDN-Library durchsuchenRegisterWindowMessage gehn.

Siehe das Bild in "Understanding the message-handling system"
WndProc ist die erste Anlaufstelle, wo alles durchkommt und (vermutlich) danach werden die entsprechenden Dispatch-Methoden ala
Delphi-Quellcode:
procedure NAME(var Message: TWM_TYPE); message WM_MESSAGE;
abgearbeitet.

Besteht nicht die Möglichkeit an der Stelle
Delphi-Quellcode:
procedure NAME(var Message: TWM_TYPE); message WM_MESSAGE;
den Wert von "WM_MESSAGE" von außerhalb der Klasse als Parameter zu übergeben?

himitsu 2. Dez 2010 20:19

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Nein.

Dieses ist nunmal eine unveränderliche Konstante, welcher an dieser Stelle wärend des Compilierens genutzt wird.
Zur Laufzeit läßt sich dieses dann eben nicht mehr ändern.

Aber genau dafür kann man eben das WndProc (WindowProcedur) nutzen, wo alles vorbeikommt.

FriendOfDelphi 3. Dez 2010 12:43

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von himitsu (Beitrag 1065766)
Nein.

Dieses ist nunmal eine unveränderliche Konstante, welcher an dieser Stelle wärend des Compilierens genutzt wird.
Zur Laufzeit läßt sich dieses dann eben nicht mehr ändern.

Aber genau dafür kann man eben das WndProc (WindowProcedur) nutzen, wo alles vorbeikommt.

Ich kann Dir noch nicht so ganz folgen:
Ist das nicht eher ein Reagieren auf eine schon vorhandene Windows-Message-Nr.?
Ich möchte doch vielmehr jedem Objekt bei der Erzeugung/Instanziierung eine eigene Windows-Message-Nr. mitgeben, auf die es dann reagiert.

himitsu 3. Dez 2010 13:08

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Du gibst z.B. deinem Constructor die Message-ID mit, speicherst sie im Objekt und vergleichst dann damit via IF in WndProc und schon hat jedes Objekt seine eigene Nummer.

FriendOfDelphi 3. Dez 2010 14:46

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von himitsu (Beitrag 1065897)
Du gibst z.B. deinem Constructor die Message-ID mit, speicherst sie im Objekt und vergleichst dann damit via IF in WndProc und schon hat jedes Objekt seine eigene Nummer.

Da ich das Senden der Message auch innerhalb des Objektes abhandle
Delphi-Quellcode:
procedure AdsRouterCallback( nEvent:Longint ); stdcall;
begin
  PostMessage(wndHandle, WM_ADSROUTERNOTIFICATION, nEvent, 0);
end;
müßte ich eine feste Liste für die verschiedenen Windows-Messages fest im Objekt integrieren und wäre dann darauf festgelegt.
Das wollte ich vermeiden.

himitsu 3. Dez 2010 15:08

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Delphi-Quellcode:
TMyObject = class(TComponent)
private
  FMessageID: LongWord;
protected
  procedure WndProc(Message: TMessage); override;
public
  constructor Create(Owner: TComponent; MessageID: LongWord);
  property MessageID: LongWord read FMessageID;
end;

procedure TMyObject.WndProc(Message: TMessage);
begin
  if Message.msg = MessageID then
  begin
    // mach was
  end;
end;

constructor TMyObject.Create(Owner: TComponent; MessageID: LongWord);
begin
  inherited Create(Owner);
  FMessageID := MessageID;
end;


id := WM_APP + 123;
obj := TMyObject.Create(nil, id);

PostMessage(obj.Handle, id, nEvent, 0);
obj.Perform(id, nEvent, 0);
oder irgendwie so

FriendOfDelphi 5. Dez 2010 15:12

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von himitsu (Beitrag 1065935)
Delphi-Quellcode:
TMyObject = class(TComponent)
private
  FMessageID: LongWord;
protected
  procedure WndProc(Message: TMessage); override;
public
  constructor Create(Owner: TComponent; MessageID: LongWord);
  property MessageID: LongWord read FMessageID;
end;

procedure TMyObject.WndProc(Message: TMessage);
begin
  if Message.msg = MessageID then
  begin
    // mach was
  end;
end;

constructor TMyObject.Create(Owner: TComponent; MessageID: LongWord);
begin
  inherited Create(Owner);
  FMessageID := MessageID;
end;


id := WM_APP + 123;
obj := TMyObject.Create(nil, id);

PostMessage(obj.Handle, id, nEvent, 0);
obj.Perform(id, nEvent, 0);
oder irgendwie so

So ganz funktiniert das noch nicht.
Ich habe noch zwei Fragen:
1.) Wird die Methode
Delphi-Quellcode:
.WndProc
automatisch aufgerufen, nachdem
Delphi-Quellcode:
.Perform
ausgeführt wurde?
2.)
Delphi-Quellcode:
PostMessage
und damit wohl auch
Delphi-Quellcode:
.Perform
sollen innerhalb der Klasse aufgerufen werden. Wie muss das dann aussehen?

DeddyH 5. Dez 2010 15:18

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
WndProc ist der MessageHandler für alle Messages, die an Deine Komponente geschickt werden. Das bedeutet, dass sowohl PostMessage als auch Perform dazu führen (sollten), dass WndProc mit der entsprechenden Message durchlaufen wird. Falls nicht, hast Du irgend etwas falsch gemacht ;)

[edit] Achja, dazu müsste Deine Komponente aber von TControl abgeleitet sein, wenn ich nicht irre. [/edit]

FriendOfDelphi 5. Dez 2010 16:45

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Also so wurde das über eine fest verknüpfte Message gemacht:
Delphi-Quellcode:
[...schnipp...]

  TMeineKlasse = class(TWinControl)
    procedure WMAdsDeviceNotification(var Message: TMessage); message WM_ADSDEVICENOTIFICATION; //feste Zuordnung von Methode zur Windows-Message

[...schnipp...]

Procedure NotificationCallback(   pAddr:PAmsAddr;
                                pNotification:PAdsNotificationHeader;
                                hUser:Longword ); stdcall;
begin
    PostMessage( HWND(hUser), WM_ADSDEVICENOTIFICATION, 0, 0);
end;

[...schnipp...]
Die Windows-Message
Delphi-Quellcode:
message WM_ADSDEVICENOTIFICATION
ruft natürlich nur die Methode
Delphi-Quellcode:
procedure WMAdsDeviceNotification(var Message: TMessage)
auf.
Deshalb habe ich das jetzt folgendermaßen geändert:
Delphi-Quellcode:
Procedure NotificationCallback(   pAddr:PAmsAddr;
                                pNotification:PAdsNotificationHeader;
                                hUser:Longword ); stdcall;
begin
    PostMessage(HWND(hUser), lwMessageID , 0, 0);
    ???.Perform(lwMessageID, 0, 0); //Hier weiß ich nicht weiter
end;
Um diese feste Zuordnung aufzulösen, soll eine eigene Windows-Message, mit der bei der Erzeugung des Objektes übergebenen Message-ID ("lwMessageID") gesendet werden.
Das
Delphi-Quellcode:
PostMessage
ist wohl richtig.
Aber anschließend muss ja noch
Delphi-Quellcode:
WndProc
mit der entsprechenden Message durchlaufen werden.
Das löst man mit
Delphi-Quellcode:
Perform(lwMessageID, 0, 0)
aus, richtig?
Hier weiß ich nicht weiter.

DeddyH 5. Dez 2010 16:49

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Auch PostMessage sollte WndProc auslösen, wenn ich keinen Denkfehler mache. Innerhalb von WndProc kannst Du doch dann die übergebene Message prüfen und dementsprechend reagieren.

FriendOfDelphi 5. Dez 2010 17:26

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von DeddyH (Beitrag 1066358)
Auch PostMessage sollte WndProc auslösen, wenn ich keinen Denkfehler mache. Innerhalb von WndProc kannst Du doch dann die übergebene Message prüfen und dementsprechend reagieren.

Ich habe wie in Nachricht #32 beschrieben im "protected"-Bereich
Delphi-Quellcode:
protected
  procedure WndProc(Message: TMessage); override;
eingefügt.

Bei
Delphi-Quellcode:
override;
meldet der Compiler den Fehler "Deklaration von 'WndProc' unterscheidet sich von vorheriger Deklaration."
Deshalb habe ich das
Delphi-Quellcode:
override;
gegen ein
Delphi-Quellcode:
overload;
ausgetauscht.

Und die Methode definiert:
Delphi-Quellcode:
procedure TMeineKlasse.WndProc(Message: TMessage);
begin
  if Message.msg = MessageID then
  begin
    // mach was
    ShowMessage('test');
  end;
end;
Soweit, so gut. Der Compiler meldet keinen Fehler.
Aber bei der Methodendefinition fehlen die "blauen" Punkte.
Die Methode wird also nicht mitcompiliert. :(

DeddyH 5. Dez 2010 17:29

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Wenn der Compiler meckert, tauscht man override einfach gegen overload? Eine sehr kreative Vorgehensweise. Wie wäre es denn mit
Delphi-Quellcode:
protected
  procedure WndProc(var Message: TMessage); override;
Nun könntest Du in der überladenen Methode einfach auf Deine Message prüfen und falls kein Treffer, inherited aufrufen, das sollte dann schon passen.

FriendOfDelphi 5. Dez 2010 18:06

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Zitat:

Zitat von DeddyH (Beitrag 1066365)
Wenn der Compiler meckert, tauscht man override einfach gegen overload? Eine sehr kreative Vorgehensweise. Wie wäre es denn mit
Delphi-Quellcode:
protected
  procedure WndProc(var Message: TMessage); override;
Nun könntest Du in der überladenen Methode einfach auf Deine Message prüfen und falls kein Treffer, inherited aufrufen, das sollte dann schon passen.

:oops: Ich muss wohl noch viel lernen. Dachte, es wäre ein Schreibfehler...

Ich habe jetzt noch folgendes Problem:
Delphi-Quellcode:
[...schnipp...]

  TMeineKlasse = class(TWinControl)
    procedure WMAdsDeviceNotification(var Message: TMessage); message WM_ADSDEVICENOTIFICATION; //feste Zuordnung von Methode zur Windows-Message
  private
    { Private-Deklarationen }
    FMessageID: LongWord;

[...schnipp...]

  public
    { Public-Deklarationen }
    property MessageID: LongWord read FMessageID;

[...schnipp...]
Ich kann die Property/Eigenschaft
Delphi-Quellcode:
TMeineKlasse.MessageID
in der Prozedur
Delphi-Quellcode:
Procedure NotificationCallback(   pAddr:PAmsAddr;
                                pNotification:PAdsNotificationHeader;
                                hUser:Longword ); stdcall;
begin
    PostMessage(HWND(hUser), TMeineKlasse.MessageID , 0, 0);
end;
nicht verwenden.
Der Compiler meldet den Fehler "Methodenbezeichner erwartet".
Kennt er die zu dem Zeitpunkt noch nicht?

DeddyH 5. Dez 2010 18:15

AW: Wie kann ein Zeiger auf eine Funktion als Paramater übergeben werden?
 
Du brauchst eine Methode. Eine solche gehört immer zu einer Klasse.
Delphi-Quellcode:
procedure Wuppdi; //reguläre Prozedur

procedure TEineKlasse.Wuppdi; //Methode der Klasse TEineKlasse


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:46 Uhr.
Seite 1 von 2  1 2      

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