C++ 当父窗口被破坏时,是否有必要显式还原控件字体?

C++ 当父窗口被破坏时,是否有必要显式还原控件字体?,c++,winapi,mfc,C++,Winapi,Mfc,我在windows创建方法中使用以下代码 HANDLE hFont = ::GetStockObject(DEFAULT_GUI_FONT); m_InfoTab.SendMessage(WM_SETFONT, (WPARAM)hFont); m_InfoTab是标准的Windows/MFC选项卡控件。是否有必要保存原始字体,并在父窗口被销毁时将其还原?否,有问题的窗口(m_infoTab)负责管理其字体,并在必要时释放旧字体。无需还原原始字体。但是,您自己负责管理字体对象,即在不再使用时将其

我在windows创建方法中使用以下代码

HANDLE hFont = ::GetStockObject(DEFAULT_GUI_FONT);
m_InfoTab.SendMessage(WM_SETFONT, (WPARAM)hFont);

m_InfoTab是标准的Windows/MFC选项卡控件。是否有必要保存原始字体,并在父窗口被销毁时将其还原?

否,有问题的窗口(m_infoTab)负责管理其字体,并在必要时释放旧字体。

无需还原原始字体。但是,您自己负责管理字体对象,即在不再使用时将其删除。此处的文档相当明确:

当不再需要字体时,应用程序应调用DeleteObject函数删除字体;例如,在它破坏控件之后

在这种特殊情况下,您不会遇到任何问题,因为您通过调用来检索字体对象。这些对象由系统控制,不需要对它们调用DeleteObject(尽管它也无害)

您的应用程序是否泄漏GDI句柄可以使用任务管理器轻松验证。转到流程选项卡,选择查看->选择列。。。并勾选GDI对象。监控到位后,更改代码并使用With
UEIPERSED=1000安装计时器(每秒一次)。使用以下代码添加一个
OnTimer
处理程序:

void CMyDialog::OnTimer(UINT_PTR nIDEvent)
{
    // Retrieve the system font
    HFONT hFontSystem = (HFONT)GetStockObject( DEFAULT_GUI_FONT );
    LOGFONT lfSystem = { 0 };
    GetObject( hFontSystem, sizeof( lfSystem ), &lfSystem );
    // And construct and identical font object
    HFONT hFontNew = CreateFontIndirect( &lfSystem );
    // This will leak the font object
    m_InfoTab.SendMessage( WM_SETFONT, (WPARAM)hFontNew );

    __super::OnTimer(nIDEvent);
}

现在打开任务管理器,启动应用程序,观察GDI对象数每秒增加1。

-1因为窗口无法安全地推断“如果有必要”释放旧字体对象,它不可能管理字体对象。应用程序必须控制字体对象的生存时间。你误解了我的回答。如果您在窗口中设置了一个新字体(称为X),则该窗口(X)负责在需要释放时释放自己的字体。你在区分“应用程序”和“窗口”,而这两者并不存在。我没有误解。窗口无法推断字体是否由其单独控制。字体对象不进行ref计数,即使它们是ref计数,ref计数也可能暂时降至0,直到应用程序决定将字体对象重新用于另一个控件。简而言之,
WM_SETFONT
不会转移所有权,因此字体对象仍在应用程序的控制之下。我想我解释得不够清楚。好的,假设在窗口的
WM_CREATE
处理程序中,调用
CreateFont
来创建用于该窗口的字体。然后有人过来给你发一条
WM\u SETFONT
信息。谁删除了旧字体?您正在对原始问题施加限制,而这些限制并不存在。当然,正确构造应用程序并没有什么错。但是说一个库存MFC控件自动管理它通过
WM_SETFONT
传递的字体充其量只是误导。