Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Prüfen, ob eine Klasse eine bestimmte Methode enthält (https://www.delphipraxis.net/110399-pruefen-ob-eine-klasse-eine-bestimmte-methode-enthaelt.html)

Christian18 17. Mär 2008 16:34


Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Hallo,

wie kann ich prüfen, ob eine Klasse eine bestimmte Methode enthält oder nicht?

Delphi-Quellcode:
if FindMethod(ClassName, MethodName) then
  begin
    // Ja
  end
else
  begin
    // Nein
  end;


function FindMethod(ClassName: TClass; MethodName: TMethod) : Boolean;
begin
  // ???
end;
MFG Christian18

Apollonius 17. Mär 2008 16:37

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Das geht nur, wenn die Methode published ist und du nicht den Klassennamen, sondern die Klasse selbst hast oder die Klasse registriert ist (RegisterClass).

Bernhard Geyer 17. Mär 2008 16:39

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Stichwort ist RTTI welche nur bei published-Elementen in ausreichender Form zur verfügung stehen.
Wieso benötigst du sowas?

Dezipaitor 17. Mär 2008 16:45

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
man kann auch stattdessen Interfaces verwenden. Wenn man ein Interface definiert und überprüft, ob eine Klasse dieses Interface implementiert, dann enthält es eben all diese Methoden.

Christian18 17. Mär 2008 16:46

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Naja,

ich habe mir eine kleine Routine geschrieben, womit ich das Fenster design über eine Xml Datei steuern kann.

<FormName>
<Label Top="100" Left="100" Caption="TextFeld" OnClick="LabelClick">
</FormName>

Das ist nur ein kleiner auszug. Ich kann noch mehr Komponenten über diese Xml steuern und auch andere ereignisse zuweisen. Im Beispiel habe ich bei OnClick "LabelClick" drinn stehen. Wenn diese Methode in einer bestimmten Klasse nicht existieren sollte, dann sollte ich eine meldung ausgeben.

[Edit]

Noch baue ich Xml Dateien selber zu fuß zusammen. Wenn der Creator fertig ist, soll das mal der Nutzer des Programms machen können.

LG Chris

Apollonius 17. Mär 2008 16:48

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Du kannst mit TObject.MethodAddress feststellen, ob eine Klasse eine published Methode besitzt.

Christian18 17. Mär 2008 16:52

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Ich denke nicht, mit MethodAdress bekomme ich ja nur den Pointer.

Apollonius 17. Mär 2008 16:53

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Eben. :) Den Pointer kannst du auf nil prüfen.

Bernhard Geyer 17. Mär 2008 16:54

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Zitat:

Zitat von Christian18
Ich denke nicht, mit MethodAdress bekomme ich ja nur den Pointer.

Und wenn dieser nil ist dann hat wohl die Klasse keine entsprechende Methode :-)

shmia 17. Mär 2008 17:06

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Letztendlich willst du nicht prüfen, ob eine Klasse eine bestimmte Methode enthält, sondern ob
ein Control ein bestimmtes Property hat und falls ja, soll dieses Property gesetzt werden.

Kleines Beispiel:
Delphi-Quellcode:
uses TypInfo;
procedure SetControlColor(AControl: TControl; Color: TColor);
begin
   if IsPublishedProp(AControl, 'Color') then
      SetOrdProp(AControl, 'Color', Color)
end;
Du solltest eine Zuordnungstabelle führen, bei dem für jedes Property der Datentyp vermerkt ist.
So kann man z.B. die Caption setzen:
Delphi-Quellcode:
  SetStrProp(dasObjekt, 'Caption', inhalt_der_Caption);

Luckie 17. Mär 2008 17:15

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
So was gibt es schon. Guck mal hier: http://www.codeproject.com/KB/dotnet/XFormsNET.aspx Hatten wir in der Firma auch mal validiert, allerdings basiert das auf einem Com-Server, der installiert werden muss, aber unsere Anwendung darf nicht installiert werden. Aber eventuell ist es ja was für dich.

Christian18 17. Mär 2008 17:33

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Hallo,

ich habe ja oben erzählt, dass ich aus der XML Datei ereignisse zuweisen kann. das funktioniert auch. er findet die onclick methode und führt sie auch aus, wenn ich auf den button clicke. Jetzt wollte ich aber die Button Farbe ändern. Das geht nicht weil eine Exeption kommt. Ich weiß aber nicht warum.

suchen und zuweisung der Methode:
Delphi-Quellcode:
Method.Data:=FMenuBtn[i - 1];
Method.Code:=AClass.MethodAddress(lXml.DocumentElement.ChildNodes[AForm.Name].ChildNodes[i - 1].Attributes['OnClick']);
OnClick:=TNotifyEvent(Method);
Methode:
Delphi-Quellcode:
procedure TFMain.Neu(Sender: TObject);
begin
  MenuActive.Picture.LoadFromFile(Prg.GetAppPath + 'Img\BtnLeave.bmp');

  MenuActive:=TImage(Sender);
end;
XML Datei:

XML-Code:
<Item Caption="Neu" OnClick="Neu" />
Achso, der Button ist in wirklichkeit ein TImage, da ich eigene Button habe.

LG Chris

Christian18 17. Mär 2008 18:25

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Hallo,

ich bins nochmal. Ich glaube meine Beschreibung was ein bisschen dürftig, da keine antworten kommen. Ich probiere es einfach nochmal.

Ich habe eine Super Klasse TFMainForm. Diese Enthält alle Grafischen elemente. Dann habe ich eine Klasse TFMain abgeleitet.

Delphi-Quellcode:
type
  TFMainForm = class(TForm)
    PMain: TPanel;
    ITop: TImage;
    IBottom: TImage;
  private
    Prg: TProgram;
    FMenuBtn: Array of TImage;
    FMenuText: Array of TLabel;
    FMenuActive: TImage;
    { Private-Deklarationen }
  public
    procedure CreateMenu(AForm: TForm; AClass : TClass);
    procedure MoveMenu(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure ClickMenu(Sender: TObject);
    procedure LeaveMenu(Sender: TObject);
    property MenuActive: TImage Read FMenuActive Write FMenuActive;
    { Public-Deklarationen }
  end;
Diese Klasse erzeugt auch das Menu, welches ich aus der Xml Datei lade. Diese Klasse wird auch nicht created. Also wird auch nie angezeigt. Angezeigt wird immer nur die TFMain.

Delphi-Quellcode:
type
  TFMain = class(TFMainForm)
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure FormShow(Sender: TObject);
    procedure FormPaint(Sender: TObject);  
    procedure FormResize(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Neu(Sender: TObject);
  private
    Prg: TProgram;
    Bg: TBackground;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;
Die Methode der Klasse TFMain ruft die Methode CreateMenu der Klasse TFMainForm auf. CreateMenu enthält auch die zuweisung des OnClick ereignisses auf die Images. Die Methoden für die OnClick Ereignisse befinden sich jedoch wieder in der Klasse TFMain.

Und wenn ich nun auf ein Image klicke, soll diese Funktionalität aufgeführt werden:

Delphi-Quellcode:
procedure TFMain.Neu(Sender: TObject);
begin
  MenuActive.Picture.LoadFromFile(Prg.GetAppPath + 'Img\BtnLeave.bmp');

  MenuActive:=TImage(Sender);
end;
Das passiert aber nicht, da eine Exception kommt. Und ich weiss nicht wieso.

Christian18 17. Mär 2008 19:41

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Falls Ihr noch Informationen benötigt, könnt Ihr ruhig fragen. Ich will nicht gleich alles Posten, damit niemand verwirrt wird. Ich denke das ich mit meinen Informationen das Problem recht anschaulich dargestellt habe.

MFG Christian18

jfheins 17. Mär 2008 19:49

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Ok, 2 Sachen wären hilfreich: Was ist das für eine Exception (AV an $000000 oder sonstawas) und in welcher Zeile tritt Sie auf?

;)

Christian18 17. Mär 2008 19:52

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Hallo,

Fehler:

Zugriffsverletzung bei Adresse 0044048F in Modul 'Proect1.exe'. Lesen von Adresse 00000057.

beim ausführen dieser zeile:

MenuActive.Picture.LoadFromFile(Prg.GetAppPath + 'Img\BtnLeave.bmp');

jfheins 17. Mär 2008 20:29

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Zitat:

Zitat von Christian18
Zugriffsverletzung bei Adresse 0044048F in Modul 'Proect1.exe'. Lesen von Adresse 00000057.

Das ist nahe Null, also greifst du auf ein nicht initialisiertes Objekt zu.

Und wenn dus mal mit
Delphi-Quellcode:
procedure TFMain.Neu(Sender: TObject);
begin
  MenuActive:=TImage(Sender);
  MenuActive.Picture.LoadFromFile(Prg.GetAppPath + 'Img\BtnLeave.bmp');
end;
probierst?
Ich hab deinen Code jetzt nicht durchschaut, aber wenn es das ist, was ich denke dass es das ist, dann solltest du das Objekt zuweisen bevor du was reinlädtst ;)

Christian18 17. Mär 2008 20:38

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Hallo,

ich denke schon, dass ich das Objekt erzeuge. Bloß an einer anderen Stelle. Nämlich wenn die form erzeugt wird:

FMenuActive ist der Active Button, der leuchten soll.

Delphi-Quellcode:
procedure TFMainForm.CreateMenu(AForm: TForm; AClass : TClass);
  var lXml: TXMLDocument;
      Count: Word;
      i: Word;
      Method: TMethod;
begin
  lXml:=TXMLDocument.Create(Application);
  try
    Prg:=TProgram.Create();
    try
      lXml.LoadFromFile(Prg.GetAppPath() + 'Settings\Menu.xml');

      Count:=lXml.DocumentElement.ChildNodes[AForm.Name].ChildNodes.Count;
      SetLength(FMenuBtn, Count);
      SetLength(FMenuText, Count);
      for i:=1 to Count do
        begin
          FMenuBtn[i - 1]:=TImage.Create(AForm);
          FMenuText[i - 1]:=TLabel.Create(AForm);

          with FMenuBtn[i - 1] do
            begin
              Name:='IItem' + IntToStr(i);
              Width:=100;
              Height:=75;
              Left:=PMain.Width - Count * Width - (Count - 1) * 8 + (i - 1) * Width + (i - 1) * 8;
              Top:=0;
              if i = 1 then
                begin
                  Picture.LoadFromFile(Prg.GetAppPath() + 'Img\BtnMove.bmp');
                  FMenuActive:=FMenuBtn[i - 1];                
                end
              else
                begin
                  Picture.LoadFromFile(Prg.GetAppPath() + 'Img\BtnLeave.bmp');
                end;

              Method.Data:=FMenuBtn[i - 1];
              Method.Code:=AClass.MethodAddress(lXml.DocumentElement.ChildNodes[AForm.Name].ChildNodes[i - 1].Attributes['OnClick']);
              OnClick:=TNotifyEvent(Method);

              OnMouseMove:=MoveMenu;
              OnMouseLeave:=LeaveMenu;

              Parent:=PMain;
            end;

          with FMenuText[i - 1] do
            begin
              Name:='LItem' + IntToStr(i);
              Left:=FMenuBtn[i - 1].Left + 4;
              Top:=57;
              Caption:=lXml.DocumentElement.ChildNodes[AForm.Name].ChildNodes[i - 1].Attributes['Caption'];
              Transparent:=True;

              Method.Data:=FMenuBtn[i - 1];
              Method.Code:=AClass.MethodAddress(lXml.DocumentElement.ChildNodes[AForm.Name].ChildNodes[i - 1].Attributes['OnClick']);
              OnClick:=TNotifyEvent(Method);

              OnMouseMove:=MoveMenu;
              OnMouseLeave:=LeaveMenu;

              Parent:=PMain;
            end;
        end;
    finally
      Prg.Free();
    end;
  finally
    lXml.Free();
  end;
end;

jfheins 17. Mär 2008 20:45

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Hmmm ... also wie gesagt, ich steig da nicht ganz durch (habs ja auch nicht programmiert :stupid: )

Aber du kannst ja bis zu der Zeile Debuggen und dann herausfinden, was da genau auf nil zeigt (entweder mit den Hints, mit den Watches oder mit F7 ;) )

Wie ich Fehler so kenne, macht es danach wahrscheinlich gar nichts mehr statt der AV :mrgreen:

Christian18 17. Mär 2008 21:10

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Hallo,

ich habe gerade mal getestet, ob FMenuActive überhaupt assigned ist. da bin ich auf was merkwürdiges gestoßen.

in der methode CreateMenu ist es Assigned.

Und in der erbenden Klasse nicht mehr. Hat jemand ne idee woran das liegen könte?

LG Chris

jfheins 17. Mär 2008 21:41

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Ich weiß nicht, ob es daran liegen könnte, aber es ist zumindest unsauber FMenuActive private zu deklarieren um dann in ner anderen Klasse derselben Unit doch wieder darauf zuzugreifen ;) protected wäre besser ... aber daran sollte es nicht leigen :gruebel:

Christian18 18. Mär 2008 09:59

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Hallo,

warum unsaube?!?! Ich mache die private variable doch mit property öffentlich. Bzw. den Verweis.

MFG Christian18

Christian18 18. Mär 2008 10:42

Re: Prüfen, ob eine Klasse eine bestimmte Methode enthält
 
Hallo,

ich bins nochmal.

Wenn ich ein Object in public Deklariere und auch zuweise, dann solle ich in der erbende klasse doch darauf zurgreifen können oder?

Delphi-Quellcode:
unit UMainForm;

interface

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

type
  TFMainForm = class(TForm)
    PMain: TPanel;
    ITop: TImage;
    IBottom: TImage;
  private
    Prg: TProgram;
    FMenuBtn: Array of TImage;
    FMenuText: Array of TLabel;
    { Private-Deklarationen }
  public
    FMenuActive: TImage; // hier dekl. ich es
    procedure CreateMenu(AForm: TForm; AClass : TClass);
    procedure MoveMenu(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure LeaveMenu(Sender: TObject);
    { Public-Deklarationen }
  end;

var
  FMainForm: TFMainForm;

implementation

{$R *.dfm}

procedure TFMainForm.CreateMenu(AForm: TForm; AClass : TClass);
  var lXml: TXMLDocument;
      Count: Word;
      i: Word;
      Method: TMethod;
begin
  lXml:=TXMLDocument.Create(Application);
  try
    Prg:=TProgram.Create();
    try
      lXml.LoadFromFile(Prg.GetAppPath() + 'Settings\Menu.xml');

      Count:=lXml.DocumentElement.ChildNodes[AForm.Name].ChildNodes.Count;
      SetLength(FMenuBtn, Count);
      SetLength(FMenuText, Count);
      for i:=1 to Count do
        begin
          FMenuBtn[i - 1]:=TImage.Create(PMain);
          FMenuText[i - 1]:=TLabel.Create(PMain);

          with FMenuBtn[i - 1] do
            begin
              Name:='IItem' + IntToStr(i);
              Width:=100;
              Height:=75;
              Left:=PMain.Width - Count * Width - (Count - 1) * 8 + (i - 1) * Width + (i - 1) * 8;
              Top:=0;
              if i = 1 then
                begin
                  Picture.LoadFromFile(Prg.GetAppPath() + 'Img\BtnMove.bmp');
                  FMenuActive:=FMenuBtn[i - 1]; // hier weise ich es zu
                end
              else
                begin
                  Picture.LoadFromFile(Prg.GetAppPath() + 'Img\BtnLeave.bmp');
                end;

              Method.Data:=FMenuBtn[i - 1];
              Method.Code:=AClass.MethodAddress(lXml.DocumentElement.ChildNodes[AForm.Name].ChildNodes[i - 1].Attributes['OnClick']);
              OnClick:=TNotifyEvent(Method);

              OnMouseMove:=MoveMenu;
              OnMouseLeave:=LeaveMenu;

              Parent:=PMain;
            end;

          with FMenuText[i - 1] do
            begin
              Name:='LItem' + IntToStr(i);
              Left:=FMenuBtn[i - 1].Left + 4;
              Top:=57;
              Caption:=lXml.DocumentElement.ChildNodes[AForm.Name].ChildNodes[i - 1].Attributes['Caption'];
              Transparent:=True;

              Method.Data:=FMenuBtn[i - 1];
              Method.Code:=AClass.MethodAddress(lXml.DocumentElement.ChildNodes[AForm.Name].ChildNodes[i - 1].Attributes['OnClick']);
              OnClick:=TNotifyEvent(Method);

              OnMouseMove:=MoveMenu;
              OnMouseLeave:=LeaveMenu;

              Parent:=PMain;
            end;
        end;
    finally
      Prg.Free();
    end;
  finally
    lXml.Free();
  end;
end;

procedure TFMainForm.MoveMenu(Sender: TObject; Shift: TShiftState; X: Integer; Y: Integer);
  var Item : String;
begin
  Item:=TComponent(Sender).Name;
  Item[1]:='I';
  TImage(PMain.FindComponent(Item)).Picture.LoadFromFile(Prg.GetAppPath + 'Img\BtnMove.bmp');
end;

procedure TFMainForm.LeaveMenu(Sender: TObject);
  var Item : String;
begin
  Item:=TComponent(Sender).Name;
  Item[1]:='I';
  TImage(PMain.FindComponent(Item)).Picture.LoadFromFile(Prg.GetAppPath() + 'Img\BtnLeave.bmp');
  FMenuActive.Picture.LoadFromFile(Prg.GetAppPath() + 'Img\BtnMove.bmp'); // hier benutze ich es nochmal, damit das active image weiter leuchtet auch wenn mit der mouse wieder runter gefahren wird
end;

end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:30 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz