Let’s asume you want to change the font of a window\control and for the sake of simplicity let’s consider an MFC dialog application. In that case, there are several steps you should follow:

  • declare a CFont variable in the dialog class
  • create the font in OnInitDialog (using CreateFont)
  • set the font to the control (using SetFont)

For example, say that you want to use Arial size 12 for a multiline edit control. In that case you could put the following code in OnInitDialog:

BOOL CFontSampleDlg::OnInitDialog()
{
	CDialog::OnInitDialog();   

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon   

	VERIFY(editFont.CreateFont(
		12,                        // nHeight
		0,                         // nWidth
		0,                         // nEscapement
		0,                         // nOrientation
		FW_NORMAL,                 // nWeight
		FALSE,                     // bItalic
		FALSE,                     // bUnderline
		0,                         // cStrikeOut
		ANSI_CHARSET,              // nCharSet
		OUT_DEFAULT_PRECIS,        // nOutPrecision
		CLIP_DEFAULT_PRECIS,       // nClipPrecision
		DEFAULT_QUALITY,           // nQuality
		DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
		_T("Arial")));             // lpszFacename   

	GetDlgItem(IDC_EDIT_SAMPLE)->SetFont(&editFont);   

	return TRUE;  // return TRUE  unless you set the focus to a control
}

The result should be the following:

control with Arial of wrong size

Look carefully and you’ll see that’s not the right size 12? Why? Because the height and width (which doesn’t matter in this case) parameters for CreateFont() are given in logical units and not pixels. When you passed 12 we meant pixels, so to correctly create a font of size 12 pixels, you must convert from pixels to logical units. To do that, you need to determine the number of pixels per logical inch along the screen height. For that you have to use GetDeviceCaps() with the appropriate device context. To compute the actual value, MulDiv() is used. This function multiplies two 32-bit integers and devides the 64-bit result by a third 32-bit integer.

In this case, OnInitDialog() becomes:

BOOL CFontSampleDlg::OnInitDialog()
{
	CDialog::OnInitDialog();   

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon   

	CDC* pDC = GetDC();
	int desiredHeight = 12;
	int height = -MulDiv(desiredHeight, pDC->GetDeviceCaps(LOGPIXELSY), 72);
	ReleaseDC(pDC);   

	VERIFY(editFont.CreateFont(
		height,                    // nHeight
		0,                         // nWidth
		0,                         // nEscapement
		0,                         // nOrientation
		FW_NORMAL,                 // nWeight
		FALSE,                     // bItalic
		FALSE,                     // bUnderline
		0,                         // cStrikeOut
		ANSI_CHARSET,              // nCharSet
		OUT_DEFAULT_PRECIS,        // nOutPrecision
		CLIP_DEFAULT_PRECIS,       // nClipPrecision
		DEFAULT_QUALITY,           // nQuality
		DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
		_T("Arial")));             // lpszFacename   

	GetDlgItem(IDC_EDIT_SAMPLE)->SetFont(&editFont);   

	return TRUE;  // return TRUE  unless you set the focus to a control
}

and the result is:

Arial with correct size 12 pixels

and that is what we wanted in the first place.

, , , , , Hits for this post: 17074 .