How to change the default CDialog font for a modeless dialog?

You must disable the "ClearType" property of the default font for all dialog box controls. This can be done for one control by setting

logfont.lfQuality = ANTIALIASED_QUALITY 

There are many suggestions on how to do the same for modal dialogs ( http://neelaakash.wordpress.com/2007/12/31/change-default-dialog-font-of-cdialog/ and others), but this should be done for modeless dialogs (created using new methods and Create (...)). I myself tried to do this:

Override the Create method and change the dialog template:

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

This method does not seem to do anything (it is called, I checked this by setting a breakpoint inside). I tried to call

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

... but got a lot of BELIEF.

I also tried to override the OnSetFont method:

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

This causes ASSERT at runtime and results in the use of a VERY large font (lost default font settings, does not accept new settings) ... I don’t know why.

Please advise how can I change the default font of the dialog box that will be "inherited" by all controls?

Many thanks.

+4
source share
1 answer

First of all: a simple and reliable way to do this is to create a dialog, and then send WM_SETFONT (or call SetFont() ) to the dialog and each control in it. I will show you how to do this below, but first, why the two strategies that you have already tried did not work (and cannot):

Change dialog template

First, you must call CDialog::CreateIndirect() if you want to use the dialog template that you have already loaded.

But don't worry. The dialog template contains only the name of the face and the size of the point - it does not allow you to specify other LOGFONT values, such as lfQuality . If that were the case, you could simply indicate this in your resource definition and not write code at all at run time!

Interception WM_SETFONT

In theory, you could do this job. But this is not practical. Your code has several problems: first you must intercept this message for each child control so that it can do something useful: the dialog itself probably does not display the text. But, even worse, you pass the original font to the base class (which passes it to the standard window procedure, which stores it internally for later use), and then immediately destroys it - this means that the dialog (and everything else using this font, including all child controls) will try to draw the text using a dummy font, and return to the default font as a result. Finally, you create a new font attached to a temporary object ( pFont ) created and destroyed by MFC, inside the CFont object you are working with, it will be separated from the font descriptor and destroyed, skipping the descriptor that uses nothing.

Leak of abstractions: note on HFONT and CFont

HFONT is the type of handle that Windows uses to represent a font object. Like most GDIs, there are special functions for creating fonts and the DeleteObject() function for destroying them.

CFont is a lightweight wrapper class for HFONT. A CFont instance can be attached and disconnected from an existing HFONT or used to create a new one. If the CFont instance is still bound to HFONT when its deconstructor executes, it calls DeleteObject() to destroy the underlying object. Internally, MFC uses temporary instances of CFont that are attached and disconnected from HFONT when various message handlers (such as OnSetFont) are called. It is worth remembering that inside Windows, Windows knows nothing about CFont, and one HFONT can belong to 0 or more instances of CFont at any given time.

Fonts and WM_SETFONT notes

When you create a new font - regardless of whether it is completed in a CFont object - you own this font, and it is your responsibility to destroy it as soon as you finish using it. Passing it to WM_SETFONT ( CWnd::SetFont() ) does not change the owner! This is actually very useful, as it allows you to transfer the same font to multiple windows without worrying about which one will destroy it - you still own it, and therefore you can (and should) destroy it yourself (if not) windows that still use it).

Finally - how to quickly create and install a font in a dialog box and all its children

So, now you should have enough background to understand the necessary steps:

  • Create a dialogue
  • Create the desired font
  • Pass the font in the dialog box and its children (by sending WM_SETFONT messages or by calling CWnd :: SetFont ... which itself sends the WM_SETFONT message).
  • When the dialogue is destroyed, also destroy your font.

Example

 // 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; } 
+6
source

Source: https://habr.com/ru/post/1316183/


All Articles