Click here to Skip to main content
15,880,972 members
Articles / Desktop Programming / MFC
Article

Font Properties Property Page

Rate me:
Please Sign up or sign in to vote.
3.54/5 (7 votes)
4 Oct 20045 min read 46K   2.6K   20  
Adding the functionality of the ChooseFont() function to a property sheet

Image 1
Demo app. ChooseFont() button opens the font common dialog for comparison.

Introduction

To choose a font is an easy thing. Calling ChooseFont(), or from MFC creating a CFontDialog object, will do the trick. This will open a new dialog window from which the user can select a font to be used. Now, it's not always desired to open new dialogs everywhere you go along to do things. The more windows opened, the harder to use. A lot of applications have a lot of different properties to be set, and it would be nice if all those are accessible from one dialog. E.g. cell formatting in MS Excel opens a tabbed dialog where you can set different properties. One of the tabs is the Font tab. This article describes how to achieve this.

Background

After searching the net for a solution to having a font properties dialog as a child window, nothing came up. The obvious idea is to somehow use the ChooseFont() function and add it as a child dialog. This however seems impossible. Please correct me if I'm wrong.

The second most obvious idea is to write all code yourself. That is the solution in this article. It's not all true though, some code was without regret stolen from Chris Losinger's excellent Font Combo. Also, Hans Dietrichs extension to the Font Combo, XFontCombo was checked out in order to add OpenType font type support. But since this method doesn't yield the same result as the ChooseFont() does, it was discarded.

Using the code

The main object is the class

class CFontPropertiesDialog : public CDialog
Add its resource template to your .rc file, add a bitmap to be displayed along TrueType fonts, create an instance of this class and you're done.

Step by step

Follow these step-by-step instructions to make it work.

1. Insert the bitmap, font_tru.bmp, as a new bitmap resource. Name the resource IDB_TTF_BMP.

2. Copy the dialog resource to your .rc file.

3. Make sure you have the definitions in your resource.h file. The following items should be included:

#define IDD_FONTPROPERTIES_DIALOG       130
#define IDC_STRIKEOUT_CHECK             1001
#define IDC_UNDERLINE_CHECK             1002
#define IDC_PREVIEW                     1003
#define IDC_FONTFACE_COMBO              1004
#define IDC_FONTSTYLE_COMBO             1005
#define IDC_FONTSIZE_COMBO              1006
#define IDC_SCRIPT_COMBO                1007
#define IDC_SCRIPT_STATIC               1009
#define IDC_EFFECTS_STATIC              1010
#define IDC_SAMPLE_STATIC               1011
#define IDC_FONTFACE_STATIC             1012
#define IDC_FONTSTYLE_STATIC            1013
#define IDC_FONTSIZE_STATIC             1014
(The actual number for IDD_FONTPROPERTIES_DIALOG may have to be altered to a unique value.)

4. Add a member of the CFontPropertiesDialog class, m_dlgFonf, to your main dialog, CMyDialog.

5. Initialize the dialog font data if necessary, then create and position the child dialog.

BOOL CMyDialog::OnInitDialog()
{
  CDialog::OnInitDialog();

  // Use the current dialog font as default
  LOGFONT lf;
  GetFont()->GetLogFont(&lf);
  m_dlgFont.SetLogFont(&lf);

  // Create the font page
  if (!m_dlgFont.Create(-1, this))
    return FALSE;

  // Position the child dialog
  CRect rc;
  GetClientRect(&rc);
  m_dlgFont[0].SetWindowPos(NULL, rc.left, rc.top, rc.Width(),
   rc.Height(), SWP_NOZORDER);

  return TRUE;
}

Public Interface

BOOL Create(DWORD dwEnumFlags = -1, CWnd* pParentWnd = NULL);
Creates the child dialog. The dwEnumFlags parameter describes what font types are to be enumerated, and also what visual elements should be displayed. Any combination of the following values can be used (with bitwise or):
RASTER_FONTTYPE     // Enumerate raster fonts
DEVICE_FONTTYPE     // Enumerate device fonts
TRUETYPE_FONTTYPE   // Enumerate TrueType fonts (OpenType fonts included)
FPD_DISPLAY_SCRIPT  // Display Script combo box
FPD_DISPLAY_EFFECTS // Display effects: Underline, Strikeout
FPD_DISPLAY_ALL     // Display all visual elements
void SetLogFont(const LOGFONT *lpLogFont);
You can initialize the dialog with a font. This method can alse be called after the dialog has been created to change the font displayed.
const LOGFONT& GetLogFont();
Get the currently selected font from the dialog.
void SetTextColor(COLORREF clr);
Sets the text color in the preview control. Default is black.
COLORREF GetTextColor() const;
Gets the text color currently used by the preview control.
void SetBkGndColor(COLORREF clr) { m_clrPreviewBkGnd = clr; }
Sets the background color of the preview control. Default is ::GetSysColor(COLOR_BTNFACE).

Overridables

virtual void LayOutControls();
This function is responsible for changing UI elements depending on the different display flags.

Implementation details

To get all font names from the system the EnumFontFamilyEx function is used. Then, when the user selects a font face, this function is called again to get available styles and point sizes. There is really not much to talk about here, since this function is well described in the documentation.

The combo box displaying font names is an owner drawn control. The code is a slightly modified version of Chris Losingers Font Combo.

If you customize the dialog template, you might have to go through the LayOutControls() function to make sure it reposition the controls as expected. Also it might be a good idea to not delete elements from the template, but rather hide and disable them if they are not wanted in the GUI.

Tradeoffs

Initially, the support for displaying which fonts are OpenType, Hans Dietrichs XFontCombo was checked out. But since this code doesn't yield the same result as the ChooseFont() does, this was abandonned, and the dialog now displays OpenTypes as plain TrueTypes. Not many application need to make that distinction anyway. However, if you do want to have this support, you can easily add it. At the top of the FontPropertiesDialog.cpp file, you can change:
#define IDENTIFY_OPENTYPE 0
to 1. If you do this, make sure you have Hans Dietrichs source code files IsOpenType.h and GetFontFile.h and their cpp file counterparts.

A color picker has been omitted by design. Different application use different color pickers. It's as easy as that. It's a look-and-feel thing. A color picker can be added without much effort.

A thought that came to mind was to use the resource template for ChooseFont() from the commdlg.dll file. This way, the dialog should automatically change language depending on the system, and also get the automatic help to work. This strategy was also abandonned in favor of customizability. Having the dialog resource at hand will make this a lot easier.

Points of Interest

The preview control in the common dialog seems to change its caption when selecting different character sets (script combo box). For instance, if Western is selected, the control shows "AaBbYyZz". Selecting another character set will change this to what seems to be a more appropriate string for that character set. How this works, I havn't been able to figure out. The implementation in CFontPropertiesDialog uses the window text supplied in the dialog template unmodified for every character set.

The enumeration process does not appear to be complete for the font common dialog. On my system I have several TrueType fonts installed which supports more styles than the four most common ones: Regular, Italic, Bold and Bold Italic. E.g. these fonts might have the styles like Oblique and Bold Oblique etc. These styles does not appear in the font common dialog but it does in CFontPropertiesDialog. My guess is that the font common dialog just sets the four basic styles for TrueType fonts, whithout using the enumeration process.

References

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --