Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add a property on TWinControl Class

Tags:

delphi

vcl

I want to add a published property into TWinControl. Is there someway to do this without the necessity of recompiling the base source code ?

If not, some way to recompile the base source code without too much troubles ?

Tks in advice...

EDIT 'CAUSE OF NEW IDEAS

Alright, What I'm thinking to do I'm trying to override the _GetMem from System.pas for classes inherited from TWinControl. Why ? 'Cause I'll alloc some extra space to the objects enough to an integer. Why an integer ? 'Cause this way I can add any pointer to object. So on the helper class to TWinControl I can make a Get an Set function to access this space of memory. Good isn't it ? How to do this ? Overrideing the GetMem procedure I can use the same strategy used on FastCode, create a jumper to the new procedure.

What I need now is understand how this memory alloc works InstanceSize to override this. At all I'm studding how do Delphi do this... And to add this on DFM I will do the same way, I'll create a jumper to the filer.

Someone have some idea to add the new space in objects ? What method I need to override ? The jumper I know how to do.

Tks Again.

EDIT = Evolution

I think that I did the injection of memory. I need to do more tests. I've just did it, I'm not caring about optimizations at the moment, if some one would like to test it, here goes the code. Just add the unit as the first unit of your project.

unit uMemInjection;


interface

uses
  Controls;

type
  THelperWinControl = class Helper for TWinControl
  private
    function RfInstanceSize: Longint;
    function GetInteger: Integer;
    procedure SetInteger(const Value: Integer);
  public
    property RfInteger: Integer read GetInteger write SetInteger;
  end;

implementation

uses
  Windows;

procedure SInstanceSize;
asm
  call TWinControl.InstanceSize
end;

function THelperWinControl.GetInteger: Integer;
begin
  Result := Integer(PInteger(Integer(Self) + (Self.InstanceSize - SizeOf(Integer)))^);
end;

function THelperWinControl.RfInstanceSize: Longint;
begin
  Result := PInteger(Integer(Self) + vmtInstanceSize)^;
  Result := Result + SizeOf(Integer);
end;

/////////////////////////////////////////////// FastCode ///////////////////////////////////////////////
type
  PJump = ^TJump;
  TJump = packed record
    OpCode: Byte;
    Distance: Pointer;
  end;

function FastcodeGetAddress(AStub: Pointer): Pointer;
begin
  if PBYTE(AStub)^ = $E8 then
  begin
    Inc(Integer(AStub));
    Result := Pointer(Integer(AStub) + SizeOf(Pointer) + PInteger(AStub)^);
  end
  else
    Result := nil;
end;

procedure FastcodeAddressPatch(const ASource, ADestination: Pointer);
const
  Size = SizeOf(TJump);
var
  NewJump: PJump;
  OldProtect: Cardinal;
begin
  if VirtualProtect(ASource, Size, PAGE_EXECUTE_READWRITE, OldProtect) then
  begin
    NewJump := PJump(ASource);
    NewJump.OpCode := $E9;
    NewJump.Distance := Pointer(Integer(ADestination) - Integer(ASource) - 5);

    FlushInstructionCache(GetCurrentProcess, ASource, SizeOf(TJump));
    VirtualProtect(ASource, Size, OldProtect, @OldProtect);
  end;
end;

/////////////////////////////////////////////// FastCode /////////////////////////////////////////////// 


{ THelperWinControl }
procedure THelperWinControl.SetInteger(const Value: Integer);
begin
  PInteger(Integer(Self) + (Self.InstanceSize - SizeOf(Integer)))^ := Value;
end;

initialization
  FastcodeAddressPatch(FastcodeGetAddress(@SInstanceSize), @TWinControl.RfInstanceSize);


end.
like image 969
Rodrigo Farias Rezino Avatar asked Jan 18 '10 13:01

Rodrigo Farias Rezino


1 Answers

Thanks to Smasher, I remembered how the Delphi team used class helpers and a designer trick to add properties to Delphi 2007 without breaking binary compatibility with Delphi 2006.

See this great article by Hallvard Vassbotn on how to do this.

I think it solves most, if not all, of your problems.

look for these things in the article:

  • TCustomFormHelper = class helper for TCustomForm
  • The FPixelsPerInch storage hack
  • Injecting design-time properties
  • Defining the streaming properties

You'll have to work your own way to do the streaming, though, as you hook from the outside world into TWinControl, but that might be possible too.

--jeroen

like image 138
Jeroen Wiert Pluimers Avatar answered Sep 24 '22 07:09

Jeroen Wiert Pluimers