Font Selector Combobox

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

CFontCombo Overview

The CFontCombo class is a CComboBox-derived class that while being a simple class is very useful in that it enables you to display all the fonts on the system in a combo box for the user's selection. Obviously, for the curious, you not only get the control itself, but the source code that shows how to iterate through the system's fonts and then how to apply a selected font to a bit of text (you can see this bit in the article's demo project shown in the screen shot above).

How it works

The way it works is that when the CFontCombo is subclassed (as with the MFC DDX mechanism), it calls ProcessFonts.
void CFontCombo::PreSubclassWindow() 
{
 // call function to get system's fonts when control is subclassed
 this->ProcessFonts();
	
 // call base class' implementation
 CComboBox::PreSubclassWindow();
}
Once, in the CFontCombo::ProcessFonts member function. As you can see below, ProcessFonts calls the Win32 SDK function, ::EnumFontFamiliesEx. A quick peek at the MSDN Library reveals that "The EnumFontFamiliesEx function enumerates all fonts in the system that match the font characteristics specified by the LOGFONT structure." The main arguments here are the second, third and forth ones. In those, I specify (in order) the LOGFONT structure (which defines which fonts I want - I selected all ANSI fonts), a callback function that Windows will call once for each font found in the system and finally a user supplied pointer to a block of memory.

The first two are pretty much self-explanatory. The last one (the user supplied memory) works like this. I'm passing the address of a CStringArray (called fontlist) which will be passed to my callback function (CFontCombo::EnumFontFamExProc) for each found font. In that callback function (which you'll see shortly), I get the name of a font which I then store in the fontlist. However, the call to EnumFontFamiliesEx doesn't return until all fonts have been enumerated. Therefore, once this call does return, I know that all the fonts are in my fontlist string array. At this point, I simply iterate through that list (see the for loop below) and add each string to the combo box.

void CFontCombo::ProcessFonts(void)
{
 LOGFONT lf;
 POSITION pos;

 lf.lfCharSet = ANSI_CHARSET;
 lf.lfFaceName[0]='\0';

 ::EnumFontFamiliesEx(this->GetParent()->GetDC()->m_hDC, 
                      &lf, 
                      (FONTENUMPROC) CFontCombo::EnumFontFamExProc, 
                      (LPARAM) &fontlist, 0);

 for(pos = fontlist.GetHeadPosition(); pos != NULL;)
  this->AddString(fontlist.GetNext(pos));
}
The last thing to look at is the callback function (CFontCombo::EnumFontFamExProc) itself. Here I simply take the font name (from the first argument) and add it to my string array (passed to me as an lparam. The last line (where I return 1) simply tells Windows that I'm not finished and that I want to continue receiving more fonts.
int CALLBACK CFontCombo::EnumFontFamExProc(ENUMLOGFONTEX *lpelfe,
                                           NEWTEXTMETRICEX *lpntme,
                                           int FontType,
                                           LPARAM lParam)
{
 CStringList* m_temp = (CStringList*) lParam;
 m_temp->AddTail((char*)lpelfe->elfFullName);

 return 1; // I want to get all fonts
}

Downloads

Download demo project - 19 Kb
Download source - 1 Kb


Comments

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • In this era of Big Data, enterprise applications create a large volume of data that may be structured, semi-structured, or unstructured in nature. Application development cycles are also shorter and application availability is a critical requirement. As such, enterprises are forced to look beyond traditional relational databases to NoSQL databases, such as MongoDB and Apache Cassandra, to onboard these next-generation applications. This guide discusses the backup and recovery challenges for distributed and …

  • On-demand webcast Continuous integration and continuous deployment (CI/CD) allow DevOps teams to be more efficient. When starting from a production environment, the use of Microsoft SQL Server 2017 in Docker containers and Kubernetes clusters can facilitate a DevOps CI/CD pipeline. Using SQL Server tools also allows you to easily integrate core DevOps application lifecycle management practices to database development. Watch this on-demand presentation to learn how defining the database dependency as …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date