Mega Code Archive

 
Categories / Delphi / Ide Indy
 

Cure to Delphis defective size constraints handling

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