Delphi XE2 and later versions have a robust theming system that has a frustrating flaw: the client width and height are not reliably preserved when the theme changes the border widths for dialog boxes.
For forms that are sizeable this is not typically a problem, but for dialogs laid out statically this can look really ugly, as shown in this Stack Overflow question.
The problem in pictures
Here’s a little form, shown in the Delphi form designer. I’ve placed 4 buttons right in the corners of the form. I’m going to populate the Memo with notes on the form size at runtime.
When I have no custom style set to the project (i.e. “Windows” style), I can run on a variety of platforms and see the buttons are where they should be. Shown here on Windows 10, Windows 7 and Windows XP (just because):
But when I apply a custom style to the project — I chose “Glossy” — then my dialog appears like so, instead:
You’ll note that the vertical is adjusted but the horizontal is not: Button2 and Button4 are now chopped off on the right. Because we are using themes, the form looks identical on all platforms.
This problem has not been addressed as of Delphi XE8.
The workaround
For my needs, I found a workaround using a class helper, which can be applied to the forms which need to maintain their design-time ClientWidth
and ClientHeight
. This is typically the case for dialog boxes.
This workaround should be used with care as it has been designed to address a single issue and may have side effects.
- It will trigger resize events at load time
- Setting AutoScroll = true means that ClientWidth and ClientHeight are not stored in the form .dfm, and so this does not work.
- It may not address other layout issues such as scaled elements scaling wrongly (I haven’t tested this).
type
TFormHelper = class helper for Vcl.Forms.TCustomForm
private
procedure RestoreDesignClientSize;
end;
procedure TfrmTestSize.FormCreate(Sender: TObject);
begin
RestoreDesignClientSize;
end;
{ TFormHelper }
procedure TFormHelper.RestoreDesignClientSize;
begin
if BorderStyle in [bsSingle, bsDialog] then
begin
if Self.FClientWidth > 0 then ClientWidth := Self.FClientWidth;
if Self.FClientHeight > 0 then ClientHeight := Self.FClientHeight;
end;
end;
After adding in this little snippet, the form is now restored to its design-time size, like thus:
Success 🙂
1 thought on “Fixing the incorrect client size for Delphi VCL Forms that use styles”