Ide Indy Delphi

Title: Cure to Delphi's defective size constraints handling.
Question: I hate that resizing from the top left corner of a form and once I hit the constraint it moves the whole window... All Borland products seem to do that. Maybe I want me program to look and work nice and.. ahem, professional... Here's my (so far perfect) cure.
Answer:
First thing's first. This is my second article so bare with me here. This is a 'simple' fix to a complex problem. VCL takes into account every property and control the form has. I just made it so the window doesn't get bigger than I want or smaller, it's flawless for that (I think). Please leave comments on what you've managed to do with it to share that with others and leave a rating to help people notice (or ignore) this article.
Don't expect...
..the window to take into account controls that have constraints
..this to work perfectly right out of the box
..to understand this fully
..this to be easy to implement
..this to be released as a component
..there to be a completed and working unit that you can copy and paste
Alright, Step 1 --------------------------
Open the form of your choice, create these events from the event's tab in the object inspector for your TForm: OnCreate, OnDestroy, OnResize.
NOTE: If any of those events exist, apply the code later in this article to the beginning of the procedure.
View the unit for the form and add the declarations that are missing:
TForm1 = class(TForm)
. . .
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormResize(Sender: TObject);
private
{ Private declarations }
. . .
public
{ Public declarations }
. . .
Constraints: TSizeConstraints;
procedure FormConstraintsChange(Sender: TObject);
procedure FormSizing(var Message: TMessage); message WM_SIZING;
end;
Place your cursor somewhere in the class declaration and hit Ctrl+Shift+C, this will automatically create those procedures.
Step 2 --------------------------
Construct and free the Constraints variable and assign some values for the constraints and set the notify event procedure for changing the constraints:
procedure TForm1.FormCreate(Sender: TObject);
begin
Constraints := TSizeConstraints.Create(Self);
Constraints.OnChange := FormConstraintsChange;
with Constraints do begin
MinWidth := 250;
MaxWidth := 475;
MinHeight := 275;
MaxHeight := 400;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Constraints.Destroy
end;
Next, insert this code into the FormConstraintsChange procedure. Read the comments.
procedure TForm1.FormConstraintsChange(Sender: TObject);
var
ARect, BRect: TRect;
Message: TMessage;
begin
GetWindowRect(Handle, ARect);
BRect := ARect;
with Message do begin
WParam := WMSZ_BOTTOMRIGHT;
LParam := Integer(@ARect);
end;
SizeLimit(Constraints, Message);
// ---------- Center Form over previous location on resize due to constraint change
// ---------- this /can/ cause the caption to disappear above the screen
if not EqualRect(ARect, BRect) then
OffsetRect(ARect, (BRect.Right - ARect.Right) div 2, (BRect.Bottom - ARect.Bottom) div 2);
// ---------- Remove above if not prefered
MoveWindow(Handle, ARect.Left, ARect.Top, ARect.Right-ARect.Left, ARect.Bottom-ARect.Top, True);
end;
Now, have the resize event call the Constraints' change procedure.
procedure TForm1.FormResize(Sender: TObject);
begin
FormConstraintsChange(nil)
end;
Finally, have the key procedure be executed while resizing the form.
procedure TForm1.FormSizing(var Message: TMessage);
begin
SizeLimit(Constraints, Message);
end;
Step 3 --------------------------
This procedure can either go into a seperate unit to be shared with all your forms and different applications or it can be placed directly under the Implementation statement (after the {$R *.RES} too). In both cases you should declare it as public with this line:
procedure SizeLimit(Constraints: TSizeConstraints; Message: TMessage);
Place this code in the place of your choice.
procedure SizeLimit(Constraints: TSizeConstraints; Message: TMessage);
var
Side: Cardinal;
Rect: PRect;
Width, Height: Integer;
LeftEdge, TopEdge: Boolean;
begin
Side := Message.WParam;
Rect := Pointer(Message.LParam);
Width := Rect.Right - Rect.Left;
Height := Rect.Bottom - Rect.Top;
LeftEdge := Side in [WMSZ_BOTTOMLEFT, WMSZ_TOPLEFT, WMSZ_LEFT];
TopEdge := Side in [WMSZ_TOPLEFT, WMSZ_TOPRIGHT, WMSZ_TOP];
if (Width 0) then
if LeftEdge then Rect.Left := Rect.Right - Constraints.MinWidth
else Rect.Right := Rect.Left + Constraints.MinWidth;
if (Width Constraints.MaxWidth) and (Constraints.MaxWidth 0) then
if LeftEdge then Rect.Left := Rect.Right - Constraints.MaxWidth
else Rect.Right := Rect.Left + Constraints.MaxWidth;
if (Height 0) then
if TopEdge then Rect.Top := Rect.Bottom - Constraints.MinHeight
else Rect.Bottom := Rect.Top + Constraints.MinHeight;
if (Height Constraints.MaxHeight) and (Constraints.MaxHeight 0) then
if TopEdge then Rect.Top := Rect.Bottom - Constraints.MaxHeight
else Rect.Bottom := Rect.Top + Constraints.MaxHeight;
end;
Step 4 --------------------------
Execute your application and test the constraints. If it fails to work then leave a comment and I'll get back to you.
Acrion Trusen
"It's not hard to stand out when the general level of competents is so low." -EMH