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 buttonsDTM_GETIDEALSIZE
- date/time pickersLM_GETIDEALSIZE
- hyperlinks; only returns height for a given width
RBBIM_IDEALSIZE
- ReBar controls; actually not a message but something elseTB_GETIDEALSIZE
- toolbarsNow 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:
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,
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With