INF: Correct Use of the SetFont() Function in MFC

ID Number: Q85518

1.00

WINDOWS

Summary:

The SetFont() member function of the CWnd class is used to change the

font in a specified control. In order for this function to work

correctly with Windows, you must ensure that the CFont object used in

the SetFont() call does not get destroyed before the control does.

More Information:

The SetFont() function takes a CFont object as a parameter, and this

font is used as the new control's font. In the implementation of the

SetFont() function, a Windows WM_SETFONT message is sent to the

control with the font handle obtained from the CFont object.

Because Windows places restrictions on when the font handle used with

WM_SETFONT can be deleted, this same restriction applies to the CFont

object used in the SetFont() call.

Specifically, the CFont object sent to the SetFont() function should

not be destroyed before the CWnd control is destroyed. When using

SetFont(), Windows does not make a copy of the font handle. Instead,

Windows uses the font handle that is specified before drawing the

text. If the font is destroyed before the control is destroyed,

unpredictable results will occur.

For a dialog box, for example, this implies that the CFont object

should not be destroyed until the dialog box is destroyed. The best

way to ensure this is to make the CFont object a member variable of

the derived Dialog class rather than making it a local variable to one

of class's member functions. This ensures that the CFont object will

exist for the lifetime of the dialog box. When the dialog box is

destroyed, the destructor for the CFont member is automatically called

and the font handle deleted.

The best time to set the font of any dialog controls is in the

OnInitDialog member function.

The following code sample demonstrates a class derived from

CModalDialog, which uses the SetFont() member function:

Sample Code

-----------

class CMyAboutBox : public CModalDialog

{

CFont m_font; // Our CFont member

public:

// Constructor -- assume a dialog box template "ABOUTDLG"

// in the .RC file.

CMyAboutBox(CWnd* pParentWnd = NULL ) :

CModalDialog("ABOUTDLG", pParentWnd) {};

BOOL OnInitDialog();

};

// OnInitDialog() function -- will be called after the dialog box

// is created, but before it is displayed on the screen.

BOOL CMyAboutBox::OnInitDialog() {

LOGFONT lf; // Used to create the CFont.

memset(&lf,0, sizeof(LOGFONT)); // Clear out structure.

lf.lfHeight = 20; // Request a 20-pixel-high font

strcpy(lf.lfFaceName, "Arial"); // with face name "Arial".

m_font.CreateFontIndirect(&lf); // Create the font.

// Now, set the text for our control. Assume the dialog box has

// a control with ID IDC_TEXT1.

GetDlgItem(IDC_TEXT1)->SetFont(&m_font);

return TRUE;

}

Additional reference words: Microsoft Foundation Classes MFC