Restrict form resize -- Delphi

http://www.delphipages.com/forum/showthread.php?t=58391

Hi,

How would I restrict a form from being resized smaller than say a height of 400 and a width of 600?

I am looking for the most effecient code possible that does not produce any flickering when trying to resize below the set limits.

Thanks,

Dan

Hi,
This is the simplest example:

procedure TForm1.FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean);
begin
  if NewHeight < 400 then
    Resize := False;
  if NewWidth < 600 then
    Resize := False;
end;

The form doesn‘t flicker at all, on my PC at least, but, if only the height, for example is less than 400, the whole thing stops resizing until you let go and start again. Try it to see what I mean.

I think we‘re close, but there is a slight problem. If you resize it really quick, the form will actually stop resizing even before it hits the size limits. I think this has to do with the mouse moving faster than the form.

You can reproduce this by the following.

Make the form much wider than 600. Then grab the right side of the form and move your mouse really fast to the left. Then, let go and try and resize it again. You‘ll find that there is still room left to resize.

I know this is a little nit picky, but it‘s little details like this that make a better product.

Any other ideas?

Thanks,

Dan

Hi,
Here‘s a revised version, killed the bug, should work nicely, does for me:

procedure TForm1.FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean);
begin
if (NewHeight < 400) or (NewWidth < 600) then
begin
  Resize := False;
  if NewHeight < 400 then
  begin
    NewHeight := 400;
    Resize := True;
  end;
  if NewWidth < 600 then
  begin
    NewWidth := 600;
  Resize := True;
 end;
end;
end;

Tsk tsk tsk...this is one of the disadvantages of growing up on OOP...er...nvm...so...this is the correct way of how to restrict resizing after a certain limit:

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

procedure TForm1.WMGetMinMaxInfo(var MinMaxInfo: TWMGETMINMAXINFO);
begin
  with MinMaxInfo.MinMaxInfo^ do
  begin
    ptMinTrackSize.X := 600; //Min limit for width
    ptMinTrackSize.Y := 400; //Min limit for height
    { ptMaxTrackSize.X := 1000; //Max limit for width
    ptMaxTrackSize.Y := 1000; //Max limit for height}
  end;
end;

With this code your form can‘t be size smaller than 600x400 and if you remove the comment marks then you can‘t size the form larger than 1000x1000 pixels...

Hope that helps...

http://www.delphigroups.info/2/3b/429380.html

In Delphi 3 (I can‘t remember if Delphi 1 and 2 had the OnResize event), use  the form‘s OnResize event:

const
  FormMaxWidth  : integer = 400;
  FormMaxHeight : integer = 300;
procedure MainFormOnResize(Sender: TObject);
begin
if (Sender as TForm).Width > FormMaxWidth then
  (Sender as TForm).Width := FormMaxWidth;
if (Sender as TForm).Height > FormMaxHeight then
  (Sender as TForm).Height := FormMaxHeight;
end; 

You can also use the same technique to implement a minimum width and/or  height for the form.

In Delphi 4, use the form‘s Constraints property; see the help file for more info.

I think an OnResize event handler will only act AFTER the resize has taken place.

So you will have the form the right size, but it will be seen to snap-back.

To prevent a form going above/below a set size when resizing, set up a  procedure, in the form‘s Protected section, to connect with the wm_GetMinMaxInfo message.

When resizing, the form will act normally until the limits are reached, then it will not resize any more.

For more size, position elements of a form you can restrict, check MinMaxInfo in the Windows 32 API helpfile.

Interface
TForm1 = Class(TForm)
    {All the usual form stuff, component names, etc.. would be in here}
    {You will have to add the PROTECTED heading yourself}
Protected   {Protected Declarations}
   Procedure GetMinMax(Var MinMaxMessage: TWMGetMinMaxInfo); Message
wm_GetMinMaxInfo;
End;{TForm1}
Implementation
Procedure TForm1.GetMinMax(Var MinMaxMessage: TWMGetMinMaxInfo);
Begin
  With MinMaxMessage.MinMaxInfo^ Do {Set window resize limits}
  Begin
    ptMinTrackSize.x:=300;    {Put the widths/heights in pixels}
    ptMinTrackSize.y:=200;
    ptMaxTrackSize.x:=600;
    ptMaxTrackSize.y:=400;
  End;{WITH}
End;{*.GetMinMax*} 

http://stackoverflow.com/questions/2538525/disable-form-resizing-in-delphi

Fixing the size is easy, you have two options:

  1. Delphi forms have a BorderStyle property and a BorderIcons property. If you set BorderStyle to bsDialog, and BorderIcons to biSystemMenu only, user can not resize the form.
  2. You can specify value to Constraints property. If you write the same number to MinWidth and MaxWidth, the width will be fixed.

Preventing move is more tricky. I can come up with only these solutions now:

  1. Set BorderStyle to bsNone. You will need to draw the form caption yourself, if needed.
  2. Write a message handler to WM_NCHITTEST, call inherited first, then check the Message.Result for HTCAPTION. If it is HTCAPTION, set it to HTCLIENTinstead. This way, you fool Windows to think the user didn‘t click on caption, so he will not be able to drag. Please try if the user can still move the window opening the system menu, and choosing Move. If so, you have to hide the system menu too (BorderIcons).

Answer found here.

If you want your form to not resize at all, then setting the form border style to bsSingle is the right thing to do, as then the mouse cursor will not change to one of the sizing cursors when moved over the form borders, so it is obvious to the user that this form can not be resized.

If you want to set a minimum and / or a maximum size for the form, then bsSizeableis the correct border style, and you can use the Constraints of the form to specify the limits. There is however the problem that the Constraints property doesn‘t prevent the resizing of the form, it only causes the sizes to be adjusted after the fact so that the limits are not violated. This will have the negative side effect that sizing the form with the left or upper border will move it. To prevent this from happening you need to prevent the resizing in the first place. Windows sends the WM_GETMINMAXINFOmessage to retrieve the minimum and maximum tracking sizes for a top level window. Handling this and returning the correct constraints fixes the moving form issue:

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;

http://www.angelfire.com/home/jasonvogel/delphi_source_limiting_a_forms_size.html

This is a demonstration how to limit the form size during resize and the forms position and size when it‘s maximized.

1. Add this line to the private section of the form declaration.

procedure WMGetMinMaxInfo( var Message :TWMGetMinMaxInfo ); message WM_GETMINMAXINFO;

2. Add this to the implementation part:

procedure TForm1.WMGetMinMaxInfo( var Message :TWMGetMinMaxInfo );
begin
  with Message.MinMaxInfo^ do
  begin
    ptMaxSize.X := 200;                {Width when maximized}
    ptMaxSize.Y := 200;                {Height when maximized}
    ptMaxPosition.X := 99;             {Left position when maximized}
    ptMaxPosition.Y := 99;             {Top position when maximized}
    ptMinTrackSize.X := 100;           {Minimum width}
    ptMinTrackSize.Y := 100;           {Minimum height}
    ptMaxTrackSize.X := 300;           {Maximum width}
    ptMaxTrackSize.Y := 300;           {Maximum height}
  end;
  Message.Result := 0;                 {Tell windows you have changed minmaxinfo}
  inherited;
end;

NOTE!

In windows 95 the screen size can change during runtime.

If the Scaled property of the form is true then component size and position can change.

The WM_GETMINMAXINFO message is sent to a window

whenever Windows needs the maximized position or dimensions of the window

or needs the maximum or minimum tracking size of the window.

The maximized size of a window is the size of the window when its borders are fully extended.

The maximum tracking size of a window is the largest window size that can be achieved by using the borders to size the window.

The minimum tracking size of a window is the smallest window size that can be achieved by using the borders to size the window.

Windows fills in a TMINMAXINFO data structure, specifying default values for the various positions and dimensions.

The application may change these values if it processes this message.

An application should return zero if it processes this message.

type
  TPoint = record
    x: Integer;
    y: Integer;
  end;
  TMinMaxInfo = record
    ptReserved: TPoint;
    ptMaxSize: TPoint;
    ptMaxPosition: TPoint;
    ptMinTrackSize: TPoint;
    ptMaxTrackSize: TPoint;
  end;
  TWMGetMinMaxInfo = record
    Msg: Cardinal;
    Unused: Integer;
    MinMaxInfo: PMinMaxInfo;
    Result: Longint;
  end;

The TWMGetMinMaxInfo type is the message record for the WM_GETMINMAXINFO message.

The TMINMAXINFO structure contains information about a window‘s maximized size and position and its minimum and maximum tracking size.

ptReserved Reserved for internal use.

ptMaxSize Specifies the maximized width (point.x) and the maximized height (point.y) of the window.

ptMaxPosition Specifies the position of the left side of the maximized window (point.x) and the position of the top of the maximized window (point.y).

ptMinTrackSize Specifies the minimum tracking width (point.x) and the minimum tracking height (point.y) of the window.

ptMaxTrackSize Specifies the maximum tracking width (point.x) and the maximum tracking height (point.y) of the window.

The TPOINT structure defines the x- and y-coordinates of a point.

In some cases, developers would want to create a regular window (Form) in Delphi that contains some of the characteristics of a dialog box.

For example, they do not want to allow their users to resize the form at runtime due to user interface design issues.

Other than creating the whole form as a dialog box, there is not a property or a method to handle this in a regular window in Delphi.

But due to the solid connection between Delphi and the API layer, developers can accomplish this easily.

The following example demonstrates a way of handling the Windows message "WM_GetMinMaxInfo"

which allows the developer to restrict the size of windows (forms) at runtime to a specific value.

In this case, it will be used to disable the functionality of sizing the window (form) at runtime. Consider the following unit:

unit getminmax;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
    procedure WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo);
              message WM_GETMINMAXINFO;
    procedure WMInitMenuPopup(var Msg: TWMInitMenuPopup);
              message WM_INITMENUPOPUP;
    procedure WMNCHitTest(var Msg: TWMNCHitTest);
              message WM_NCHitTest;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

 procedure TForm1.WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo);
 begin
     inherited;
     with Msg.MinMaxInfo^ do
     begin
          ptMinTrackSize.x:= form1.width;
          ptMaxTrackSize.x:= form1.width;
          ptMinTrackSize.y:= form1.height;
          ptMaxTrackSize.y:= form1.height;
     end;
 end;

 procedure TForm1.WMInitMenuPopup(var Msg: TWMInitMenuPopup);
 begin
      inherited;
      if Msg.SystemMenu then
         EnableMenuItem(Msg.MenuPopup, SC_SIZE, MF_BYCOMMAND or MF_GRAYED)
 end;

 procedure TForm1.WMNCHitTest(var Msg: TWMNCHitTest);
 begin
      inherited;
      with Msg do
           if Result in [HTLEFT, HTRIGHT, HTBOTTOM, HTBOTTOMRIGHT,
                     HTBOTTOMLEFT, HTTOP, HTTOPRIGHT, HTTOPLEFT] then
              Result:= HTNOWHERE
 end;
end.  { End of Unit}

A message handler for the windows message "WM_GetMinMaxInfo"

in the code above was used to set the minimum and maximum TrackSize of the window

to equal the width and height of the form at design time.

That was actually enough to disable the resizing of the window (form),

but the example went on to handle another couple of messages just to make the application look professional.

The first message was the "WMInitMenuPopup" and that was to gray out the size option from the System Menu

so that the application does not give the impression that this functionality is available.

The second message was the "WMNCHitTest" and that was used to disable the change of the cursor icon

whenever the mouse goes over one of the borders of the window (form) for the same reason

which is not to give the impression that the resizing functionality is available.

时间: 2024-10-17 01:25:32

Restrict form resize -- Delphi的相关文章

Delphi ActiveX Form的使用实例

Delphi ActiveX Form的使用实例 By knityster 1. ActiveX控件简介 ActiveX控件也就是一般所说的OCX控件,它是ActiveX技术的一部分. ActiveX控件可以被集成到很多支持ActiveX的应用当中去,或者直接用来扩展应用的功能,这些支持ActiveX的应用包括C++ Builder.Delphi.Visual dBASE. Visual Basic.Visual C++.Internet Explorer.Netscape Navigator等

Delphi与Javascript的交互

网络上也有人写了关于Delphi与Javascript的文章,其大多数使用ScriptControl等,均无法达到与Delphi自身融合的效果.我也是在翻阅自己的组件库的时候发现了这个以前收集来的代码.这个主要是使用了Mozilla的Javascript引擎,所以在程序运行的时候必须带上js3215R.dll和msvcr70.dll这两个动态链接库. 现在我们来看一看几个例子: 例程1: 说明:该例程主要是把Javascript代码以字符串的形式内置在Delphi程序代码内,然后与Delphi交

DELPHI的编译指令

DELPHI的编译指令 {$IFDEF WIN32} -- 这可不是批注喔! 对于Delphi来说﹐左右大括号之间的内容是批注﹐然而「{$」(左括号后紧接着货币符号)对于Compiler(编译器)而言并不是批注﹐而是写给Compiler看的特别指示. 应用时机与场合 Delphi中有许许多多的Compiler Directives(编译器指令)﹐这些编译指令对于我们的程序发展有何影响呢? 它们又能帮我们什么忙呢? Compiler Directive 对程序开发的影响与助益, 可以从以下几个方向

【技术分享】很详细的JS底层分析

1. 序言现在学的东西很容易忘记,写这篇文章的目的是能让我在需要时快速找回当时的感觉. 入门学习和参考手册建议翻阅JavaScript.The.Definitive.Guide.5th.Edition的附录(有电子版). 2. 准备设置服务器*.xml的MIME为text/xml ,Windows Xp自带的IIS的设置如下图 js_0000.png Firefox上有许多插件是开发必备的,用法大家Google,我列一下名称 FireBug Web Developer Toolbar Greas

PYQT设计无边框窗体

#UI.py,通过UI设计师制作后直接转换为UI.py脚本 # -*- coding: utf-8 -*-from PyQt4 import QtCore, QtGui try:    _fromUtf8 = QtCore.QString.fromUtf8except AttributeError:    _fromUtf8 = lambda s: s class Ui_Form(object):    def setupUi(self, Form):        Form.setObject

Raudus入门(1)

Raudus入门(1) (2013-08-09 14:38:17) 转载▼ 标签: it 分类: Delphi 基于delphi做web应用,有个Raudus,基于对ext js的封装,可以在delphi ide中,象开发普通delphi应用一样,快速制作web应用.让我们一起来看看如何做第一个Raudus应用.1.下载并安装Raudus,下载最新版本0.9.52.下载后可直接安装,安装后在delphi xe4的File->New-Other可以看到RaApplication及RaApplica

PYQT窗口居中

#UI.py,通过UI设计师制作后直接转换为UI.py脚本 # -*- coding: utf-8 -*-from PyQt4 import QtCore, QtGui try:    _fromUtf8 = QtCore.QString.fromUtf8except AttributeError:    _fromUtf8 = lambda s: s class Ui_Form(object):    def setupUi(self, Form):        Form.setObject

PYQT窗口托盘目录

#UI.py,通过UI设计师制作后直接转换为UI.py脚本 # -*- coding: utf-8 -*- from PyQt4 import QtCore, QtGui try:    _fromUtf8 = QtCore.QString.fromUtf8except AttributeError:    _fromUtf8 = lambda s: s class Ui_Form(object):    def setupUi(self, Form):        Form.setObjec

结队编程1-四则运算(95、97)

Coding地址: https://coding.net/u/huhulqq/p/jiedui1/git/tree/master/ 结队成员:                林清青 201421123095                郑莹   201421123097 一.题目要求: 本次要求把这个程序做成GUI(可以是Windows PC 上的,也可以是Mac.Linux,web,手机上的),成为一个有基本功能.一定价值的程序.在下面的功能需求中实现两个: 记录用户的对错总数,程序退出再启