我的程序使用动态创建的框架,有时我会遇到控件未正确对齐的问题。
我使用自己继承自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;
框架及其所有控件都已对齐且必须具有主窗体的宽度,但在您手动调整窗体大小之前,Edit1
和ComboBox1
在视觉上不会对齐(发送WM_SIZE
没有效果。)
但是如果你对Edit1.Clear
行发表评论,那么从程序开始一切都会正常。此代码并非特定于错误,您可以在此输入,例如ComboBox1.Items.Add('')
等。
如果框架是静态创建的,或者GridPanel
更改为Panel
,问题就会消失。
由于@quasoft我已经创建了一个新的test2版本,它效果更好 - 现在控件水平对齐,但是垂直组合框不在正确的位置,可以通过更改表单大小来看到。 / p>
答案 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;