Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Komponente ableiten: Ereignisse überschreiben (https://www.delphipraxis.net/70886-komponente-ableiten-ereignisse-ueberschreiben.html)

Martin K 6. Jun 2006 12:12


Komponente ableiten: Ereignisse überschreiben
 
Hi,

bin gerade dabei, mir eine Komponente ableiten.
Dabei möchte ich, dass bestimmte Ereignisse (z. B. OnMouseMove) im OI nicht verfügbar sein sollen, da ich sie bereits in der abgeleiteten Komponente für etwas anderes nutze (habe also diesem Ereinis schon etwas zugeordnet).

Eine andere Möglichkeit wäre natürlich, bei OnMouseMove würden beide Ereignisse ausgeführt werden:
Das was ich in der abgeleiteten Komponente habe und das was der User im OI hinzufügt.
Dieses wäre natürlich eine bessere Lösung!

Ist eines von beiden (oder beides?) irgendwie möglich?

DGL-luke 6. Jun 2006 12:28

Re: Komponente ableiten: Ereignis löschen ???
 
du kannst die WIndowsmessage (WM_MOUSE oder so) selbst abfangen und dann zuerst dein eigenes event starten udn dann fOnMouseMove auslösen.

Du kannst natürlich auch nur in der Nachrichtenbehandlung deine Sache machen und dann die message einfach weiterleiten.

Ich würde da wahrscheinlcih sogar die komplette Nachrichtenschleife "verschieben" und in meiner eigenen die nachrichten abfangen/weiterleiten, wenn du verstehst was ich meine.

shmia 6. Jun 2006 12:31

Re: Komponente ableiten: Ereignis löschen ???
 
Du musst die Methode MouseMove überschreiben. Sie hat folgende Deklaration:
Delphi-Quellcode:
procedure MouseMove(Shift: TShiftState; X, Y: Integer); dynamic;
Du kannst innerhalb von MouseMove zuerst dein eigenes Zeug ausführen und dann rufst du
den ursprünglichen Code auf:
Delphi-Quellcode:
   inherited MouseMove(Shift, X, Y);
end;

DGL-luke 6. Jun 2006 12:33

Re: Komponente ableiten: Ereignis löschen ???
 
warum einfach, wenns auch kompliziert geht... :oops:

shmia 6. Jun 2006 12:34

Re: Komponente ableiten: Ereignis löschen ???
 
Zitat:

Zitat von DGL-luke
warum einfach, wenns auch kompliziert geht... :oops:

Tja... wer den Sourcecode der VCL hat, hat auch die MACHT. ;-)

Martin K 6. Jun 2006 12:37

Re: Komponente ableiten: Ereignis löschen ???
 
Danke erstmal für den Code, sieht echt einfach aus :thumb:
Aberm muss ich dann nicht noch das Ereignis zuweisen?
Delphi-Quellcode:
  OnMouseMove := MouseMove;

shmia 6. Jun 2006 12:44

Re: Komponente ableiten: Ereignis löschen ???
 
Zitat:

Zitat von Martin K
Aberm muss ich dann nicht noch das Ereignis zuweisen?

Nicht nötig. Der Sourcecode der Klasse TControl sieht so aus:
Delphi-Quellcode:
procedure TControl.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
  // Wenn Event OnMouseMove gesetzt, dann wird der Eventhandler aufgerufen
  if Assigned(FOnMouseMove) then FOnMouseMove(Self, Shift, X, Y);
end;
Durch Überschreiben von MouseMove wird dein MouseMove aufgerufen.
Du kannst also schön dein Ding ausführen und dann die Kontrolle über inherited
wieder auf den Standardweg abgeben.

Martin K 6. Jun 2006 12:47

Re: Komponente ableiten: Ereignis löschen ???
 
Okay, danke!

Dann werd ich's mal testen...

SirThornberry 6. Jun 2006 12:54

Re: Komponente ableiten: Ereignis löschen ???
 
Als ich den Source noch nicht hatte hab ich sowas wie folgt gemacht:
Delphi-Quellcode:
  TMeinKlasse = class(TUrsprungsklasse)
  private
    fOnMouseMove: TMouseMoveEvent;
    procedure FOnMouseMoveProc(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  public
    constructor Create(AOwner: TComponent); override;
  published
    property OnMouseMove: TMouseMoveEvent read fOnMouseMove write fOnMouseMove;
  end;
[...]
constructor TMeinKlasse.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  inherited OnMouseMove := FOnMouseMoveProc;
end;

procedure TMeinKlasse.FOnMouseMoveProc(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  //Mein Zeugs
  if Assigned(fOnMouseMove) then
    fOnMouseMove(Sender, Shift, X, Y);
end;
Die Lösung mit dem Überschreiben ist zwar besser (vor allem wenn auf Vorgängerobjecte gecastet wird etc.) aber wenn es keine Methode zum Überschreiben gibt bzw. man diese nicht kennt ist dies eine annehmbare Lösung.

Martin K 6. Jun 2006 14:56

Re: Komponente ableiten: Ereignis löschen ???
 
Hmm... irgendwie krieg ich's nich hin. :(

Wo muss ich denn die Prozedur
Delphi-Quellcode:
procedure MouseMove(Shift: TShiftState; X, Y: Integer); dynamic;
deklarieren? (nach dem Schema von Beitrag #3 !!!)

Zur Zeit steht sie im public Teil, aber sie wird einfach nicht ausgeführt :?

Übrigens:
Seit dem ich daran rumbastle kann ich Delphi nicht mehr neu starten, nur noch mit dem gerade geöffneten Delphi arbeiten.
Wenn ich Delphi starten will, kommt diese Fehlermeldung:
Zitat:

---------------------------
delphi32.exe - Einsprungpunkt nicht gefunden
---------------------------
Der Prozedureinsprungpunkt "@Inifiles@TMemIniFile@$bctr$qqrx17System@AnsiStri nt" wurde in der DLL "rtl70.bpl" nicht gefunden.
---------------------------
OK
---------------------------
:wiejetzt:

xaromz 6. Jun 2006 15:03

Re: Komponente ableiten: Ereignis löschen ???
 
Hallo,
Zitat:

Zitat von Martin K
Hmm... irgendwie krieg ich's nich hin. :(

Wo muss ich denn die Prozedur
Delphi-Quellcode:
procedure MouseMove(Shift: TShiftState; X, Y: Integer); dynamic;
deklarieren? (nach dem Schema von Beitrag #3 !!!)

Zur Zeit steht sie im public Teil, aber sie wird einfach nicht ausgeführt :?

Die Prozedur sollte in den "protected"-Bereich. Da ist sie auch ursprünglich definiert.
Außerdem musst Du natürlich die Prozedur mit override überschreiben, statt dynamic zu verwenden.

Gruß
xaromz

Martin K 6. Jun 2006 15:12

Re: Komponente ableiten: Ereignis löschen ???
 
Cool :???: , jetzt gehts!
Danke!

Aber warum geht das ganze nicht mit MouseEnter und MouseLeave :?:

SirThornberry 6. Jun 2006 15:16

Re: Komponente ableiten: Ereignis löschen ???
 
weil es für MouseEnter und MouseLeave keine dynamiche oder virtuelle Methode gibt. Bei diesen Events bleibt dir wohl nur die Möglichkeit so wie ich es beschrieben hab (bzw. kommt es auf die Komponente an von der du ableitest ob diese eine virtuelle oder dynamiche Methode davor vorgesehen hat)

Martin K 6. Jun 2006 15:21

Re: Komponente ableiten: Ereignis löschen ???
 
Zitat:

Zitat von SirThornberry
weil es für MouseEnter und MouseLeave keine dynamiche oder virtuelle Methode gibt. Bei diesen Events bleibt dir wohl nur die Möglichkeit so wie ich es beschrieben hab (bzw. kommt es auf die Komponente an von der du ableitest ob diese eine virtuelle oder dynamiche Methode davor vorgesehen hat)

Naja, ich habe ein TLabel abgeleitet, da gibt es schon MouseEnter und MouseLeave.
Aber:
Zitat:

[Fehler] Methode 'MouseEnter' nicht in Basisklasse gefunden

xaromz 6. Jun 2006 15:30

Re: Komponente ableiten: Ereignis löschen ???
 
Hallo,
Zitat:

Zitat von Martin K
Zitat:

Zitat von SirThornberry
weil es für MouseEnter und MouseLeave keine dynamiche oder virtuelle Methode gibt. Bei diesen Events bleibt dir wohl nur die Möglichkeit so wie ich es beschrieben hab (bzw. kommt es auf die Komponente an von der du ableitest ob diese eine virtuelle oder dynamiche Methode davor vorgesehen hat)

Naja, ich habe ein TLabel abgeleitet, da gibt es schon MouseEnter und MouseLeave.
Aber:
Zitat:

[Fehler] Methode 'MouseEnter' nicht in Basisklasse gefunden

Es gibt die Ereignisse, aber sie sind anders implementiert, nämlich direkt in den Message-Behandlungsroutinen (TControl.CMMouseEnter bwz. TControl.CMMouseLeave).

Gruß
xaromz

Martin K 6. Jun 2006 15:32

Re: Komponente ableiten: Ereignis löschen ???
 
Und wie muss ich die dann deklarieren?

Martin K 6. Jun 2006 15:45

Re: Komponente ableiten: Ereignis löschen ???
 
Hab's mal so probiert:
Delphi-Quellcode:
  protected
    procedure CMMouseEnter; override;
Aber leider die gleiche Fehlermeldung wie oben :?

xaromz 6. Jun 2006 15:52

Re: Komponente ableiten: Ereignis löschen ???
 
Hallo,

die beiden Methoden sind folgendermaßen in private deklariert:
Delphi-Quellcode:
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
So sieht die Implementierung von TControl aus:
Delphi-Quellcode:
procedure TControl.CMMouseEnter(var Message: TMessage);
begin
  if FParent <> nil then
    FParent.Perform(CM_MOUSEENTER, 0, Longint(Self));
  if (Message.LParam = 0) and Assigned(FOnMouseEnter) then
    FOnMouseEnter(Self);
end;

procedure TControl.CMMouseLeave(var Message: TMessage);
begin
  if FParent <> nil then
    FParent.Perform(CM_MOUSELEAVE, 0, Longint(Self));
  if (Message.LParam = 0) and Assigned(FOnMouseLeave) then
    FOnMouseLeave(Self);
end;
Das kannst Du so übernehmen und einfach die Methoden abändern.

Gruß
xaromz

SirThornberry 6. Jun 2006 15:54

Re: Komponente ableiten: Ereignis löschen ???
 
klar das dies nicht funktioniert. Die Fehlermeldung hat ja ausgesagt das es in der Basisklasse keine solche Methode gibt. Und wenn es eine solche Methode nicht gibt kann man Sie auch nicht überschreiben (Grundlagen).

Du musst wenn dann die Message selbst abfangen oder eben die von mir bereits gepostete Variante nutzen.

Oder leite einfach von TCustomLabel ab, dort sind die Properties noch nicht published und somit brauchst du die Properties auch nicht neu definieren sondern lässt sie einfach im Protected so das niemand ran kommt.

Martin K 6. Jun 2006 15:58

Re: Komponente ableiten: Ereignis löschen ???
 
@xaromx:
Also nur die beiden Methoden aus dem ersten Code in private schreiben, override dahinter und den zweiten Code brauch ich nicht?

@SirThornberry:
Wie sieht denn bei einem TCustomLabel die Deklaration von MouseEnter im protected-Teil aus?

SirThornberry 6. Jun 2006 16:05

Re: Komponente ableiten: Ereignis löschen ???
 
TCustomLabel ist der Vorfahre von TLabel. Allerdings sind dort die Properties noch nicht published. Das heißt niemand sieht das OnMouseEnter und somit kann auch niemand eine Methode zuordnen.

xaromz hat allerdings schon aufgezeigt wie du das MouseEnter abarbeiten kannst.

Martin K 6. Jun 2006 16:07

Re: Komponente ableiten: Ereignis löschen ???
 
:cry: Leider geht grad gar nix mehr :cry:
Wenn ich Delphi starten will, kommt:
Zitat:

---------------------------
delphi32.exe - Einsprungpunkt nicht gefunden
---------------------------
Der Prozedureinsprungpunkt "@Inifiles@TMemIniFile@$bctr$qqrx17System@AnsiStri nt" wurde in der DLL "rtl70.bpl" nicht gefunden.
---------------------------
OK
---------------------------
Und die betreffende Datei "rtl70.bpl" wurde am 09.11.2005 zuletzt geändert.... :?:


//Edit:
Jaja, so isses wenn man Windows hat:
Einfach neu starten und schon geht's wieder :???:

Martin K 6. Jun 2006 16:30

Re: Komponente ableiten: Ereignis löschen ???
 
So, geschafft :thumb:
Nochmal Danke an alle, ihr seid super!!!!

Eines noch:
Wie kann ich bei CMMouseEnter und -Leave die ursprünliche Methode aufrufen, die der User eingegeben hat?

Mit inherited geht es ja nicht, da ich auch kein override habe...

Martin K 6. Jun 2006 16:42

Re: Komponente ableiten: Ereignis löschen ???
 
Noch ein Problem:

Das Ereignis CMMouseEnter wird auch ausgeführt, wenn das Programm noch nicht läuft.
Also schon vor der Laufzeit....

DGL-luke 6. Jun 2006 16:51

Re: Komponente ableiten: Ereignis löschen ???
 
Du meinst, zur Designzeit? Ansonsten kann ich mir kaum vorstellen, dass dein Programm schon was tut, bevor es läuft^^

Es gibt eine Boolean-Variable, die dir sagt, ob noch Entwurfszeit gilt; Ansonsten solltest du alle Probleme durch saubere Weiterleitung von allem, mit dem du nichts zu tun haben willst, lösen können.

SirThornberry 6. Jun 2006 16:57

Re: Komponente ableiten: Ereignis löschen ???
 
@Martin K: Das was du gemacht hast nennt sich pushen und ist in diesme Forum erst nach 24 Stunden erlaubt. Wenn du etwas deinem Post hinzufügen willst benutze bitte den "Edit"-Button und poste nicht 3 mal hintereinander.
Auch andere wollen das Ihre Themen gelesen werden und denen gegenüber ist es unfair wenn du deinen Thread immer wieder davor schiebst in dem du pushst.

Wenn du eine Neue Frage hast (viel hat die letzte Frage ja nicht mehr mit der Ausgangsfrage zu tun) eröffne bitte ein neues Thema damit die Übersichtlichkeit gewahrt bleibt.

MfG SirThornberry

Martin K 6. Jun 2006 17:01

Re: Komponente ableiten: Ereignis löschen ???
 
@DGL-luke:
Ja, genau zur Designzeit.

@SirThornberry:
Oh, sorry :oops:

//Edit:
Naja, diese Frage hat schon etwas mit der Problemstellung aus dem ersten Beitrag zu tun:
Zitat:

Zitat von Martin K
Eines noch:
Wie kann ich bei CMMouseEnter und -Leave die ursprünliche Methode aufrufen, die der User eingegeben hat?

Mit inherited geht es ja nicht, da ich auch kein override habe...

Es hat sich halt ein Problem zu dem anderen entwickelt...

Hansa 6. Jun 2006 17:23

Re: Komponente ableiten: Ereignis löschen ???
 
Zitat:

Zitat von Martin K
...Wie kann ich bei CMMouseEnter und -Leave die ursprünliche Methode aufrufen, die der User eingegeben hat?

Mit inherited geht es ja nicht, da ich auch kein override habe...

Was hat das eine mit dem anderen zu tun ? :shock: "Inherited" heißt : "geerbt" ! Und es dient genau dazu, die Originalmethode einer Basisklasse aufzurufen ! Mit override kann ich die zwar überschreiben, aber das hindert einen nicht daran, trotzdem in der neuen Prozedur "inherited" zu benutzen, um eben nicht alles neu machen zu müssen. Der neue Code ist dann eben nur eine Ergänzung zum bereits vorhandenen, der eben vom inherited geliefert wird. Vorsicht auch bei ...Custom... Die Vorzüge von OOP fallen dann so gut wie weg, weil sowieso fast alles selber gemacht werden muß !

DGL-luke 6. Jun 2006 17:32

Re: Komponente ableiten: Ereignisse überschreiben
 
Du kannst eine Methode der Basisklasse immer ausdrücklich über TBasisKlasse(Objekt).Methode(); aufrufen.

Martin K 6. Jun 2006 17:32

Re: Komponente ableiten: Ereignisse überschreiben
 
Zitat:

Zitat von Hansa
Was hat das eine mit dem anderen zu tun ? :shock: "Inherited" heißt : "geerbt" ! Und es dient genau dazu, die Originalmethode einer Basisklasse aufzurufen ! Mit override kann ich die zwar überschreiben, aber das hindert einen nicht daran, trotzdem in der neuen Prozedur "inherited" zu benutzen, um eben nicht alles neu machen zu müssen. Der neue Code ist dann eben nur eine Ergänzung zum bereits vorhandenen, der eben vom inherited geliefert wird.

Okay, vielleicht hat das eine nichts mit dem anderen zu tun, aber ich hab's halt nicht hinbekommen.
Was muss ich denn - z.B. bei CMMouseEnter - dann nach dem inherited schreiben?
Hab verschiedenes probiert (CMMouseEnter, MouseEnter, OnMouseEnter) ging alles nicht.


Zitat:

Zitat von Hansa
Vorsicht auch bei ...Custom... Die Vorzüge von OOP fallen dann so gut wie weg, weil sowieso fast alles selber gemacht werden muß !

Ja, das hab ich dann auch gemerkt. Bei TCustomLabel gibts z.B. nicht einmal Caption....


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