我想将已发布的属性添加到TWinControl中.有没有必要重新编译基本源代码?
如果没有,有一些方法重新编译基本源代码没有太多麻烦?
请咨询......
编辑新思路的原因
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.
有人有想法在对象中添加新空间吗?我需要覆盖哪种方法?跳线我知道怎么做.
再来一次.
编辑=进化
我认为我注射了记忆.我需要做更多的测试.我刚刚做到了,我现在不关心优化,如果有人想测试它,这里就是代码.只需将该单元添加为项目的第一个单元即可.
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.
Run Code Online (Sandbox Code Playgroud)
感谢Smasher,我记得Delphi团队如何使用类帮助程序和设计器技巧为Delphi 2007添加属性,而不会破坏与Delphi 2006的二进制兼容性.
看到这个伟大的文章由Hallvard Vassbotn如何做到这一点.
我认为它解决了大部分问题,如果不是全部的话.
在文章中寻找这些东西:
但是,当您从外部世界挂钩到TWinControl时,您将不得不以自己的方式进行流式传输,但这也许是可能的.
--jeroen
Delphi2007 及更高版本具有“类助手”。
您可以引入新的函数和属性,但不能引入字段/变量。因此,您必须将新属性的值存储在 .Tag 属性中的额外对象中(通过工厂或其他方式)或(非常难看)...
不知道类助手是否也适用于包/设计时?