我在这里放了最简单的代码来向您展示我的问题。有两个按钮btnTest
和btnChangeTestWidth
。
我为他们添加了 OnClick 事件:1)btnChangeTestWidthClick
更改btnTest
宽度属性并设置值为100和2){ {1}}恢复按钮的原始(设计)宽度。
问题是 :您是否知道如何引用和获取组件的原始(设计)大小的其他方式?
在这种情况下,它是按钮和宽度属性。我发现只有这样才能获得按钮的原始宽度。问题是我必须为每个按钮创建变量以保持此宽度,然后从 FromCreate 过程获取它。我正在开发 AutoBizing of ToolBar ,我需要为其中的许多人做这件事,并且不能为每个人创建变量。
btnTestClick
答案 0 :(得分:1)
我知道这个问题的两个解决方案:
1)创建所有者表单的新虚拟实例
2)读取并解析组件的DFM代码
解决方案1
新的VCL Applicaiton
在表单上放置一个面板和一个按钮
创建OnFormCreate
事件:
程序TForm1.FormCreate(发件人:TObject); 开始 Panel1.Width:= 100; 端;
向按钮添加OnClick
处理程序:
procedure TForm1.Button1Click(Sender: TObject);
var
Form: TForm1;
begin
Form := TForm1.CreateNew(Application);
try
ReadComponentRes(Form1.ClassName, Form);
Panel1.Width := Form.Panel1.Width;
finally
Form.Free;
end;
end;
简单就是这样!
优点:简单代码
缺点:如果你加载很多,可能需要一段时间。
解决方案2
新的VCL Applicaiton
在表单上放置一个面板和一个按钮
创建OnFormCreate
事件:
uses
uDFMParser;
procedure TForm1.FormCreate(Sender: TObject);
begin
Panel1.Width := 100;
end;
向按钮添加OnClick
处理程序:
procedure TForm1.Button2Click(Sender: TObject);
var
rs: TResourceStream;
ms: TMemoryStream;
DfmTree: TDfmTree;
DfmObject: TDfmObject;
DfmProperty: TDfmProperty;
i: Integer;
begin
rs := TResourceStream.Create(hinstance, TForm32.ClassName, RT_RCDATA);
ms := TMemoryStream.Create;
DfmTree := TDfmTree.Create;
try
rs.Position := 0;
ObjectBinaryToText(rs, ms);
ms.Position := 0;
ObjectTextToTree(ms, DfmTree);
DfmObject := nil;
for i := 0 to DfmTree.OwnedObjectCount - 1 do
if DfmTree.OwnedObject[i].ObjectName = Panel1.Name then
begin
DfmObject := DfmTree.OwnedObject[i];
break;
end;
if DfmObject = nil then
exit;
DfmProperty := DfmObject.PropertyByName('Width');
if DfmProperty = nil then
exit;
Panel1.Width := DfmProperty.IntegerValue;
finally
DfmTree.Free;
ms.Free;
rs.Free;
end;
end;
要使这个解决方案起作用,你需要一份Robert Love的DFM parser
<强>赞成强>: 现在工作量来自创建虚拟表单 读取和解析DFM代码
<强>缺点强>: 更复杂的代码。 第三方图书馆
这两个解决方案只是一个快速而肮脏的演示,因此您必须自己添加错误处理并使代码更通用(我刚刚对组件名称进行了硬编码)
我个人会选择解决方案2.
答案 1 :(得分:1)
您还可以添加辅助类或子类,如果您要记住多个属性,这可能会特别有用。子类化是最容易理解的:
Unit Unit4;
interface
uses
VCL.StdCtrls,
System.Classes;
type
TButton = class( VCL.StdCtrls.TButton )
private
fOriginalWidth: integer;
protected
procedure Loaded; override;
public
property OriginalWidth : integer
read fOriginalWidth;
end;
implementation
{ TButton }
procedure TButton.Loaded;
begin
inherited;
fOriginalWidth := Width;
end;
end.
然后确保您的新单元位于主程序中的使用列表的末尾。
unit Unit3;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
Unit4;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
if Button1.Width = Button1.OriginalWidth then
begin
Button1.Width := 2 * Button1.Width;
Button1.Caption := IntToStr( Button1.OriginalWidth );
end
else
begin
Button1.Caption := IntToStr( Button1.Width );
Button1.Width := Button1.OriginalWidth;
end;
end;
end.
请注意,您可以在主单元中使用新的额外属性,即使它在原始TButton中不存在,并且您也可以子类化TButton的祖先以使其更通用。 &#39;加载&#39;在从资源加载表单之后调用,这就是我重写该函数的原因