6

我正在尝试以下列方式使用 TFlowPanel 组件:

  1. 放置在主窗体Form1组件上FlowPanel1: TFlowPanel
  2. 设置Form1.Width = 400, FlowPanel1.Align = alTop, FlowPanel1.AutoSize = True, FlowPanel1.AutoWrap = True.
  3. 放置在FlowPanel15 个 SpeedButton 上并将其设置Width为 64。
  4. 编译并运行。
  5. 减小表格的宽度(关于Form1.Width = 200)。

出于某种原因,当用户调整表单大小时,速度按钮不会自动排成两行。AutoSize = False虽然,当,时,它们确实排成两排AutoWrap = True
这种行为的原因是什么以及如何解决?

编辑:我找到了“快速而肮脏”的解决方案。以下代码是事件的事件处理程序TFlowPanel.OnResize

procedure TForm1.FlowPanel1Resize(Sender: TObject);
begin
  with FlowPanel1 do
  begin
    AutoSize := False;
    Realign;            // line up controls
    AutoSize := True;   // adjust TFlowPanel.Height
  end;
end;

但是,我仍然想知道是否有解决问题的标准方法。

4

2 回答 2

6

我无法在代码中找到这种行为的确切原因,但基本上你已经挑战了两个大小属性来对抗,AutoSizeAlign. 问题是,我认为,当您调整表单大小时,AutoSize配置为 True 并Align设置为alTop的控件将首先尝试自动调整控件大小,然后对齐到其父级的顶部。我可以肯定地说,至少从它们的逻辑含义来看,这两个属性不应该结合在一起。

我建议您的解决方法是默认关闭自动调整大小,并在OnResize事件中将其临时打开并重新关闭以自动调整高度。所以在代码中它会简单地更改为:

procedure TForm1.FlowPanel1Resize(Sender: TObject);
begin
  // there's no Realign here, since the AlignControls request is called
  // at control resize, so here you have children already aligned, what
  // you then need is to request the control to autosize the height and
  // turn off the autosizing to the default, disabled state
  FlowPanel1.AutoSize := True;
  FlowPanel1.AutoSize := False;
end;
于 2012-09-13T07:26:11.030 回答
3

tl,dr:这是TFlowPanel.

通常情况下,AutoSizeAlign属性默认情况下很好地结合在一起,因为这已经在TControl级别上进行了处理,所以我想知道为什么会发生这种情况。我注意到一个被覆盖的AlignControls方法,TFlowPanel并考虑绕过它进行测试:

type
  TWinControlAccess = class(TWinControl);
  TAlignControls = procedure(Instance: TObject; AControl: TControl;
    var Rect: TRect);

  TFlowPanel = class(Vcl.ExtCtrls.TFlowPanel)
  protected
    procedure AlignControls(AControl: TControl; var Rect: TRect); override;
  end;

  TForm1 = class(TForm)
    ...

procedure TFlowPanel.AlignControls(AControl: TControl; var Rect: TRect);
begin
  // Skip TCustomFlowPanel.AlignControls
  TAlignControls(@TWinControlAccess.AlignControls)(Self, AControl, Rect);
end;

procedure TForm1.FlowPanel1Resize(Sender: TObject);
begin
  // Do my own aligning of the last button
  if FlowPanel1.ClientWidth < Button5.BoundsRect.Right then
  begin
    Button5.Left := 1;
    Button5.Top := Button1.Height + 1;
  end
  else if FlowPanel1.ClientWidth > Button4.BoundsRect.Right + Button5.Width then
  begin
    Button5.Left := Button4.BoundsRect.Right;
    Button5.Top := 1;
  end;
end;

现在,这按预期工作。那么TFlowPanel' 的实施有什么问题AlignControls?看起来下面的代码片段是原因:

if AutoSize then
  Rect := TRect.Create(
    Rect.Left,
    Rect.Top,
    Rect.Left + (ExplicitWidth - (Width - (Rect.Right - Rect.Left))),
    Rect.Top + (ExplicitHeight - (Height - (Rect.Bottom - Rect.Top))));

当这部分被注释掉时,行为与Alignset 和预期的一样。现在,我想将此提交给 QC,但也许我忽略了它的某些方面。请编辑或评论何时(以及为什么)确实需要此代码。

于 2012-09-13T18:08:30.550 回答