动态创建的框架

时间:2017-01-28 12:52:52

标签: delphi alignment frame

我的程序使用动态创建的框架,有时我会遇到控件未正确对齐的问题。

我使用自己继承自TPanel的容器控件,但在使用GridPanel时也可以找到同样的问题。

以下是重现问题的test程序的源代码(使用已编译的exe)。

关键代码段:

主要形式:

//creating Frame from the main form
procedure TForm1.FormCreate(Sender: TObject);
begin
  f := TFrame2.Create(Self);
  f.Parent := Self;
end;

在框架中:

//constructor of the Frame
constructor TFrame2.Create(AOwner: TComponent);
begin
  inherited;
  Edit1.Clear;// the problem appears
end;

框架及其所有控件都已对齐且必须具有主窗体的宽度,但在您手动调整窗体大小之前,Edit1ComboBox1在视觉上不会对齐(发送WM_SIZE没有效果。)

但是如果你对Edit1.Clear行发表评论,那么从程序开始一切都会正常。此代码并非特定于错误,您可以在此输入,例如ComboBox1.Items.Add('')等。

如果框架是静态创建的,或者GridPanel更改为Panel,问题就会消失。

由于@quasoft我已经创建了一个新的test2版本,它效果更好 - 现在控件水平对齐,但是垂直组合框不在正确的位置,可以通过更改表单大小来看到。 / p>

1 个答案:

答案 0 :(得分:3)

快速修复:

问题的快速解决方案是使用Text的{​​{1}}属性,而不是TEdit方法 - 如前所述,将Clear替换为Edit1.Clear }。

了解问题

但是如果你计划长期使用Delphi中的帧,或者你在睡觉时会困扰你(开玩笑),你需要更好地理解这个问题。

真正的问题是,在为Edit1.Text := ''分配帧之前,您正在修改帧的状态。

Parent

这样做不允许procedure TForm1.FormCreate(Sender: TObject); begin f := TFrame2.Create(Self); // <--- Your text edit is cleared inside f.Parent := Self; // <--- Your frame is attached to the form here end; 组件在计算其列和行的大小时考虑父项的宽度,高度和位置。

使用TGridPanel属性有效,因为属性setter不会直接更改控件的文本,而是会将此消息发送到消息队列:

  

除了Controls.pas:

Text

实际上,在您分配了帧的... procedure TControl.SetTextBuf(Buffer: PChar); begin Perform(WM_SETTEXT, 0, Longint(Buffer)); Perform(CM_TEXTCHANGED, 0, 0); end; procedure TControl.SetText(const Value: TCaption); begin if GetText <> Value then SetTextBuf(PChar(Value)); end; ... 之后,文本实际上会发生变化 - 因为在表单创建方法完成后将稍微处理一下消息队列。

另一方面,

Parent方法直接更改文本:

  

摘自StdCtrls.pas:

Clear

更好的解决方案

如您所知,快速修复仅适用于您提供的特定示例。

更好的解决方案是在您的框架中创建... procedure TCustomEdit.Clear; begin SetWindowText(Handle, ''); end; ... 方法,并在分配 Init之后从主要表单调用此方法:

您的框架:

Parent

您的主要表单:

procedure TFrame2.Init;
begin
  Edit1.Clear;
  ComboBox1.Items.Add('Foo Bar');
end;