Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi CodeRedirect von Protected-Methoden (https://www.delphipraxis.net/167511-coderedirect-von-protected-methoden.html)

freedy 3. Apr 2012 08:44

Delphi-Version: XE

CodeRedirect von Protected-Methoden
 
Hallo Forum,

in meinem aktuellen Projekt möchte ich eine Überwachung des Properties "Enabled" von allen Ableitungen von TControl überwachen. Das Setzen auch aus dem Programmablauf heraus soll nur dann möglich sein, wenn die notwendigen Rechte vorliegen respektive meine Anwendung das Okay dafür gibt. Allerdings stoße ich hier auf die Schwierigkeit, dass ich eine Methode einer Klasse umleiten muss.

Ich habe nun verschiedene Vorgehen ausprobiert, um auf das "TControl.SetEnabled" zuzugreifen. Leider ohne großen Erfolg. Ein Code-Redirect durch Einfügen eines Jumps an der Originaladresse schien mir sinnvoll. Ich konnte aber nicht mehr zurück auf die Ursprungsadresse verweisen, um dort den Originalcode auszuführen.

Gibt es eine Möglichkeit, einen Programmteil in solche Grundklassen einzuschleusen, so dass ein Aufruf des inherited in abgeleiteten Klassen automatisch auch auf diesen Code geleitet und anschließend der ursprüngliche Code ausgeführt wird?

Vielen Dank für Eure Hilfe.

Michael.

freedy 3. Apr 2012 18:21

AW: CodeRedirect von Protected-Methoden
 
Hallo,

ich hab's nun nach einigen Versuchen geschafft. Für meine Lösung habe ich mir die CPU-Ansicht in der IDE während der Laufzeit ohne Redirect angeschaut. Dort habe ich die nötigen Assembler-Befehle entsprechend übernommen. So habe ich Zugriff auf die jeweilige Instanz und die übergebenen Parameter bekommen.

Bis auf den Fehler, dass der JZ-Befehl im Original-Code auf eine falsche Adresse zeigt, klappt alles super. Dieser Fehler kann aber durch eine einfache Überprüfung in der aufrufenden Funktion umgangen werden.

Trotzdem Danke für's Nachdenken.

Viele Grüße

brechi 3. Apr 2012 21:08

AW: CodeRedirect von Protected-Methoden
 
Das Parsen uebernehmen einige Units für dich z.b. Flocke ( http://www.delphipraxis.net/54339-ge...code-hook.html ) oder mit ( http://uall.cheat-project.net/uallCollection )

freedy 3. Apr 2012 21:24

AW: CodeRedirect von Protected-Methoden
 
Hallo brechi,

vielen Dank für den Hinweis. Ich werde das morgen noch einmal ausprobieren. Ich muss mich in die ganzen Möglichkeiten dieser Hooks noch richtig einarbeiten. So richtig fit fühle ich mich da noch nicht. :wink:

Grüße
Michael

himitsu 3. Apr 2012 22:21

AW: CodeRedirect von Protected-Methoden
 
Gibt es nicht in XE oder XE2 eine hauseigene Lösung?

Mir ist so, als hatte ich das vor 'ner Weile hier mal gesehn. :gruebel:
Ich glaub da wird intern ein generisches Objekt erstellt, worüber die Umleitung geregelt wird und dann wird die RTTI auf die neue Klasse umgeleitet, bzw. der Typ wird im gewünschten Objekt ersetzt, so daß ab nun alles über die neue Klasse abläuft, oder irgendwie so.



SetEnabled ist ja virtual, also könnte man auch einfach die VMT ändern.



TApplicationEvents.OnMessage und dort auf CM_ENABLEDCHANGED mit dem Handle deiner Komponente warten. [edit]alle[/edit]
PS: Du hast dir nicht umsonst den VCL-Quellcode gekauft ... ich an deiner Stelle würde dort öfters mal nachsehn.



Ab XE2 könnte man eventuell auch das DataBinding für sowas verwenden. :gruebel:

freedy 3. Apr 2012 22:35

AW: CodeRedirect von Protected-Methoden
 
Zitat:

Zitat von himitsu (Beitrag 1160058)
Gibt es nicht in XE oder XE2 eine hauseigene Lösung?

Mir ist so, als hatte ich das vor 'ner Weile hier mal gesehn. :gruebel:
Ich glaub da wird intern ein generisches Objekt erstellt, worüber die Umleitung geregelt wird und dann wird die RTTI auf die neue Klasse umgeleitet, bzw. der Typ wird im gewünschten Objekt ersetzt, so daß ab nun alles über die neue Klasse abläuft, oder irgendwie so.

Hallo Himitsu,

eine hauseigene Lösung kenne ich hier nicht.


Zitat:

Zitat von himitsu (Beitrag 1160058)
SetEnabled ist ja virtual, also könnte man auch einfach die VMT ändern.

Sollen dann alle Nutzer meiner Rechteverwaltung die VCL neu erstellen? Das halte ich für nicht sinnvoll und wird bei anderen höchst wahrscheinlich auch auf Ablehnung stoßen.

Zitat:

Zitat von himitsu (Beitrag 1160058)
TApplicationEvents.OnMessage und dort auf CM_ENABLEDCHANGED mit dem Handle deiner Komponente warten. [edit]alle[/edit]
PS: Du hast dir nicht umsonst den VCL-Quellcode gekauft ... ich an deiner Stelle würde dort öfters mal nachsehn.

An der Stelle, wo die Message ausgelöst wird, bin ich bereits zu spät. Nach meinem Konzept muss ich mir merken, ob aus dem Programmverlauf heraus das Control deaktiviert ist oder ob es durch die Rechteverwaltung deaktiviert wurde. Beides zusammen ergibt dann den Zustand von Enabled. Bei meinen Versuchen die Message abzufangen, fingen die Controls an leicht zu flackern.

himitsu 3. Apr 2012 22:53

AW: CodeRedirect von Protected-Methoden
 
Ich weiß es leider auch nicht mehr genau ... glaub nur es mal gesehn zu haben :cry:


Es lassen sich über die neue RTTI alle möglichen Klassen suchen.
Darüber kommt man nun auch an die TypeInfo dieser Klassen und kann darin die VMT bearbeiten und den Prozedurzeiger ersetzen.
> auf seine Prozedur umleiten und sich natürlich den alten Zeiger merken, um die alte Prozedur wieder aufrufen zu können.



CM_ENABLEDCHANGED:
Über TApplicationEvents kommst du als Erstes an diese Message (solange sich voeher kein Anderer dort auch drangehängt hat)

Handled auf True setzen, damit die Message nicht weitergeleitet wird und dann über die neue RTTI das private FEnabled suchen und dort den alten Wert (negierter aktueller Wert) am Setter vorbei setzen.
Einziges Problem währe, wenn SetEnabled in den Klassen überschrieben wurde.

brechi 4. Apr 2012 17:38

AW: CodeRedirect von Protected-Methoden
 
oder du machst dir eine eigene Unit in der Art (musst dir dann jedoch die Controls alle einmal selsbt erstellen und als letztes einbinden):

Delphi-Quellcode:
unit Unit17;

interface

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

type
  TEdit = class(StdCtrls.TEdit)
  public
    procedure SetEnabled(Value: Boolean); override;
  end;

  TForm17 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure NotifyEnabled(_Control: TControl);
  end;

var
  Form17: TForm17;

implementation

{$R *.dfm}

procedure TForm17.Button1Click(Sender: TObject);
var
  C: TControl;
begin
  C := FindComponent(Format('Edit%d', [Random(2) + 1])) as TControl;
  C.Enabled := not C.Enabled;
end;

procedure TEdit.SetEnabled(Value: Boolean);
begin
  inherited;
  Form17.NotifyEnabled(Self)
end;

procedure TForm17.NotifyEnabled(_Control: TControl);
begin
  caption := _Control.Name + ' ' + BoolToStr(_Control.Enabled, True);
end;
geht dann auch mit ueberschriebenen Funktionen


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