代码之家  ›  专栏  ›  技术社区  ›  Budda

如何更改非模式对话框的默认CDialog字体?

  •  4
  • Budda  · 技术社区  · 15 年前

    对于所有对话框控件,必须关闭默认字体的“ClearType”属性。对于一个控件,可以通过设置

    logfont.lfQuality = ANTIALIASED_QUALITY
    

    对于模态对话,有很多建议如何做到这一点( http://neelaakash.wordpress.com/2007/12/31/change-default-dialog-font-of-cdialog/

    重写“Create”方法,并修改对话框模板:

    BOOL CActivationChildDialogLicenseInfo::Create(UINT nIDTemplate, 
                                                   CWnd* pParentWnd)
    {
      CDialogTemplate dlt;
      int nResult;
      // load dialog template
      if (!dlt.Load(MAKEINTRESOURCE(nIDTemplate))) return -1;
      // set your own font, for example “Arial”, 10 pts.
      dlt.SetFont(L"Arial", 12);
      // get pointer to the modified dialog template
      LPSTR pdata = (LPSTR)GlobalLock(dlt.m_hTemplate);
      // let MFC know that you are using your own template
      m_lpszTemplateName = NULL;
      InitModalIndirect(pdata);
      // display dialog box
      nResult = CActivationChildDialog::Create(nIDTemplate, pParentWnd);
      // unlock memory object
      GlobalUnlock(dlt.m_hTemplate);
    
      return nResult ;
    }
    

    似乎这个方法什么都不做(它被调用了,我已经检查过了,把断点放在里面)。 我试过打电话

    nResult = CActivationChildDialog::Create(NULL, pParentWnd);
    

    我还尝试重写“OnSetFont”方法:

    void CActivationChildDialogLicenseInfo::OnSetFont(CFont *pFont)
    {
        CActivationChildDialog::OnSetFont(pFont);
    
        LOGFONT logfont;
        pFont->GetLogFont(&logfont);
        LOGFONT logfont2=logfont;
        pFont->DeleteObject();
    
        logfont2.lfItalic = true;
        logfont2.lfQuality = ANTIALIASED_QUALITY;
        pFont->CreateFontIndirect(&logfont2);
    }
    

    这会在运行时导致ASSERT,并导致使用非常大的字体(丢失默认字体设置,不接受新的指定设置)。。。我不知道为什么。

    请告知,如何更改将由所有对话框控件“继承”的默认对话框字体?

    非常感谢你。

    1 回复  |  直到 15 年前
        1
  •  8
  •   Community Mohan Dere    5 年前

    首先:简单可靠的方法是创建对话框,然后发送消息 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! 这实际上非常有用,因为它允许您将同一字体传递到多个窗口,而不必担心哪个窗口会销毁它—您仍然是所有者,因此您可以(而且必须)自己销毁它(一旦没有窗口仍在使用它)。

    最后-如何快速创建和设置一个对话框及其所有子字体

    所以你现在应该有足够的背景来理解必要的步骤:

    1. 创建对话框
    2. 创建所需字体
    3. 将字体传递给对话框及其子级(通过发送WM\u SETFONT消息或调用CWnd::SETFONT。。。它本身会发送一个WM\u SETFONT消息)。
    4. 当对话框被销毁时,也要销毁字体。

    例子

    // 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;
    }