在Delphi中禁用表单调整大小

20

有没有办法阻止用户调整表单的大小?

目前我正在使用:

当表单大小改变时....

MainForm.Height := 761;
MainForm.Width := 777;

但是这个看起来很糟糕,因为当用户尝试改变表单大小时,它会闪烁。


1
你不能捕获WM_RESIZE事件并将其吞噬吗?我敢打赌今晚在我回家之前会有其他人发布一些代码,但如果没有的话,我稍后会发布一些。我99%确定我以前做过这件事。 :-) - robsoft
1
你指的事件是 wm_Size,@Robsoft,但它是一种通知而不是命令。一旦您收到了该消息,就太晚了,因为窗口的大小已经改变了。 - Rob Kennedy
3个回答

41

固定窗口大小很容易,有两种方法:

  1. Delphi窗体有一个BorderStyle属性和一个BorderIcons属性。如果你将BorderStyle设置为bsDialog,并且将BorderIcons设置为只有biSystemMenu,则用户无法调整窗体大小。

  2. 你可以指定Constraints属性的值。如果你将MinWidthMaxWidth写成相同的数字,则宽度将被固定。

防止移动就有点棘手了。我现在只能想到以下几种解决方案:

  1. BorderStyle设置为bsNone。如果需要,你需要自己绘制窗体标题栏。

  2. 写一个消息处理程序来处理WM_NCHITTEST消息,首先调用继承的处理程序,然后检查Message.Result是否为HTCAPTION。如果是HTCAPTION,则将其设置为HTCLIENT。这样,你欺骗Windows认为用户没有点击标题栏,因此他将无法拖动。请尝试是否仍然可以通过打开系统菜单并选择移动来移动窗口,如果是,则还需要隐藏系统菜单(BorderIcons)。

答案来源于这里


2
+1 我认为最简单的实现方式是使用约束条件。 - johnny
5
然而,约束条件存在一个非常讨厌的问题:如果你将“MinWidth”、“MaxWidth”、“MinHeight”和“MaxHeight”分别设置为相同的值,并尝试使用左侧或顶部边框调整窗体大小,则窗体不会被调整大小,而是移动位置。将“bsSingle”设为显示样式没有这个问题,而且从用户界面设计的角度来看更好(一致)。不能调整大小的窗体也不应该有调整大小的边框。 - mghie
2
@mghie。如果这个问题被修复,那么表单将不会被调整大小而是被移动。这是一个VCL的错误,看起来已经被修复了。请参见QC71595- http://qc.embarcadero.com/wc/qcmain.aspx?d=71595以获得可能的解决方法。 - Sertac Akyuz
@Sertac:是的,这是一个自从引入约束以来就存在的VCL错误,而且在过去十年中都没有得到修复。我对这个问题的答案有另一种解决方法(无需更改VCL),我一直在使用。虽然他们似乎终于修复了它,这太棒了。 - mghie

9

如果您希望表单根本不会自动调整大小,那么将表单边框样式设置为bsSingle是正确的做法,因为当鼠标移动到表单边框上时,鼠标指针不会变成其中一个调整大小的指针,这样用户就可以明确地知道该表单无法调整大小。

如果您想为表单设置最小和/或最大尺寸,则bsSizeable是正确的边框样式,并且您可以使用表单的Constraints来指定限制。然而存在问题,即Constraints属性不能防止表单的调整大小,它只会在事后调整大小,以便不违反限制。这将导致负面影响,即使用左边框或上边框调整大小会移动表单。要防止出现这种情况,您需要在第一时间防止调整大小。Windows发送WM_GETMINMAXINFO消息以检索顶层窗口的最小和最大跟踪尺寸。处理并返回正确的约束条件可以解决移动表单的问题:

type
  TForm1 = class(TForm)
  private
    procedure WMGetMinMaxInfo(var AMsg: TWMGetMinMaxInfo);
      message WM_GETMINMAXINFO;
  end;

// ...

procedure TForm1.WMGetMinMaxInfo(var AMsg: TWMGetMinMaxInfo);
begin
  inherited;
  with AMsg.MinMaxInfo^ do begin
    ptMinTrackSize := Point(Constraints.MinWidth, Constraints.MinHeight);
    ptMaxTrackSize := Point(Constraints.MaxWidth, Constraints.MaxHeight);
  end;
end;

谢谢,你的解决方案帮了我大忙。 - user1556433

2
您可以在事件"OnCanResize"中添加代码:
Resize := False;

例子:

procedure TF_NameForm.FormCanResize(Sender: TObject; var NewWidth,
  NewHeight: Integer; var Resize: Boolean);
begin
  Resize := False;
end;

然而,您应该首先设置其最小值和最大值,否则这将调整窗体大小为默认的正方形窗体大小。 - Romans

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接