当最大化表单时(即使在 IDE 设计器中),Delphi 表单会出现不正确的行为,为什么?

问题描述 投票:0回答:1

这是完整 Delphi 应用程序的精简版本。 即使在Delphi7 IDE设计器中,当双击窗体的标题时,窗体也会错误地最大化,这意味着左上角将移动到屏幕坐标(0,0),但窗体并没有真正最大化。

附上两个相关文件: 错误形式F.pas 故障形式F.dfm

unit FaultyFormF;
{$O-}
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;

type
  TfrmFaultyForm = class(TForm)
    pnlControl: TPanel;
    pnlDataContainer: TPanel;
    lbl_pnlDataContainer_Left: TLabel;
  private
    { Private declarations }

  public
    { Public declarations }

  end;

var
  frmFaultyForm: TfrmFaultyForm;

implementation

uses Types;

{$R *.dfm}

end.

然后是DFM文件FaultyFormF.dfm:

object frmFaultyForm: TfrmFaultyForm
  Left = 277
  Top = 133
  Width = 899
  Height = 497
  AutoSize = True
  Caption = 'FaultyForm'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  DesignSize = (
    891
    470)
  PixelsPerInch = 96
  TextHeight = 13
  object lbl_pnlDataContainer_Left: TLabel
    Left = 200
    Top = 0
    Width = 153
    Height = 8
    Alignment = taCenter
    AutoSize = False
    Caption = 'lbl_pnlDataContainerLeft'
    Color = clLime
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentColor = False
    ParentFont = False
    Visible = False
  end
  object pnlControl: TPanel
    Left = 0
    Top = 12
    Width = 185
    Height = 458
    Anchors = [akLeft, akTop, akBottom]
    TabOrder = 0
  end
  object pnlDataContainer: TPanel
    Left = 200
    Top = 12
    Width = 691
    Height = 458
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 1
  end
end

我以前使用 Delphi IDE 的对象检查器中的 Constraints:TSizeConstraints 属性来设置 MinWidth 值,但我删除了它,因为我怀疑它可能与观察到的此表单的不正确最大化行为有关。 删除后,我在表单设计器中使用 Delphi 的“View as Text”本地菜单选项进行检查,发现 Delphi 已正确删除文本表单 DFM 数据中的所有 Constraints 行。

因此,对约束与问题有关的怀疑可能是错误的。

由于我还删除了所有 OnResize 事件处理程序,因此它们应该与不正确的最大化行为无关 - 除非有人将自己的组件安装到 Delphi IDE(我没有这样做),例如 OnResize 事件处理程序仅与 Delphi 应用程序的运行时行为相关,而不与它在 Delphi IDE 表单设计器中的行为方式相关。

在Delphi7的表单设计器中,双击表单的标题两次,首先将表单最大化,然后再次将其恢复到正常大小,这是验证是否正确设置所有可见组件的Anchors属性的好方法。

不幸的是,在较新版本的 Delphi 中,双击窗体的标题不再最大化窗体,这使得运行应用程序成为验证是否已正确设置所有可见组件的 Anchors 属性的唯一方法。

或者在较新版本的 Delphi 中是否有一些我不知道的在设计时最大化表单的技巧?

添加了屏幕截图,显示往返: 最大化 -> 正常 -> 最大化将每次往返将最大化窗口的高度减少 24 像素:

日志备忘行格式: HH:MM:SS.cc 窗口状态宽度 x 高度,其中 cc = 1/100 秒单位。 第一行是由 FormCreate() 事件处理程序生成的。

这是更新后的示例表单,首先是 PAS 文件:

unit FaultyFormF;
{$O-}
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;

type
  TfrmFaultyForm = class(TForm)
    pnlControl: TPanel;
    pnlDataContainer: TPanel;
    lbl_pnlDataContainer_Left: TLabel;
    pnlInfoScreen: TPanel;
    pnlInfoForm: TPanel;
    Label1: TLabel;
    lblScreenWidth: TLabel;
    lblScreenHeight: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label2: TLabel;
    lblFormWidth: TLabel;
    lblFormHeight: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    memLog: TMemo;
    procedure FormResize(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }

  public
    { Public declarations }

  end;

var
  frmFaultyForm: TfrmFaultyForm;

implementation

uses Types;

{$R *.dfm}

const
  WindowStateNames : Array[TWindowState] of String = ('wsNormal', 'wsMinimized', 'wsMaximized');

function TimeStr:String;
begin
  Result := FormatDateTime('hh:nn:ss.zzz', Now);
  Result[Length(Result)] := ' ';  // remove the 3rd decimal of seconds - leave only 1/100th of a second as the smallest time unit.
end;

procedure TfrmFaultyForm.FormResize(Sender: TObject);
begin
  // Form Resize:
  lblScreenWidth.Caption  := IntToStr(Screen.Width);
  lblScreenHeight.Caption := IntToStr(Screen.Height);
  lblFormWidth.Caption    := IntToStr(Width);
  lblFormHeight.Caption   := IntToStr(Height);

  // Add Form Size Info Line:
  memLog.Lines.Add( TimeStr + IntToStr(Width) + 'x' + IntToStr(Height) + ' ' + WindowStateNames[WindowState] );
end;

procedure TfrmFaultyForm.FormCreate(Sender: TObject);
begin
  memLog.Lines.Add( TimeStr + IntToStr(Width) + 'x' + IntToStr(Height) + ' ' + WindowStateNames[WindowState] + ' FormCreate()' );
end;

end.

这是更新后的 DFM 文件:

object frmFaultyForm: TfrmFaultyForm
  Left = 277
  Top = 133
  Width = 899
  Height = 497
  AutoSize = True
  Caption = 'FaultyForm'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnResize = FormResize
  DesignSize = (
    891
    470)
  PixelsPerInch = 96
  TextHeight = 13
  object lbl_pnlDataContainer_Left: TLabel
    Left = 200
    Top = 0
    Width = 153
    Height = 8
    Alignment = taCenter
    AutoSize = False
    Caption = 'lbl_pnlDataContainerLeft'
    Color = clLime
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentColor = False
    ParentFont = False
    Visible = False
  end
  object pnlControl: TPanel
    Left = 0
    Top = 12
    Width = 185
    Height = 458
    Anchors = [akLeft, akTop, akBottom]
    TabOrder = 0
  end
  object pnlDataContainer: TPanel
    Left = 200
    Top = 12
    Width = 691
    Height = 458
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 1
    object pnlInfoScreen: TPanel
      Left = 16
      Top = 16
      Width = 201
      Height = 161
      TabOrder = 0
      object Label1: TLabel
        Left = 8
        Top = 8
        Width = 37
        Height = 13
        Caption = 'Screen:'
      end
      object lblScreenWidth: TLabel
        Left = 104
        Top = 28
        Width = 72
        Height = 13
        Caption = 'lblScreenWidth'
      end
      object lblScreenHeight: TLabel
        Left = 104
        Top = 48
        Width = 75
        Height = 13
        Caption = 'lblScreenHeight'
      end
      object Label4: TLabel
        Left = 8
        Top = 28
        Width = 31
        Height = 13
        Caption = 'Width:'
      end
      object Label5: TLabel
        Left = 8
        Top = 48
        Width = 34
        Height = 13
        Caption = 'Height:'
      end
    end
    object pnlInfoForm: TPanel
      Left = 16
      Top = 192
      Width = 201
      Height = 161
      TabOrder = 1
      object Label2: TLabel
        Left = 8
        Top = 8
        Width = 26
        Height = 13
        Caption = 'Form:'
      end
      object lblFormWidth: TLabel
        Left = 104
        Top = 28
        Width = 61
        Height = 13
        Caption = 'lblFormWidth'
      end
      object lblFormHeight: TLabel
        Left = 104
        Top = 48
        Width = 64
        Height = 13
        Caption = 'lblFormHeight'
      end
      object Label7: TLabel
        Left = 8
        Top = 28
        Width = 31
        Height = 13
        Caption = 'Width:'
      end
      object Label8: TLabel
        Left = 8
        Top = 48
        Width = 34
        Height = 13
        Caption = 'Height:'
      end
    end
    object memLog: TMemo
      Left = 240
      Top = 8
      Width = 441
      Height = 345
      ScrollBars = ssVertical
      TabOrder = 2
      WordWrap = False
    end
  end
end

更新的问题:

  1. 添加了屏幕截图

  2. 添加了 PAS 和 DFM 文件的修改版本。

屏幕尺寸:1600 x 900 像素。 不使用 Windows 操作系统显示缩放。

并且,其他 Delphi 窗体行为正确(除了原始的错误窗体,这是一个简化的精简版本)。

user-interface delphi vcl
1个回答
0
投票

使用您的代码我能够重现该问题。

您在 Delphi 中遇到了一个众所周知的、几十年前的“无法修复” bug。

解决方法是在设计时将表单的 AutoSize 属性设置为 False

这可以让表单在运行时和设计时正确最大化:

我猜扶手椅评论者正在以标准 DPI 运行。

© www.soinside.com 2019 - 2024. All rights reserved.