Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to get the preferred size of Windows controls

I need to figure out the preferred size — both width and height — of controls in the Windows API. As far as I can tell, the only official word on the matter is the Layout page of the Windows Desktop Program Guidelines, a document seemingly introduced with Windows Vista, and the Microsoft Management Console docs equivalent, which the former appears to be based on.

The former page gives example sizes in both dialog units and pixels (something not in the latter page!) ostensibly for 9-point Segoe UI at 96 dpi. I don't know if the dialog unit calculations were never updated for this new DPI value or not, but regardless, I tried three different approaches, and nothing adds up exactly.

This program computes in two ways, both based on the information here and here. The first uses the tmAveCharWidth field of the TEXTMETRICS structure; the second uses the GetTextExtentPoint32() function in the first link. Then, it repeats the process, taking the ancient System font into consideration (see the first link).

Running this program on Windows 7 with

  • BUTTON_SIZE_X kept at 50 (the listed width of several things)
  • BUTTON_SIZE_Y changed to 25 (the listed height of the Vista-and-up-only Command Link with one line of text)

such that our expected size based on the Layout page would be 75x41 yields

GetTextExtentPoint32: Segoe UI 9 | baseX 7 baseY 15 | button 50 x 25 -> 88 x 47
tm.tmAveCharWidth:    Segoe UI 9 | baseX 6 baseY 15 | button 50 x 25 -> 75 x 47
with system font: System 9
GetTextExtentPoint32: Segoe UI 9 | cX 7 cY 15 sysX 8 sysY 16 | button 50 x 25 -> 87 x 46
tm.tmAveCharWidth:    Segoe UI 9 | cX 6 cY 15 sysX 7 sysY 16 | button 50 x 25 -> 85 x 46

Already we can see four different possible conversions from dialog units to pixels.

The second program just makes a dummy dialog box and calls MapDialogRect() to get the baseX and baseY coordinates in the above. This yields

Segoe UI 9 weight:400 italic:0 charset:1
[0 0 8 16]

and if we manually do the calculations the first program did:

width  - (50*8)/4 = 100
height - (25*16)/8 = 50

I'm wondering if all the calculations (including the one for Command Links) used Tahoma or MS Sans Serif, the fonts used before Vista... but then I don't know what the correct size is!

And that still leaves controls like check boxes and static text controls (and command links!) that don't have a listed width or width formula. Sure, for static text controls I could just get the width of the text and say that's the preferred width, but that doesn't take into account any possible horizontal padding provided by the control. And that doesn't answer for checkboxes, where there's extra width for the checkbox part. (I did find some ways to find those coordinates, particularly on Stack Overflow, but they all have their drawbacks). Not even the MMC docs I mentioned at the top of this question say much (or worse, to make things as wide as possible; if this is to fit the dialog box, that totally works when I'm trying to figure out how wide to make the dialog box in the first place!).

What's more, when Microsoft created the version 6 Common Controls library, they decided to include messages for determining the proper size of controls! ...only some controls:

  • BCM_GETIDEALSIZE - push buttons; listed as ineffective for other types of buttons
  • DTM_GETIDEALSIZE - date/time pickers
  • LM_GETIDEALSIZE - hyperlinks; only returns height for a given width
  • RBBIM_IDEALSIZE - ReBar controls; actually not a message but something else
  • TB_GETIDEALSIZE - toolbars

Now what about comparing against controls in Windows? Well things already do look correct on Windows XP, but Winodws 7's dialogs and other controls are amazingly inconsistent (some still use Tahoma or even MS Sans Serif as dialog fontS!) and I can never be sure what button size is right.

So what I want to know is any combination of:

  • which of the five calculation methods is truly correct, if the examples on the Layouts page are not?
  • is/was there a more authoritative reference on control sizing (and ideallys pacing as well) than the incomplete Layout and MMC Layout pages?
  • was there such a reference that predated Vista that could also provide clues?
  • or is all this just hopeless and I have to pick somehting htat just looks wrong to me no matter what?
like image 236
andlabs Avatar asked Jun 09 '14 23:06

andlabs


1 Answers

Just some clues:

1. To get the preferred size of windows control:

If visual-style is on, use GetThemePartSize, otherwise you need to develop you our routine to calculate the preferred size. Please refer Firefox's source code.

2. How to layout the controls:

or how to determine the right size and right position for a control. It's not a simple problem, you'd need to develop your own layout management system just as other UI system does. Take android as an example,

  1. It need to measure the control's size based on current window's size and its own layout parameters(fixed-size/fill-parent/warp-content). For text button it need to measure the size of text.
  2. If the sum of all children size overflows the window's size, it need do some coordination.
  3. Finally set the right size and position for the control.

There are many different layout requirements for an application, so android develop a lot of layout managers such as LinearLayout, GridLayout etc. So does it for Windows UI layout system and all other UI layout systems.

You need to write a lot of code do this right. Please refer to source code of chrome/firefox UI system.

3. Solution:

I think you'd better use some existing UI system such as QT/Vxwidgets to do Windows control layout.

like image 162
Jichao Avatar answered Nov 05 '22 21:11

Jichao