在TWinControl类上添加属性 [英] Add a property on TWinControl Class

查看:88
本文介绍了在TWinControl类上添加属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将已发布的属性添加到TWinControl。
是否有某种方法可以执行而无需重新编译基本源代码?



如果没有,则可以通过某种方式重新编译基本源代码而不会带来太多麻烦?



建议中的提示...



编辑新想法的原因



好的,我想做的是,我试图重写System.pas中的_GetMem,以继承自TWinControl继承的类

为什么? ‘因为我会为对象分配一些额外的空间,足以容纳一个整数。
为什么是整数? ‘因为这种方式,我可以向对象添加任何指针。
因此,在TWinControl的辅助类上,我可以创建一个Get Set函数来访问此内存空间。
好​​吗?这个怎么做 ?
覆盖GetMem过程我可以使用FastCode上使用的相同策略,创建新过程的跳线。



我现在需要了解的是此内存分配如何工作InstanceSize来覆盖它。
我完全在研究Delphi的操作方法...然后将其添加到DFM中,我将以同样的方式进行操作,我将为文件管理器创建一个跳线。



有人想在对象中添加新空间吗?我需要重写什么方法?我知道怎么做跳线。



再次发短信。



EDIT = Evolution



我认为我做了记忆的注入。
我需要做更多测试。
我刚刚做了,我现在不在乎优化,如果有人想测试它,代码就在这里。
只需将单元添加为项目的第一个单元。

  unit uMemInjection; 


界面

使用
控件;

类型
THelperWinControl = TWinControl的类助手
私有
函数RfInstanceSize:Longint;
函数GetInteger:整数;
过程SetInteger(const Value:Integer);
公共
属性RfInteger:整数读取GetInteger写入SetInteger;
结尾;

实施

使用
Windows;

过程SInstanceSize;
asm
调用TWinControl.InstanceSize
end;

函数THelperWinControl.GetInteger:整数;
开始
结果:= Integer(PInteger(Integer(Self)+(Self.InstanceSize-SizeOf(Integer)))^);
结尾;

函数THelperWinControl.RfInstanceSize:Longint;
开始
结果:= PInteger(Integer(Self)+ vmtInstanceSize)^;
结果:=结果+ SizeOf(整数);
结尾;

///////////////////////////////////////////// ///// FastCode ////////////////////////////////////////////// ///
类型
PJump = ^ TJump;
TJump =打包记录
OpCode:字节;
距离:指针;
结尾;

函数FastcodeGetAddress(AStub:Pointer):指针;如果PBYTE(AStub)^ = $ E8,则
开始
,然后
开始
Inc(Integer(AStub));
结果:= Pointer(Integer(AStub)+ SizeOf(Pointer)+ PInteger(AStub)^);
结束
否则
结果:= nil;
结尾;

过程FastcodeAddressPatch(const ASource,ADestination:Pointer);
const
Size = SizeOf(TJump);
var
NewJump:PJump;
OldProtect:红衣主教;
开始
如果VirtualProtect(ASource,Size,PAGE_EXECUTE_READWRITE,OldProtect)然后
开始
NewJump:= PJump(ASource);
NewJump.OpCode:= $​​ E9;
NewJump.Distance:= Pointer(Integer(ADestination)-Integer(ASource)-5);

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

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


{THelperWinControl}
过程THelperWinControl.SetInteger(const Value:Integer);
开始
PInteger(Integer(Self)+(Self.InstanceSize-SizeOf(Integer)))^:=值;
结尾;

初始化
FastcodeAddressPatch(FastcodeGetAddress(@SInstanceSize),@ TWinControl.RfInstanceSize);


结尾。


解决方案

感谢Smasher ,我记得Delphi团队如何使用类助手和设计技巧来向Delphi 2007添加属性,而又不会破坏与Delphi 2006的二进制兼容性。



请参阅此 Hallvard Vassbotn 上的noreferrer>精彩文章。。 p>

我认为它可以解决大多数(即使不是全部)问题。



在文章中查找以下内容:




  • TCustomFormHelper = TCustomForm的类助手

  • FPixelsPerInch存储黑客

  • 注入设计时属性

  • 定义流属性



您将必须以自己的方式做但是,当您从外部世界进入TWinControl时,他可以进行流媒体播放。但这也有可能。



-jeroen


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.

解决方案

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

这篇关于在TWinControl类上添加属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆