首先:简单可靠的方法是创建对话框,然后发送消息
WM_SETFONT
SetFont()
)对话框和其中的每个控件。我将在下面向您展示如何做到这一点,但首先,以下是您已经尝试过的两种策略不起作用(也不起作用)的原因:
修改对话框模板
首先,你应该打电话
CDialog::CreateIndirect()
如果希望使用已加载的对话框模板。
但别麻烦了。对话框模板只包含面名称和点大小-确实如此
不
lfQuality
做
,您只需在资源定义中指定它,就可以避免编写任何运行时代码!
WM\U设置字体
从理论上说,你可以做到这一点。但这并不实际。您的代码有几个问题:首先,您必须为每个子控件截获此消息,以便它执行任何有用的操作:对话框本身可能不会呈现任何文本。但更糟的是,你通过了考试
起初的
将字体添加到基类(基类将其交给默认窗口过程,该过程将其存储在内部供以后使用),然后立即销毁它—这意味着对话框(以及使用该字体的所有其他内容,包括所有子控件)将尝试使用假字体绘制文本,并因此还原为默认字体。最后,创建一个附加到临时对象的新字体(
pFont
)由MFC创建和销毁-在内部,您正在处理的CFont对象将从字体句柄分离并销毁,从而将句柄泄漏到一个什么都不用的字体对象。
HFONT是Windows用来表示字体对象的句柄类型。像大多数GDI一样,有创建字体的特定函数和通用函数
DeleteObject()
破坏它们的功能。
CFont是hfont的一个轻量级包装类。CFont实例可以从现有HFONT附加和分离,也可以用于创建新实例。如果一个CFont实例在解构器执行时仍然连接到一个HFONT,它将调用
DeleteObject()
销毁底层对象。在内部,MFC使用临时CFont实例,这些实例在调用各种消息处理程序(例如OnSetFont)时与hfont连接并分离。值得记住的是,在内部,Windows对CFont一无所知,单个HFONT在任何给定的时间点都可能属于0个或多个CFont实例。
当你创建一个新字体时,不管它是否包装在一个CFont对象中,你都是这个字体的所有者,一旦你使用完它,你就有责任销毁它。
Passing it to
WM_SETFONT
(
CWnd::SetFont()
) doesn't change ownership!
这实际上非常有用,因为它允许您将同一字体传递到多个窗口,而不必担心哪个窗口会销毁它—您仍然是所有者,因此您可以(而且必须)自己销毁它(一旦没有窗口仍在使用它)。
最后-如何快速创建和设置一个对话框及其所有子字体
所以你现在应该有足够的背景来理解必要的步骤:
-
创建对话框
-
创建所需字体
-
将字体传递给对话框及其子级(通过发送WM\u SETFONT消息或调用CWnd::SETFONT。。。它本身会发送一个WM\u SETFONT消息)。
-
当对话框被销毁时,也要销毁字体。
例子
// define this as a class member - class destructor then handles step four!
CFont m_nonCleartypeFont;
BOOL CActivationChildDialogLicenseInfo::Create(UINT nIDTemplate,
CWnd* pParentWnd)
{
// step one: create dialog normally
BOOL nResult = CActivationChildDialog::Create(nIDTemplate, pParentWnd);
// step two: create custom font
// relying on destructor to destroy font once we're done with it
// so be careful to only create it once!
if ( NULL == m_nonCleartypeFont.m_hObject )
{
CFont* pOriginalFont = GetFont(); // use template font as... template!
// pull information from original font
LOGFONT logfont;
pOriginalFont->GetLogFont(&logfont);
// make font adjustments:
// specify italics
logfont.lfItalic = true;
// and non-cleartype antialiasing
logfont.lfQuality = ANTIALIASED_QUALITY;
// create our font based on adjusted information
m_nonCleartypeFont.CreateFontIndirect(&logfont);
}
// step three: set our custom font on the dialog and all children
SetFont(&m_nonCleartypeFont, FALSE);
// Send message to quickly set this font for all children.
// See documentation for SendMessageToDescendants()
// - this is actually the example given!
SendMessageToDescendants(WM_SETFONT,
(WPARAM)m_nonCleartypeFont.m_hObject,
MAKELONG(FALSE, 0),
FALSE);
return nResult;
}