4

作为这个问题的延伸:

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

在显示表单之前是否有其他因素会影响 OnResize 是否会触发?例如,可能影响此的其他属性或属性组合?

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

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

4

3 回答 3

1

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

于 2009-08-15T21:51:54.067 回答
0

我相信当一个事件发送一条消息说表单大小(左、下、宽、高)将被修改时,OnResize 会触发。

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

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

编辑:让我们去低水平。窗口中的表单(粗略地说)有所谓的“窗口类”(它不是我们所知道的类)。每当窗体的窗口类被调整大小(窗体可见)时,都会发送 WM_SIZE。

所以它不会在显示表单的所有时间都发生,但与底层窗口类相比,只有它的尺寸发生了变化。

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

这是一个非常肤浅的解释,还有很多其他细节——但这是我对事情“在幕后”如何运作的理解。

于 2009-08-06T21:21:23.477 回答
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,并且我看到在某些组合中,当显示表单时 resize 似乎会触发两次。有趣的。

于 2009-08-07T13:07:53.243 回答