Lazarus

Programming => LCL => Topic started by: Tharon on September 22, 2021, 06:02:43 pm

Title: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 22, 2021, 06:02:43 pm
Hello, i've encountered a strange issue with check boxes and the font size setting of Windows.

I have recentely purchased a 1440p monitor, so i've changed various font size of windows to be more readable. To my suprise, if i change the font size for the menu setting the check boxe are affected too, changing their height and making them collide with vertically adjacent components.

There is a way to prevent this to happen ?
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 22, 2021, 06:50:42 pm
This is an example, from a tool i made some time ago.

In the left is when the tool is launched with the standard menu font size (9) and on the right is when the tool is launcher with the menu font size incresed (12).

Higher font size make the checkboxes go even lower, even making them disappear from the form.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: dseligo on September 23, 2021, 07:55:11 am
In Project options check if you selected 'Use LCL scaling (High-DPI)' and 'DPI awareness' on.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 23, 2021, 10:47:56 am
Both are off.

Anyway isn't related to DPI, the DPI of my sistem is set a 100%.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 24, 2021, 08:51:48 pm
After some test it seems the height of the Tcheckbox is fixed and depends on the system theme. Apparently can't be changed in Lazarus, both in design or runtime.

Don't know if this is a bug or it's caused by Windows.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 24, 2021, 10:15:57 pm
I don't understand these screenshots. You say the left one is with font size 9, and the right one is with font size 12. But the texts in both images have the same size. Please post unmanipulated screenshots.

Do you work with auto-sizing and anchors? You must if you change fonts. What looks correct with one font will be awfully off with another font otherwise.

It seems to me that the radiogroup is not auto-sized. Usually AutoFill=true and AutoSize=true are the correct settings for a radiogroup.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 24, 2021, 11:36:32 pm
The screenshots are not manipulated, i've only put them one near each other.

The font size i was refering isn't the one of the text, but the size of the "menu" font in windows.

As i've said in my first post, i've changed the menu font size from the Windows theme settings to have more readable menu text in Windows. After doing this the check boxes of all my lazarus programs changed size too, even at design time, even already compiled one.

No DPI have been changed in my system, and i'm not changing font in the software.
The setting i'm talking about is the one in the screenshot.

The two screenshot shows the same program (not two different version, it's the same executable) running with the two windows menu settings.

The issue isn't the radiogroup not autosized... the individuals checkboxes height of the checkboxed changed accordly to the Windows menu text size. It happens on every checkbox, not only the ones inside a radiogroup.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 24, 2021, 11:39:47 pm
OK, I understand now. Which Windows version is this? I've not seen a possibility to change the menu font for a long time (or it's buried deeply in Windows 10).

Does the RadioGroup have AutoFill=true and AutoSize=true?
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 24, 2021, 11:53:18 pm
Windows 7, but happen in Windows 10 too if the system font is enlarged in the "ease of access" settings.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 25, 2021, 12:12:10 am
Here. This is Lazarus with the program launched first with the default Windows menu text size, and then with increased Windows menu text size. I didn't change anything, only launched lazarus and loaded the project file.

The size of the checkbox height automatically changed from 19 to 25 and can't be manually resized. This happen on the compiled executable too. It doesn't matter if i compiled it when the height is 19, if i change the Windows menu text size the checkbox height changes too.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 25, 2021, 12:43:54 am
The height of the checkbox is not the problem when you make sure that the position of the items in the groupbox adjusts automatically when the font size changes.

In the attached demo I am using a Groupbox and placed some checkboxes into it. The checkboxes were not positioned with the mouse but by means of the ChildSizing property of the Groupbox - look at the settings in the Object Inspector. This way the checkboxes change their position with font size. The Groupbox itself has its AutoSize property set to true and thus can adjust its size to changes in text length and item count.

Another way to achieve this is by using the AnchorEditor.

I copied the same groupbox twice and changed the font size from 0 (default), to 12 and 16. Since the layout is auto-adjusting there is no overlap.

PS.
I also tried a TCheckGroup which uses ChildSizing internally as well. But this does not work very well - TCheckgroup is quite buggy...
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 25, 2021, 02:04:45 am
This is the look of your example if i set the windows menu text size at 24.
I didn't changed the font size with lazarus, i've only compiled it and then changed the windows theme settings.

The height of each Checkbox grow and go outside the form.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 25, 2021, 10:00:55 am
I did not want to confuse you with the AnchorEditor and thus did not auto-size the form.

You must set the form's AutoSize to true. In order to avoid all controls jumping to the upper-left corner you must anchor them so that they cannot be moved with the mouse any more:
* Open the Anchor Editor.
* Select the left groupbox. Anchor its left side to the left side of the form, and its top side to the top side of the form. Adjust the distance to the form by specifying appropriate BorderSpacing values.
* Select the center groupbox. Anchor its left side to the right side of the left groupbox, anchor its top side to the top of the form.
* Select the right groupbox. Anchor its left side to the right side of the center groupbox, anchor its top side to the top of the form.
* Set the form's AutoSize to true.
* You wont see a difference, but at runtime the size of the form is adjusted such that it always encloses the three groupboxes.

I am attaching the project in this state, as well as two screenshots taken with "Ease-of-access" setting to 100% and 225%, respectively.

In case that all this is not working for you: what is your Lazarus/FPC version? What are the DPI-settings on your two systems?
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 25, 2021, 10:14:29 am
In your second screenshot the checkbox height changed. This is exactly what i want to avoid.
Checkboxes should not change at all if the ease of access is modified, or the component is not reliable.

The program UI should remain the same on every system, regardless of the Windows settings.
Is not a matter of keep the boxes inside the form or the radiogroup, but keep them in their exact place.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 25, 2021, 10:25:08 am
happen in Windows 10 too if the system font is enlarged in the "ease of access" settings.

Be careful with this method of improving legibility of your applications. It is a system-wide settings and most programs cannot handle this correctly, not even the Windows explorer - see screenshot taken from the Explorer at 255% setting.

It is better to change the dpi of the monitor. In older Windows, the correspondig settings were named "normal fonts", "large fonts" or similar, in Win 10 it is on the "Display" page, "Change the size of apps and text" (or similar, translated from German). It is a system-wide setting, too, but handled by many programs correctly. Lazarus takes care of it by means of LCLScaling (which - as you wrote - is turned off in your application. Why? No good idea...).
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 25, 2021, 10:52:31 am
LCL scaling and DPI are disabled in my application. All the components keeps their size and positions, only checkboxes changes.

It's not a matter of improving elegibity or not. Lazarus checkboxes have issue with ease of access. I can't develop applications and just say the users "hey, don't use ease of access because you can screw the UI layout" :D

I've checked my old lazarus applications, starting from 2016 and all of them have the same issues with checkboxes.
My older Delphi applications works without issue, so it's something related to Lazarus only.


Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 25, 2021, 11:01:55 am
LCL scaling and DPI are disabled in my application. All the components keeps their size and positions, only checkboxes changes.
You're warned that your users with super-high-res retina displays of 300% or more will complain that they cannot hit the tiny 16x16 icons any more.

I've checked my old lazarus applications, starting from 2016 and all of them have the same issues with checkboxes.
My older Delphi applications works without issue, so it's something related to Lazarus only.
Just checked with Delphi XE 10.3: Delphi ignores the "ease-of-access" setting completely. The font does not change between 100% and 200% ease-of-access. Neither does the height of a checkbox change.

Well, Delphi has hard-coded fonts and font sizes. I tried to simulate that with Lazarus: I put a TLabel, a TCombobox, a TRadioButton and a TCheckbox on a form and set their Font.Size to 9 (rather than the default 0). When I now change the "Ease of access" font size the fonts in all these controls remain the same, but the height occupied by the Checkbox and RadioButton increases. This is strange and should not occur. Is this your issue?

Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 25, 2021, 11:56:41 am
Quote
I tried to simulate that with Lazarus: I put a TLabel, a TCombobox, a TRadioButton and a TCheckbox on a form and set their Font.Size to 9 (rather than the default 0). When I now change the "Ease of access" font size the fonts in all these controls remain the same, but the height occupied by the Checkbox and RadioButton increases. This is strange and should not occur. Is this your issue?

Yes, exactly.
I've tryed with font size 0 or a set value, but the result is the same. Not matter what i do, the height of the checkbox is always dictacted by the Ease of access.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 25, 2021, 12:48:41 pm
Of course, you can turn off the checkbox AutoSize since you always have the same font size. Delphi, BTW, does not have this property at all and thus works always with AutoSize off.

Just tested: when Checkbox.AutoSize is false, and Checkbox.Font.Size = (some non-zero value), then the checkbox bounds and its font do not change at all when the ease-of-access setting is modified.

Nevertheless, the dependence of the auto-sized TCheckbox.Height with non-zero Font.Size on ease-of-access setting is in error and should be addressed since under these conditions nothing changes in the checkbox with ease-of-access; it looks as if the checkbox uses the default font (Font.Size=0) as reference.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 25, 2021, 01:01:58 pm
Just tested and yes, this workaround works. Having autosize off and manually setting the font size make the height of the checkbox stable.
This is not optimal, because manually set the font size disable the parent font property, but i can dodge around it.

Thank you for the tip and your patience !
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 25, 2021, 01:18:21 pm
The procedure GetPreferredSize is responsible for determining the size of an auto-sized control. In case of the Checkbox, this is implemented in the widgetset (unit lcl/interface/win32/win32wsstdctrls) and consists of two parts: determination of the text height and determination of the checkbox symbol height - the larger one determines the overall autosize height.

Code: Pascal  [Select][+][-]
  1. class procedure TWin32WSCustomCheckBox.GetPreferredSize(const AWinControl: TWinControl;
  2.   var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean);
  3. var
  4.   iconHeight: integer;
  5. begin
  6.   if MeasureText(AWinControl, AWinControl.Caption, PreferredWidth, PreferredHeight) then
  7.   begin
  8.     Inc(PreferredWidth, GetSystemMetrics(SM_CXMENUCHECK));
  9.     // pixels spacing between checkbox and text
  10.     if ThemeServices.ThemesEnabled then
  11.       Inc(PreferredWidth, 4)
  12.     else
  13.       Inc(PreferredWidth, 6);
  14.     iconHeight := GetSystemMetrics(SM_CYMENUCHECK);
  15.     if iconHeight > PreferredHeight then
  16.       PreferredHeight := iconHeight;
  17.     if WithThemeSpace then
  18.     begin
  19.       Inc(PreferredWidth, 1);
  20.       Inc(PreferredHeight, 4);
  21.     end;
  22.   end;
  23. end;      

Debugged into this procedure I found that the text height (MeasureText(... preferredHeight)) remains constant when the font of the checkbox is nonzero and when ease-of-access changes. The iconHeight, however, does increase with the ease-of-access percentage, although it is painted always at the same height. Therefore the issue is in the call to GetSystemMetrics(SM_CYMENUCHECK) in which windows reports a value dependent on the system font. I think replacing this by a ThemeServices call could fix the issue.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 25, 2021, 07:28:57 pm
Wrote a bug report (https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/39398) so that the issue is not forgotten.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 25, 2021, 10:18:46 pm
I was able to fix the issue based on the analysis that I gave above and committed the fix to main. If you don't use Lazarus main you can patch it easily yourself:
Code: Pascal  [Select][+][-]
  1. class procedure TWin32WSCustomCheckBox.GetPreferredSize(const AWinControl: TWinControl;
  2.   var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean);
  3. var
  4.   dx: Integer;  // pixel spacing between checkbox and text
  5.   iconHeight: integer;
  6.   iconWidth: Integer;
  7.   details: TThemedElementDetails;
  8. begin
  9.   if MeasureText(AWinControl, AWinControl.Caption, PreferredWidth, PreferredHeight) then
  10.   begin
  11.     if ThemeServices.ThemesEnabled then
  12.     begin
  13.       dx := 4;
  14.       if AWinControl is TRadioButton then
  15.         details := ThemeServices.GetElementDetails(tbRadioButtonCheckedNormal)
  16.       else
  17.         details := ThemeServices.GetElementDetails(tbCheckBoxCheckedNormal);
  18.       with ThemeServices.GetDetailSize(details) do
  19.       begin
  20.         iconWidth := CX;
  21.         iconHeight := CY;
  22.       end;
  23.     end else
  24.     begin
  25.       dx := 6;
  26.       iconWidth := GetSystemMetrics(SM_CXMENUCHECK);
  27.       iconHeight := GetSystemMetrics(SM_CYMENUCHECK);
  28.     end;
  29.     Inc(PreferredWidth, iconWidth + dx);
  30.     if iconHeight > PreferredHeight then
  31.       PreferredHeight := iconHeight;
  32.     if WithThemeSpace then
  33.     begin
  34.       Inc(PreferredWidth, 1);
  35.       Inc(PreferredHeight, 4);
  36.     end;
  37.   end;
  38. end;

This code fixes also the issue that the autosized width of the checkbox was too large when the ease-of-access factor is greater than 100%. And it fixes the same issues that could be observed for TRadioButton and TToggleBox (the latter is not yet perfect because it takes a checkbox width into account in width calculation - but since fixing this would break existing code I did not touch it).
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 25, 2021, 11:46:07 pm
Thank you very much for your help.

For my actual software i've already implemented the workaround, but i will use the fix for my future projects.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: wp on September 26, 2021, 12:14:42 am
But I would like you to test the fix. There were some misunderstandings initially, and I really don't know whether it fixes your issue. I need confirmation before I dare to backport the changed code to the fixes_2_2 branch.
Title: Re: Strange behaviour of TCheckBox and Windows Menu settings
Post by: Tharon on September 26, 2021, 09:32:57 am
I've tested the fix. Yes, it fixes the issue.

Now the checkboxes remain stable both in the IDE and in the compiled executable regardless of the Ease of Access setting without having to do the workaround.
TinyPortal © 2005-2018