How to get size of check and gap in check box?

Short answer:

enter image description here

Long Version

From MSDN Layout Specifications: Win32, we have the specifications of the dimensions of a checkbox.

It is 12 dialog units from the left edge of the control to the start of the text:

enter image description here

And a checkbox control is 10 dialog units tall:

Surfaces and Controls  Height (DLUs)  Width (DLUs)
=====================  =============  ===========
Check box              10             As wide as possible (usually to the margins) to accommodate localization requirements.

First we calculate the size of a horizontal and a vertical dialog unit:

const dluCheckBoxInternalSpacing = 12; //12 horizontal dlus
const dluCheckboxHeight = 10; //10 vertical dlus

Size dialogUnits = GetAveCharSize(dc);

Integer checkboxSpacing = MulDiv(dluCheckboxSpacing, dialogUnits.Width,  4); 
Integer checkboxHeight = MulDiv(dluCheckboxHeight,   dialogUnits.Height, 8);

Using the handy helper function:

Size GetAveCharSize(HDC dc)
{
   /*
      How To Calculate Dialog Base Units with Non-System-Based Font
      http://support.microsoft.com/kb/125681
   */
   TEXTMETRIC tm;
   GetTextMetrics(dc, ref tm);

   String buffer = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";    

   Size result;
   GetTextExtentPoint32(dc, buffer, 52, out result);

   result.Width = (result.X/26 + 1) / 2; //div uses trunc rounding; we want arithmetic rounding
   result.Height = tm.tmHeight;

   return result;
}

Now that we know how many pixels (checkboxSpacing) to add, we calculate the label size as normal:

textRect = Rect(0,0,0,0);
DrawText(dc, Caption, -1, textRect, DT_CALCRECT or DT_LEFT or DT_SINGLELINE);

chkVerification.Width = checkboxSpacing+textRect.Right;
chkVerification.Height = checkboxHeight;

enter image description here

Bonus Reading

What's a dialog unit?

A dialog is a unit of measure based on the user's preferred font size. A dialog unit is defined such that the average character is 4 dialog units wide by 8 dialog units high:

enter image description here

This means that dialog units:

  • change with selected font
  • changed with selected DPI setting
  • are not square

Note: Any code released into public domain. No attribution required.


Sorry for resurrecting this old thread. I recently found myself wondering about the exact same question. Currently, none of the answers above give a result consistent with Windows 10 for different fonts and font sizes, especially in high-DPI environments.

Instead, it seems that the correct result is obtained by

SIZE szCheckBox;
GetThemePartSize(hTheme, hDC, BP_CHECKBOX, CBS_UNCHECKEDNORMAL, &rcBackgroundContent, TS_TRUE, &szCheckBox);

for the size of the checkbox itself. And

SIZE szZeroCharacter;
GetTextExtentPoint32(hDC, L"0", 1, &szZeroCharacter);
int iGapWidth = szZeroCharacter.cx / 2;

for the width of the gap. After trying a lot of different methods inspired by the posts above, I found L"0" in the dissembly of comctl32.dll. And while it looks like a joke to me (not necessarily a good one), I suspect it's a holdover from the old days when this might have been a good enough approximation of 2DLU.

Disclaimer: While I tested the result with various fonts and different sizes on Windows 10, I have not attempted to verify that it also holds on any other (older) version of the operating system.


I'm pretty sure the width of the checkbox is equal to

int x = GetSystemMetrics( SM_CXMENUCHECK );
int y = GetSystemMetrics( SM_CYMENUCHECK );

You can then work out the area inside by subtracting the following ...

   int xInner = GetSystemMetrics( SM_CXEDGE );
   int yInner = GetSystemMetrics( SM_CYEDGE );

I use that in my code and haven't had a problem thus far ...