Add Object to TWinControl Class

I want to add a published property in TWinControl. Is there a way to do this without having to recompile the underlying source code?

If not, is there some way to recompile the basic source code without much trouble?

Tks on the board ...

CHANGE REASONS FOR NEW IDEAS

Well, what I'm going to do, I'm trying to override _GetMem from System.pas for classes inherited from TWinControl. What for? 'Because I allocated extra space for objects sufficient for an integer. Why an integer? Because I can add any pointer to an object. Therefore, in the helper class for TWinControl, I can make the Get Set function to access this memory space. Okay right? How to do it? Overriding the GetMem procedure, I can use the same strategy as on FastCode to create a jumper for the new procedure.

Now I need to understand how this memory distribution InstanceSize works to override this. I generally learn how Delphi does this ... And to add this to DFM, I will do the same, I will create a jumper for the filter.

Does anyone have an idea to add new space to objects? Which method do I need to override? Jumper I know how to do this.

Tks Again.

EDIT = Evolution

I think I injected the memory. I need to do more tests. I just did this, I don't care about optimization at the moment, if someone wants to test it, here is the code. Just add the device as the first block 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.
+3
source share
5 answers

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

Hallvard Vassbotn , .

, , , .

:

  • TCustomFormHelper = TCustomForm
  • FPixelsPerInch

- , TWinControl, .

-

+8

Delphi2007 " ".

, /. , ( factory - ) ( ) .Tag...

, / ?

+4

, :

  • : TWinControl /
  • , : GetMyPropertyFor (AWinControl: TWinControl): SetMyPropertyFor (AWinControl: TWinControl: AValue:), TWinControl

: , Tag . "", .

+2

, TWinControl VCL. VCL ( "" VCL - , Delphi). , TWinControl, .

VCL, . : http://www.delphigroups.info/2/6/744173.html

, " "...

+1

( , , , )

, , TGridPanel: "Column", "Row", "ColumnSpan" "RowSpan" , GridPanel. .

, , TGridPanel ( TFlowPanel ), . , , .

For runtime support, you can go with class helpers. When using class helpers, note that only the closest visible for the class will be applied.

Another way you can follow is to use the Tag property (which is an Integer, but you can pass it to a pointer or TObject), but you can also bite it with others using this. You must create your own development-time support for these tag properties.

- Jeroen

0
source

Source: https://habr.com/ru/post/1728919/


All Articles