在最大化丢失分配值之前动态分配表单大小

Dynamically assigning form size before maximize loses assigned values

我有一个应用程序总是在初始时最大化。这包括将 Self.WindowState := wsMaximized; 放在主窗体的 OnCreate 中。

就在这之前,如果用户要将 window 状态更改为 wsNormal,我将分配主窗体的默认尺寸。

所以,简而言之,主窗体的 OnCreate 处理程序类似于:

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Width:= 1300;
  Height:= 800;
  WindowState:= wsMaximized;
end;

理论上,我可以在设计时分配这些维度,这就是我需要的。但是,由于我的屏幕大小,因此 IDE,如果不滚动,整个表单一眼看不到。在设计中,我将表单保持在较小的尺寸,这样我就可以看到所有内容。但是在运行时,我需要分配这些默认尺寸,然后默认最大化它。当用户将 window 状态更改为最大化时,我希望它会转到我动态分配的那些维度。

问题是它似乎在最大化表单后丢失了这些尺寸,并且恢复到设计时的任何值。如果我注释掉 WindowState:= wsMaximized; 行,那么它会以所需的默认尺寸显示表单。然而,最大化它似乎覆盖并忽略了我刚刚在它之前分配的这些值。

如何创建和显示默认最大化的主窗体,同时动态分配默认大小,而不丢失分配的值?

您必须在 FormActivate 上设置表单大小:

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  if Tag = 0 then
  begin
    // Top := 100;
    // Left := 100;
    Width:= 1300;
    Height:= 800;
    WindowState:= wsMaximized;
    Tag := 1;
  end;
end;

(与 10.3.3 确认。) 我无法确定这个问题的确切根源,但一个合理的原因是在构造函数期间正在读取表单组件并且以前的大小似乎已明确备份:

procedure TControl.SetWidth(Value: Integer);
begin
  SetBounds(FLeft, FTop, Value, FHeight);
  Include(FScalingFlags, sfWidth);
  if csReading in ComponentState then
    FExplicitWidth := FWidth;
end;

一个可能的解决方案是在 OnCreate 事件中设置所需的大小,就像您现在正在做的那样,但是推迟设置所需的 WindowsState 直到 OnShow 事件。

procedure TForm1.FormCreate(Sender: TObject);
begin
  Width := 1300;
  Height := 800;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  WindowState := wsMaximized;
end;

当然,您可能应该使用 a one-off mechanism 来防止连续调用。 请也看看wsMaximized forms do not appear maximized

显然,VCL 不存储明确的中间大小(无论如何在某些 Delphi 版本中),但似乎在实际显示表单时将更改与最大化的更改合并。

喜欢 quite correctly suggested, you can use SetWindowPlacement绕过这个VCL干扰:

procedure TForm1.FormCreate(Sender: TObject);
var
  WindowPlacement: TWindowPlacement;
begin
  GetWindowPlacement(Handle, WindowPlacement);
  WindowPlacement.rcNormalPosition := Bounds(Left, Top, 1300, 800);
  WindowPlacement.showCmd := SW_SHOWMAXIMIZED;
  SetWindowPlacement(Handle, WindowPlacement);
end;