Jump to content
Registration disabled at the moment Read more... ×
PiedSoftware

canvas.TextWidth not working in Win 11

Recommended Posts

Hi

 

I want to be able to expand a small modal dialog that offers the user just a combo box to the minimum size able to show all values in the dropdown list of a TComboBox. I wrote the following code to calculate the size required by the combobox:

function MaxTextWidth(canvas: TCanvas; list: TStrings): integer;
var s: string;
begin
  result := 0;
  for s in list do
    result := Max(result, canvas.TextWidth(s));
end;


procedure SetComboWidth(Combo: TComboBox);
var
  width: integer;
begin
  width :=  MaxTextWidth(Combo.Canvas, Combo.Items) + 26; // Include arrow button
  if Combo.Style = csDropDown then
    inc(width, 8);
  Combo.Width := width;
end{ SetComboWidth};

It had the desired effect on my machine, a NUC box still on good ole' Windows 10. The users however on Windows 11 find that the calculated with is not enough. The longest values were clipped. I don't know if the OS is the problem. My machine doesn't let me update.

Does this problem look familiar to anyone?

 

-- Mark
 

Edited by PiedSoftware

Share this post


Link to post

It is always a good idea to not hard code any widths related to the visual apsects of controls. They might change when the OS changes version. 


You have to get the width of the non-client area of a ComboBox so that you can add it your calculated MaxTextWidth to get a proper control width. But... ComboBox does not play nicely and getting its ClientWidth is not possible with functions like GetClientRect thus ComboBox does not have a properly calculated ClientWidth for it so you will have to make another plan to get it.

 

There is a Win32 function called GetComboBoxInfo. It returns a record with details about the combobox like size of the control, the size and position of the button and size of position of the edit control in it.

 

You will use the width of the edit control and deduct that from the width of the ComboBox and there you have the non-client area width. Just add that to the MaxTextWidth and you have the size the ComboBox should be.

 

Remember to do these calculations and setting of the ComboBox size again when the Windows theme or settings change or the font changes.

 

 

Share this post


Link to post

Another possible issue is that when you use a control's canvas outside the paint event, the font of that canvas may not be set properly.  It's good practice to set it explicitly with something like:

 

Combo.Canvas.Font := Combo.Font;

 

before calling TextWidth.  Also note that you may have to scale any hard coded pixel values based on dpi.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×