Click here to Skip to main content
Click here to Skip to main content

XFontDialog - Customizing CFontDialog Part I: Adding Font Filters

By , 7 Oct 2008
 

Introduction

In one project I was involved in, we had to display font selection dialog. My Product Manager had some issues with MFC's CFontDialog. He is very focused on reducing support costs by simplifying user interface, to eliminate anything that might be confusing or misleading. OK, it is hard to argue against this goal. In case of CFontDialog, he didn't like all the controls that were unnecessary for our application. Here is what the standard CFontDialog looks like:

screenshot

My Product Manager didn't like Effects, Font Style, or Script controls, since our app used only Font and Font Size values. I was starting to feel a little apprehensive (since I had never once won an argument with him), so I pointed out that we could easily eliminate some of the unnecessary controls. I asked him to come back tomorrow for a demonstration. For the rest of day, I tried to figure out how to remove controls he didn't like. I was only partially successful, because CFontDialog provides very little in its API to facilitate customizing user interface. When the Product Manager came by next day, this is what I showed him:

screenshot

He thought it looked really lame, and I had to agree. The Font Style combo was still there, and getting rid of Effects controls only left a big hole in the dialog - the Sample control had not even been resized to take advantage of free space on left. Finally, the best I could do was to disable Script combo.

But I had found out two things in my research into CFontDialog: first, you could use your own dialog template, based on the template provided in Font.Dlg; and second, there was a hook proc you could supply in your own CFontDialog-derived class.

After a few days playing with CFontDialog, I knew it would be possible to customize the font dialog to look the way we wanted. Mostly this involved editing the template used for the standard font dialog, and moving the unwanted controls outside the dialog:

screenshot

I also had to create new controls for sample text, because CFontDialog insists on reverting to text "AaBbYyZz" when you select new font in fonts combo.

To jump ahead a bit, here is final dialog:

screenshot

This is more compact than the standard font dialog, but looks enough like it that our users won't have to learn a completely different UI. At the same time, it removes the elements that might be frustrating to try to select (with no apparent effect, since they're not used in our apps). Plus, it gave us an opportunity to add some features that permitted better integration with our apps.

CXFontDialog Features

Here are the features in the new CXFontDialog:
screenshot Removal of all controls except font list and size list
screenshot Font filters to select only specific groups of fonts to display
screenshot Visual indication of monospaced fonts
screenshot New APIs for monospaced and symbol fonts
screenshot API to set caption of font dialog
screenshot API to set sample text of font dialog

Implementation Notes

The main source for technical information that I relied on to customize CFontDialog is the MSDN documentation on the CHOOSEFONT Structure. This struct includes the lpfnHook member that allows you to set your hook proc, and the lpTemplateName and hInstance members, which must be set in order to load the customized template. What MSDN doesn't tell you is where to find the default template. For VS 6.0, I found it in C:\Program Files\Microsoft Visual Studio\VC98\Include\Font.Dlg. For Visual Studio 8 and 9, it's located in the Platform SDK's Include directory. After I found it, next step was to set up a separate XFontDialog.rc file, and cut and paste the template from Font.Dlg. To set up XFontDialog.rc, I used the techniques I describe in my article XDialogImport - How to share dialogs between projects.
Note that by not defining IDD_XFONTDIALOG, the Class Wizard will treat IDD_XFONTDIALOG as a string. The advantage of this is that there is no possibility of conflicts with any other dialog resource ids in your project.

Now I can use Visual Studio Resource Editor to configure controls like I wanted - moving unwanted controls to the side and marking them not visible. I also make sample control bigger, and add static control to top of font list - so for monospaced fonts, you will see MONOSPACED displayed:

screenshot

I then use Class Wizard to generate new CXFontDialog class by double-clicking on template in Resource Editor:

screenshot

I select CFontDialog as base class, and enter CXFontDialog for new class name:

screenshot

And finally I am able to use Class Wizard for the new class:

screenshot

You will notice that all symbolic names in Font.Dlg have been converted to numeric IDs. This doesn't matter, since these IDs must not change anyway or CFontDialog would not work. (I assign names to these IDs inside XFontDialog.cpp to make it easier to work with.) I have added two handler functions to CXFontDialog: OnCtlColor() and OnShowMonoSpaced(), which is called from within the hook proc when user selects a monospaced font (this is where the MONOSPACED gets displayed). I also add DoModal() function, which is where dialog template and hook function are specified. The key function is the hook proc, where WM_INITDIALOG is caught. This is where font filters (if any) are applied.

How To Use

To integrate CXFontDialog into your app, you first need to add following files to your project:

  • XFontDialog.cpp
  • XFontDialog.h
  • XFontDialog.rc
  • XFontDialogRes.h
Note that XFontDialogRes.h - even though basically empty - is needed if you want to edit the dialog template in the resource editor.

You also need to add XFontDialog.rc to project rc file - go to View | Resource Includes... and in the bottom listbox, scroll down to the end. Insert #include "XFontDialog.rc" right before the #endif:

screenshot

Next, include header file XFontDialog.h in appropriate project files. Now you are ready to start using CXFontDialog.

Demo App

The XFontDialogTest.exe demo shows how to use CXFontDialog:

screenshot

Revision History

Version 1.1 - 2008 October 7

  • Changed the way that the monospaced attribute is determined. Previously I was using this technique:
        bIsMonoSpaced = (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0;
    but I discovered that some monospaced fonts (such as the excellent Pragmata font by Fabrizio Schiavi) did not mark the font in this way. So I resorted to the simpler, but more reliable method of comparing the widths of the '!' and 'W' characters. If they're the same, that means the font is monospaced.
  • Added API to allow setting the sample text.
  • Enlarged the dialog to make more fonts visible in the fonts combo.
  • Added VS2005 project.

Version 1.0 - 2003 June 21

  • Initial public release.

Usage

This software is released into the public domain. You are free to use it in any way you like, except that you may not sell this source code. If you modify it or extend it, please to consider posting new code here for everyone to share. This software is provided "as is" with no expressed or implied warranty. I accept no liability for any damage or loss of business that this software may cause.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Hans Dietrich
Software Developer (Senior) Hans Dietrich Software
United States United States
Member
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.
 
Recently, I have moved to Los Angeles where I am doing consulting and development work.
 
For consulting and custom software development, please see www.hdsoft.org.






Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalhey thanks a lot buddy..membersrinu501919 Jan '10 - 22:34 
its a very useful one for me..instead of wasting much time on this i jsut made use of this one..thanks a lot agian..
GeneralAwesomememberMichael Klim25 Feb '09 - 10:20 
This thing is great! Thanks a lot for making it available to us!  
GeneralThe extra CXFontDialogTestDlg func. to keep chosen in CFontDialog font color.memberOleg Boyko16 Nov '08 - 17:59 
Hi Hans,   I like your code stile. Just a little add-in to your project to keep chosen in CFontDialog font color back to CXFontDialogTestDlg for sample text.   I added variable COLORREF m_color in CXFontDialogTestDlg class which is black (RGB(0,0,0)) by default (in constructor)...
Generalhandling the size of the fontsmemberrupesh_gangi30 Oct '07 - 6:51 
Hai, I just need a help in handling the sizes that are displayed in the CFontDialog. Can we have the chance of placing our own sizes in the CFontDialog.Thanks in advance
QuestionHow to make .rc and res.h filessussali130585 May '05 - 10:32 
I found my export menu is grayed. how to generate these two files ? "XFontDialog.rc " "XFontDialogRes.h " thanks
QuestionCan you make the Color drop down visiblememberJia Qing29 Mar '05 - 22:25 
I also need the color, but after I check the color combo to Visible, it still does not visible.
I know you have a color pick sample, but I think if you can just turn the combo visible it will be simpler.
Can you give a solution? thanks
 
BTW: this is a good example, I have same requirement from my boss, but we also need color.
 
Jia
AnswerRe: Can you make the Color drop down visiblesussAnonymous3 Apr '05 - 20:32 
I have figured this out myself ,thanks anyway
AnswerRe: Can you make the Color drop down visiblemembertaphan26 Oct '05 - 1:08 
You can enable it by: From Declare class change code like this   // Construction public: CXFontDialog(LPLOGFONT lplfInitial = NULL, DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS, CDC* pdcPrinter = NULL, CWnd* pParentWnd = NULL); #ifndef _AFX_NO_RICHEDIT_SUPPORT...
Generalchanging colorpicker.sussblikstad20 Feb '05 - 6:35 
I need to _change_ the color picker to something that allows me to choose more colors rather than remove it. I've added a better colorpicker to the dialog, but I can't seem to figure out how to update the sample box with my new color. Any pointers?
GeneralRe: changing colorpicker.memberblikstad21 Feb '05 - 8:23 
Okay, I found a solution even though it's a bit of a "hack".   First of all I used the color picker from http://www.codeproject.com/miscctrl/colour_picker.asp.   I tried to create a hook and all that stuff but there seem to be some "magic" going on to update the sample box, so what...
GeneralThanks!memberrobosport28 Aug '04 - 15:19 
Very helpful article on customizing a common dialog, even for non-MFC users.
GeneralEffects & colormembermhassan24 Sep '03 - 4:54 
I try to make Strikeout visible again. So i change in XFontDialog Resourses, i make Strikeout is visible then i combile, but it still not appear. Can you help me
GeneralThanks for all the inside info on the font choosermemberJonesWooHoo28 Jul '03 - 1:35 
Ta, it got me goin again when I was stuck.   Jones
GeneralSmall Windows bug with font dialogmemberDamir Valiulin3 Jul '03 - 10:13 
Great work!   There is a bug with Windows Font Dialog though. When you select a font that doesn't have a Regular font style and has only Italic style (like Monotype Corsiva for example), the dialog automatically sets Font Style selection to Italic. If later you select a different font...
GeneralRe: Small Windows bug with font dialogmemberHans Dietrich4 Jul '03 - 18:29 
Damir Valiulin wrote: Is it possible to track the font selection and then switch back to Regular style automatically?   You might be able to do that, or you could simply remove the fonts from the combobox. In the for loop inside WM_INITDIALOG handler: if (!bDeleted &&...
GeneralCompile ErrormemberJohn R. Shaw24 Jun '03 - 14:57 
Ecellent work!   I had one error while compiling: Compiling... XFontDialog.cpp C:\Down Loaded Coding Files\CodeProject\Fonts and GDI\XFontDialog - Customizing CFontDialog Part I Adding Font Filters\XFontDialog_demo\XFontDialog.cpp(91) : error C2440: '=' : cannot convert from 'unsigned...
GeneralRe: Compile ErrormemberHans Dietrich25 Jun '03 - 3:37 
At first I was amazed, because I always compile at level 4. Then I remembered that I have Platform SDK installed, and I was able to reproduce this error. The problem is that VC 6 defines UINT_PTR as unsigned long, while Platform SDK defines it as unsigned int. So your solution is probably the...

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 7 Oct 2008
Article Copyright 2003 by Hans Dietrich
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid