我想将已发布的属性添加到TWinControl中。 有没有必要重新编译基本源代码?
如果没有,有一些方法可以重新编译基本源代码而不会有太多麻烦吗?
提出建议......
编辑'新想法的原因
好吧,我正在考虑做什么我试图从System.pas覆盖_GetMem用于类 继承自TWinControl。 为什么?因为我会为对象分配一些额外的空间足够一个整数。 为什么是整数?因为这样我可以添加任何指向对象的指针。 所以在TWinControl的辅助类上,我可以创建一个Get a Set函数来访问这个内存空间。 好不是吗?这该怎么做 ? 重写GetMem过程我可以使用在FastCode上使用的相同策略,创建一个跳转到新过程。
我现在需要了解内存分配如何使用InstanceSize来覆盖它。 总之,我正在研究Delphi如何做到这一点...而在DFM上添加它我将以同样的方式,我将创建一个跳线到文件管理器。
有人有想法在对象中添加新空间吗?我需要覆盖哪种方法?跳线我知道怎么做。
再来一次。编辑=演变
我认为我注射了内存。 我需要做更多的测试。 我刚刚做到了,我现在不关心优化,如果有人想测试它,这里就是代码。 只需将该单元添加为项目的第一个单元即可。
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.
答案 0 :(得分:9)
感谢Smasher,我记得Delphi团队如何使用类帮助程序和设计器技巧为Delphi 2007添加属性,而不会破坏与Delphi 2006的二进制兼容性。
great article Hallvard Vassbotn了解如何执行此操作。
我认为它解决了大部分(如果不是全部)问题。
在文章中查找这些内容:
但是,当你从外部世界挂钩进入TWinControl时,你必须以自己的方式进行流式传输,但这也许是可能的。
- 的Jeroen
答案 1 :(得分:4)
Delphi2007及更高版本有“级助手”。
您可以引入新的功能和属性,但不能引入字段/变量。因此,您必须将新属性的值存储在.Tag属性中的额外对象(通过工厂或其他)或(非常难看)......
不知道类助手是否也能在包/设计时工作?
答案 2 :(得分:2)
如果您仅在应用程序级别使用此属性,则可以使用以下方法:
其他:根据您的其他评论,现有的Tag属性应该可以满足您的需求。您甚至可以通过使用不同的值来定义“级别”。
答案 3 :(得分:1)
不,没有重新编译VCL就无法修改TWinControl。此外,我不建议更改VCL(因为具有“自定义”VCL会影响项目的可移植性 - 至少在Delphi安装之间)。我的目标是创建另一个继承自TWinControl的类,然后将已发布的属性添加到这个新类中。
如果您仍想更改VCL,请参阅以下帖子: http://www.delphigroups.info/2/6/744173.html
请注意“您将无法再使用运行时进行编译 包” ...
答案 4 :(得分:0)
(我知道答案有点密集,请评论您需要了解更多信息的详细信息)
你可以做的是例如TGridPanel的作用:它将Column,Row,ColumnSpan和RowSpan'属性'添加到对象检查器中,用于GridPanel上的所有组件。 这将解决您的设计时支持。
我以为我有一个关于TGridPanel如何做到这一点的参考(和TFlowPanel做类似的事情),但我现在找不到它。 Ray Konopka可能在会议期间对此进行了解释,但该信息可能不会在线。
对于运行时支持,您可以使用类助手。 使用类帮助程序时,请注意只应用类的最近可见的帮助程序。
您可能遵循的另一个路线是使用Tag属性(它是一个Integer,但您可以将其强制转换为指针或TObject),但是您也可能被其他人使用。 您必须为这些标签属性创建自己的设计时支持。
- 的Jeroen