TForm会在什么条件下展开OnResize?

时间:2009-08-06 19:07:43

标签: delphi winapi vcl onresize

作为this question的扩展名:

TForm.OnResize有时会在首次显示表单之前触发,但并非总是如此。例如,如果BorderStyle是bsDialog或bsNone,则OnResize将不会触发。对于所有其他BorderStyle值(以及其默认值下的所有其他属性),OnResize会触发。

在显示表单之前是否还会影响OnResize是否会触发?例如,其他属性或属性组合会对此产生影响吗?

OnResize事件是ShowWindow API函数向窗口发送WM_SIZE消息的结果。这有点重复:消息来自Windows,而不是来自Delphi。这是一个Windows函数(ShowWindow),它(有时)发送触发事件的消息 - 所以VCL源代码在这种情况下,代码并没有真正的帮助。

基于记录的ShowWindow / WM_SIZE行为的明确答案的奖励积分,例如:参考MSDN文档或Petzold书籍。

3 个答案:

答案 0 :(得分:1)

可能甚至取决于用户的显示设置或桌面主题或Windows版本。如果OnResize给我这样的问题,我会建立我的程序,总是期待它并在任何情况下处理它,无论我认为是什么原因。

答案 1 :(得分:0)

我相信OnResize会在事件发送消息时触发 说将修改表格大小(左,底,宽,高)。

由于您已经发现了哪个消息触发了该事件,因此您需要 现在跟踪在vcl中发送消息的位置。

查看vcl源代码,了解是否可以发现这些操作。

编辑:让我们走低级别。窗户中的表格(粗略地说话)有什么 被称为“窗口类”(它不是像我们所知的那样的类)。所有时候窗体的窗口类都被调整大小(并且窗体是可见的),WM_SIZE被发送。

因此,不会一直显示表单,但与底层窗口类相比,只会更改它的尺寸。

正如您所观察到的,许多属性值会改变表单的尺寸(甚至几个像素)。

这是一个非常肤浅的解释,这是其他一些细节 - 但是我理解了事情是如何工作的。“

答案 2 :(得分:0)

没有替代测试。如何在代码中创建表单,设置您感兴趣的属性以及在调用resize事件时进行记录。

如果您原谅代码的丑陋,这里是一个粗略的概念证明,它可以测试BorderStyle和Position的所有组合,而无需为每个组合明确编码。您可以添加更多属性并随意使用。像CodeSite这样的工具也会使日志记录更清晰,更容易。

使用2个表单创建一个应用程序。确保第二个不是自动创建的。

在第二种形式中,添加一个属性并在表单的Resize事件中添加一些日志记录代码:

  private
    FOnResizeFired: TNotifyEvent;
  public
    property OnResizeFired: TNotifyEvent read FOnResizeFired write FOnResizeFired;
  end;

...

procedure TForm2.FormResize(Sender: TObject);
begin
  if Assigned(FOnResizeFired) then
    FOnResizeFired(self);
end;

在主窗体中,将TypInfo添加到uses子句并在窗体上放置一个按钮和一个备忘录。

添加一个简单的程序:

procedure TForm1.ResizeDetected(Sender: TObject);
begin
  Memo1.Lines.Add('    *** Resize detected');
end;

现在将以下内容添加到ButtonClick事件中:

procedure TForm1.Button1Click(Sender: TObject);
var
  lBorderStyle: TFormBorderStyle;
  lBorderStyleName: string;
  lPosition: TPosition;
  lPositionName: string;
  lForm: TForm2;
begin
  Memo1.Clear;
  for lBorderStyle in [low(TFormBorderStyle) .. high(TFormBorderStyle)] do
  begin
    for lPosition in [low(TPosition) .. high(TPosition)] do
    begin
      lBorderStyleName := GetEnumName(TypeInfo(TFormBorderStyle), Integer(lBorderStyle));
      lPositionName := GetEnumName(TypeInfo(TPosition), Integer(lPosition));
      Memo1.Lines.Add(Format('Border: %s  Position: %s', [lBorderStyleName, lPositionName]));

      Memo1.Lines.Add('  Creating form');
      lForm := TForm2.Create(self);
      try
        Memo1.Lines.Add('  Form Created');
        lForm.OnResizeFired := ResizeDetected;
        Memo1.Lines.Add('    Setting border style');
        lForm.BorderStyle := lBorderStyle;
        Memo1.Lines.Add('    Setting Position');
        lForm.Position := lPosition;
        Memo1.Lines.Add('    Showing form');
        lForm.Show;
        Memo1.Lines.Add('    Form Shown');
        lForm.Close;
        Memo1.Lines.Add('    Form Closed');
      finally
        FreeAndNil(lForm);
        Memo1.Lines.Add('    Form Freed');
      end;
    end;
  end;
end;

你会注意到在显示表单之前设置某些属性时会调整大小,并且我看到在某些组合中,当显示表单时,resize似乎会触发两次。有趣。