Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Ausführen einer Methode bei MethodAddress (https://www.delphipraxis.net/214588-ausfuehren-einer-methode-bei-methodaddress.html)

josef-b 4. Feb 2024 09:31

Delphi-Version: 11 Alexandria

Ausführen einer Methode bei MethodAddress
 
Ich habe ein Formular mit vielen sichtbaren abgeleiteten Graphic-Komponenten.

Ich habe den Namen der Komponente, weiß aber nicht genau von welchem Typ die ist.

Ich möchte diese bestimmte neu zeichnen mit "repaint" weil sich einfach nur die Farbe ändern soll.

Dazu habe ich folgenden Ansatz?, weiß aber nicht wie ich die Methode repaint dann ausführen kann.
Stehe ich da einfach nur auf dem Schlauch?


Delphi-Quellcode:
procedure TFMain.repaint_bauteil(acomp_name: string; astatus: integer);
var
  aComp: TComponent;
  aMethodAddress: Pointer;

begin

aComp := FMain.FindComponent(aComp_Name);

aMethodAddress := aComp.MethodAddress('Repaint');

if Assigned(aMethodAddress) then
  begin

  //wie jetzt hier die entsprechende Procedure 'Repaint' ausführen?
   
  end;
end;

Olli73 4. Feb 2024 10:15

AW: Ausführen einer Methode bei MethodAddress
 
Entweder guckst du hier ab:

https://docwiki.embarcadero.com/Libr....MethodAddress

Oder du machst sowas:

Delphi-Quellcode:
(aComp as TControl).Repaint;

himitsu 4. Feb 2024 11:29

AW: Ausführen einer Methode bei MethodAddress
 
Entweder selbst durch die TypeInfo kämpfen Delphi-Referenz durchsuchenTypInfo
oder die erweiterte RTTI benutzen Delphi-Referenz durchsuchenTRTTI.

Die Funktionen an TObjekt kennen keine Typen (das sind die Funktionen, welche der DFM-Loader/Writer nutzt, aber deswegen prüft/vergleicht inzwischen der FormDesigner, in der IDE, nun beim Speichern zumindest mal die Typen der Felder und Methoden-Parameter zwischen PAS und DFM)

josef-b 4. Feb 2024 14:35

AW: Ausführen einer Methode bei mehreren Komponenten
 
So richtig komme ich noch nicht klar.

Mit einer einzelnen bestimmten Komponente gehts..

Delphi-Quellcode:
procedure TFMain.repaint_bauteil(acomp_name: string; astatus: integer);
var
  aComp: TComponent;
  acolor: TColor;
begin
aComp := FMain.FindComponent(aComp_Name);
acolor := (acomp as TMyOwnComp).FarbeDefault;

case aStatus of
  99: Acolor := clred;
  100: Acolor := clyellow;
  end;

(acomp as TMyOwnComp).Farbe := acolor;
(acomp as TMyOwnComp).Repaint;

end;
Da ich aber verschiedene eigene Klassen habe (verschiedene eigene Grafiken) vom
Typ TmyOwnCompName1, TmyOwnCompName2..... dachte ich mir, es geht vielleicht wie folgt,
tuts aber nicht :(

Alle Komponenten haben die Eigenschft Farbe und die Methode Repaint;

Delphi-Quellcode:
procedure TFMain.repaint_bauteil(acomp_name: string; astatus: integer);
var
  aComp: TComponent;
  acolor: TColor;

  aClassType: TClass;

begin

aComp := FMain.FindComponent(aComp_Name);

aCLassType := aComp.ClassType;

.....

(acomp as aClassType).Farbe := acolor; // geht nicht *******
end;

Olli73 4. Feb 2024 14:41

AW: Ausführen einer Methode bei MethodAddress
 
Wie ist denn die Klassenhierarchie für deine Komponenten?

Olli73 4. Feb 2024 14:43

AW: Ausführen einer Methode bei MethodAddress
 
Wenn das z.b irgendwie alles von t-control abgeleitet ist, dann reicht as TControl für repaint.

jaenicke 4. Feb 2024 15:13

AW: Ausführen einer Methode bei MethodAddress
 
Wenn das alles deine eigenen Klassen sind, leite sie doch einfach von einer gemeinsamen Elternklasse ab, die diese Funktionalität bereitstellt. Dann kannst du darauf casten.

Wenn das nicht geht, kannst du ein Interface verwenden, in dem die Funktionalität erreichbar ist, so dass deine Klassen dieses alle implementieren können. Dann kannst du mit Supports dieses holen und nutzen.

himitsu 4. Feb 2024 15:25

AW: Ausführen einer Methode bei MethodAddress
 
Casten und die Methode "direkt" aufrufen ist natürlich immernoch das Beste, am Einfachsten über einen gemeinsamen Vorfahren.

Delphi-Quellcode:
type
  TMyForm = class(TForm)
  private
    procedure Test;
    procedure DoLog(S, S2: string);
  end;

procedure TMyForm.Test;
begin
  for var M in TRttiContext.Create.GetType({TMyForm}Self.ClassType).GetMethods do // ja, es fehlt ein .FindMethod('DoLog') ... k.A. warum die immer wieder so dämlich sind
    if M.Name = 'DoLog' then
      M.Invoke(Self, ['abc', 'def']);
end;

josef-b 4. Feb 2024 19:58

AW: Ausführen einer Methode bei MethodAddress jetzt habe ich noch ne AV
 
ich habe es wohl nicht so mit Klassen, eigenen Komponenten und Vererben (vererben klingt auch so negativ irgendwie)

also die Elternklasse ist TGraphicControl..

Ich erstelle eine neue Komponente TT

die sieht dann erstmal nackt so aus:

Delphi-Quellcode:

unit Test;

interface

uses
  System.SysUtils, System.Classes, Vcl.Controls;

type
  TTest = class(TGraphicControl)
  private
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
  published
    { Published-Deklarationen }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('TEest', [TTest]);
end;

end.
Funktioniert soweit.

wenn ich jetzt diese Komponente auf ne Form ziehe und folgenden Code habe als Beispiel:

Delphi-Quellcode:

procedure TFMain.BtnTestCompClick(Sender: TObject);
var
  aComp: TComponent;
  aComp_Name: string;
begin

aComp_Name := 'Test1';

aComp := FMain.FindComponent(aComp_Name);

(acomp as TGraphicControl).Height := 200;

end;
läuft das Progrämmchen auch, aber es kommt eine Zugriffsverletzung bei der letzten Zeile mit "acomp as'.

Habe bestimmt nur ne Kleinigkeit übersehen? Die Eigenschaft height ist ja standardmässig auch vorhanden in TGraphicControl

Delphi.Narium 4. Feb 2024 20:11

AW: Ausführen einer Methode bei MethodAddress
 
Weder prüfst Du, ob aComp überhaupt was zugeweisen wurde, also FindComponent erfolgreich war, noch prüfst Du, ob aComp überhaupt vom Typ TGraphicControl ist.
Delphi-Quellcode:
if Assigend(aComp) and (aComp is TGraphicControl) then TGraphicControl(acomp).Height := 200;

josef-b 4. Feb 2024 20:36

AW: Ausführen einer Methode bei MethodAddress
 
Ja, ich glaube ich war jetzt einfach etwas zu schnell und ungenau, sorry

josef-b 4. Feb 2024 21:31

AW: Ausführen einer Methode bei MethodAddress
 
Zitat:

Zitat von jaenicke (Beitrag 1532998)
Wenn das alles deine eigenen Klassen sind, leite sie doch einfach von einer gemeinsamen Elternklasse ab, die diese Funktionalität bereitstellt. Dann kannst du darauf casten.

So habe ich das jetzt gemacht. Funktioniert prima. Vielen Dank für Eure Hilfe

himitsu 4. Feb 2024 22:04

AW: Ausführen einer Methode bei MethodAddress
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1533006)
weder ... noch prüfst Du, ob aComp überhaupt vom Typ TGraphicControl ist.

Doch doch.

Wenn es Keines ist, dann gibt es eine "passende" Exception, denn
Delphi-Quellcode:
(acomp as TGraphicControl)
.

Aber hier
Delphi-Quellcode:
TGraphicControl(acomp)
würde es nicht geprüft.


Achtung, IS und AS haben beim NIL einen kleinen UInterschied.

IS sagt False, wenn es NIL ist, also wenn es nicht "dieser Typ" ist.
AS dagegen läßt NIL durch, da es nur püpft, ob es der richtige Typ ist ... und NIL ist nicht ein "falscher Typ", da es nichts ist.



Zitat:

Dann kannst du darauf casten
Nicht vergessen, dass beim Zugriff über einen Vorfahr-Typen eventuell ein VIRTUAL + OVEERRIDE nötig ist, wenn die Funktionalität erst in den Nachfahren steckt.

Delphi.Narium 5. Feb 2024 00:30

AW: Ausführen einer Methode bei MethodAddress
 
Zitat:

Zitat von himitsu (Beitrag 1533011)
Zitat:

Zitat von Delphi.Narium (Beitrag 1533006)
weder ... noch prüfst Du, ob aComp überhaupt vom Typ TGraphicControl ist.

Doch doch.

Wenn es Keines ist, dann gibt es eine "passende" Exception, denn
Delphi-Quellcode:
(acomp as TGraphicControl)
.

Deshalb prüfe ich mit
Delphi-Quellcode:
if Assigend(aComp)
Zitat:

Zitat von himitsu (Beitrag 1533011)
Aber hier
Delphi-Quellcode:
TGraphicControl(acomp)
würde es nicht geprüft.

deshalb prüfe ich mit
Delphi-Quellcode:
and (aComp is TGraphicControl)
Zitat:

Zitat von himitsu (Beitrag 1533011)
Achtung, IS und AS haben beim NIL einen kleinen UInterschied.

IS sagt False, wenn es NIL ist, also wenn es nicht "dieser Typ" ist.
AS dagegen läßt NIL durch, da es nur püpft, ob es der richtige Typ ist ... und NIL ist nicht ein "falscher Typ", da es nichts ist.

und mit dem anschließenden
Delphi-Quellcode:
then TGraphicControl(acomp).Height := 200;
sollte die Zuweisung auf height erst dann erfolgen, wenn acomp sowohl etwas zugewiesen wurde, also nicht Nil ist, dieses Etwas vom Typ TGraphicControl ist und damit über das Attribut Height von TGraphicControl geerbt haben sollte. Soweit ich das sehe, sollten die von Dir genannten Bedingungen alle (ohne Exception) geprüft und vor dem Zuweisen von 200 auf das Attribut Height erfüllt sein. Also dürfte auch
Zitat:

Zitat von himitsu (Beitrag 1533011)
Dann kannst du darauf casten

erfüllt sein.

joachimd 5. Feb 2024 08:18

AW: Ausführen einer Methode bei MethodAddress
 
Tu Dir einen Gefallen und verwende - wie Jaenicke weiter oben vorgeschlagen hat - Interfaces. Lose koppeln, wo immer möglich.
Das gibt Dir die Möglichkeit, auch an fremde Klassen mit ganz anderer Vererbungs-Hierarchie noch etwas dranzukleben.

jaenicke 5. Feb 2024 18:34

AW: Ausführen einer Methode bei MethodAddress
 
Interfaces bieten viele Vorteile, aber diese kommen erst richtig zur Geltung, wenn man sie auch in der Architektur berücksichtigt. Insofern ist die gemeinsame Basisklasse erst einmal die einfachste Lösung für das konkrete Problem.

Trotzdem macht es natürlich Sinn, sich anzuschauen, wie es mit Interfaces gehen würde, um diese künftig im Hinterkopf zu haben.


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