簡體   English   中英

如何更改非模態對話框的默認CDialog字體?

[英]How can I change the default CDialog font for a non-modal dialog?

對於所有對話框控件,必須關閉默認字體的“ClearType”屬性。 通過設置可以對一個控件執行此操作

logfont.lfQuality = ANTIALIASED_QUALITY

有很多建議如何對模態對話框做同樣的事情( http://neelaakash.wordpress.com/2007/12/31/change-default-dialog-font-of-cdialog/等),但那應該是可以用於非模態對話框(使用new和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);

......但是得到了很多ASSERT。

我也嘗試覆蓋'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並導致使用非常大的字體(丟失默認字體設置,不接受新的指定設置)...我不知道為什么。

請指教,如何更改所有對話框控件將“繼承”的默認對話框字體?

非常感謝你。

首先:簡單,可靠的方法是創建對話框,然后將WM_SETFONT (或調用SetFont() )發送到對話框及其中的每個控件。 我將在下面告訴你如何做到這一點,但首先,這就是為什么你已經嘗試過的兩種策略沒有(也做不到)的原因:

修改對話框模板

首先,如果您希望使用已加載的對話框模板,則應調用CDialog::CreateIndirect()

但是不要打擾。 該對話框的模板包含只有面部名稱和大小-它不允許你指定其他LOGFONT值,如lfQuality 如果是這樣 ,您可以在資源定義中指定它,並避免編寫任何運行時代碼!

攔截WM_SETFONT

從理論上講,你可以做到這一點。 但這不切實際。 您的代碼有幾個問題:首先,您必須為每個子控件攔截此消息,以便它執行任何有用的操作:對話框本身可能不會呈現任何文本。 但更糟糕的是,您將原始字體傳遞給基類(將其傳遞給默認窗口過程,該過程在內部存儲以供以后使用)然后立即銷毀它 - 這意味着對話框(以及使用該字體的所有其他內容,包括所有子控件)將嘗試使用偽造字體繪制文本,並因此恢復為默認字體。 最后,您正在創建一個附加到由MFC創建和銷毀的臨時對象( pFont )的新字體 - 在內部,您正在使用的CFont對象將從字體句柄中分離並銷毀,泄漏字體對象的句柄什么都沒用。

漏洞抽象:關於HFONT和CFont的說明

HFONT是Windows用於表示字體對象的句柄類型。 像大多數GDI一樣,有用於創建字體的特定函數,以及用於銷毀它們的通用DeleteObject()函數。

CFont是HFONTs的輕量級包裝機。 CFont實例可以與現有的HFONT連接或分離,或用於創建新的實例。 如果CFont實例在解析器執行時仍然附加到HFONT,它將調用DeleteObject()來銷毀底層對象。 在內部,MFC利用在調用各種消息處理程序(例如OnSetFont)時附加和分離HFONT的臨時CFont實例。 值得記住的是,在內部,Windows對CFont一無所知,並且在任何給定的時間點,單個HFONT可能屬於0個或更多CFont實例。

關於字體和WM_SETFONT的注釋

當您創建一個新字體 - 無論它是否包含在CFont對象中 - 您是該字體的所有者,並且您有責任在完成使用后銷毀它。 將它傳遞給WM_SETFONTCWnd::SetFont() )不會改變所有權! 這實際上非常有用,因為它允許你將相同的字體傳遞給多個窗口,而不用擔心哪一個會破壞它 - 你仍然是所有者,所以你可以(並且必須)自己銷毀它(一旦沒有窗戶仍在使用它)。

最后 - 如何在對話框及其所有子對象上快速創建和設置字體

所以你現在應該有足夠的背景來理解必要的步驟:

  1. 創建對話框
  2. 創建所需的字體
  3. 將字體傳遞給對話框及其子對象(通過發送WM_SETFONT消息,或通過調用CWnd :: SetFont ...本身發送WM_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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM