代码更改后如何获取组件的原始(设计)Width属性?

时间:2015-12-15 18:19:41

标签: delphi width ribbon autosize

我在这里放了最简单的代码来向您展示我的问题。有两个按钮btnTestbtnChangeTestWidth

我为他们添加了 OnClick 事件:1)btnChangeTestWidthClick更改btnTest 宽度属性并设置值为100和2){ {1}}恢复按钮的原始(设计)宽度

问题是 :您是否知道如何引用和获取组件的原始(设计)大小的其他方式?

在这种情况下,它是按钮和宽度属性。我发现只有这样才能获得按钮的原始宽度。问题是我必须为每个按钮创建变量以保持此宽度,然后从 FromCreate 过程获取它。我正在开发 AutoBizing of ToolBar ,我需要为其中的许多人做这件事,并且不能为每个人创建变量。

btnTestClick

2 个答案:

答案 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;在从资源加载表单之后调用,这就是我重写该函数的原因