Click here to Skip to main content
15,893,814 members
Articles / Desktop Programming / WTL

Font Enumerator

Rate me:
Please Sign up or sign in to vote.
5.00/5 (10 votes)
1 Sep 2009CPOL7 min read 36.1K   3.1K   26  
A tool that enumerates all fonts installed on Windows, and shows you the preview so as to help you code conveniently.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--------------------------------------------------------------------------->  
<!--                           INTRODUCTION                                

 The Code Project article submission template (HTML version)

Using this template will help us post your article sooner. To use, just 
follow the 3 easy steps below:
 
     1. Fill in the article description details
     2. Add links to your images and downloads
     3. Include the main article text

That's all there is to it! All formatting will be done by our submission
scripts and style sheets. 

-->  
<!--------------------------------------------------------------------------->  
<!--                        IGNORE THIS SECTION                            -->
<html>
<head>
<title>The Code Project</title>
<Style>
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt }
H2,H3,H4,H5 { color: #ff9900; font-weight: bold; }
H2 { font-size: 13pt; }
H3 { font-size: 12pt; }
H4 { font-size: 10pt; color: black; }
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono; WHITE-SPACE: pre; }
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; }
</style>
<link rel="stylesheet" type="text/css" href="CodeProject.css">
</head>
<body bgcolor="#FFFFFF" color=#000000>
<!--------------------------------------------------------------------------->  


<!-------------------------------     STEP 1      --------------------------->
<!--  Fill in the details (CodeProject will reformat this section for you) -->

<pre>Title:       Font Enumerator
Author:      PARK Youngho 
Email:       
Member ID:   3279933
Language:    C++
Platform:    Windows
Technology:  WTL, STL
Level:       Intermediate
Description: An article on a tool that enumerates all fonts installed on Windows, and shows you the preview so as to help code easily
Section      WTL
SubSection   Applications
License:     <a href="http://www.codeproject.com/info/licenses.aspx">CPOL</a>
</pre>

<!-------------------------------     STEP 2      --------------------------->
<!--  Include download and sample image information.                       --> 

<ul class=download>
<li><a href="FontEnumerator_demo.zip">Download demo project - 78&nbsp;Kb </a></li>
<li><a href="FontEnumerator_src.zip">Download source - 40&nbsp;Kb</a></li>
</ul>

<p><img src="FontEnumerator1.gif" alt="Sample Image - maximum width is 600 pixels" width="657" height="560"></p>


<!-------------------------------     STEP 3      --------------------------->

<!--  Add the article text. Please use simple formatting (<h2>, <p> etc)   --> 

<h2>Introduction</h2>

<p>Sometimes, we have to deal with font for any reason. While I was studing fonts through a book &quot;WIN API Conquer&quot; which was written by KIM Sanghyung in Korean, I found a good sample code.&nbsp;I&nbsp;used&nbsp;it&nbsp;as&nbsp;a&nbsp;utility&nbsp;but I found that it did not have the functions I want. It only enumerates the fonts up to 500 fonts and shows parameters of each font. That's all. So, I improved that sample code.&nbsp;Original one was&nbsp;written in pure WIN32 API codes but I changed its framework into WTL and got rid of its&nbsp;enumerating limitation up to&nbsp;500 fonts by using STL vector and added more&nbsp;new functions I wanted&nbsp;so that the smell of the origin has almost gone. But, I want to reveal&nbsp;where the origin code of this program to enumerate font came from.<h3>Purpose of this small tool</h3>
<p>In order to use font, we need to see what&nbsp;the font looks like not only as itself but also with parameters changed such as height, italic effect, orientation, etc. If we are coding some program, we often have&nbsp;to create fonts with desirable or predetermined parameters. In that case, this program will be helpful to save your time. This is a small tool that:<br>1) enumerates all fonts installed on Windows,<br>2) allows you to choose one of them and to change some parameters which will be filled in structure LOGFONT in order to create font, and<br>3)&nbsp;shows you the preview of the font with the changed parameters.<br>So, you can try several possible fonts easily with changing parameters and eventially choose the best one for you. It will also put the necessary code to create font on clipboard for you so that you can just paste it on your IDE editor.


<h2>How to use Font Enumerator and How it works</h2>
<h3>How to enumerate Fonts and see&nbsp;corresponding&nbsp;parameters of the font you chose</h3>
<p>When you execute FontEnumerator.exe, it firstly enumerates all the fonts installed on Windows. On Korean windows, all the message will be shown in Korean&nbsp;while&nbsp;those&nbsp;will&nbsp;be&nbsp;in&nbsp;English&nbsp;on&nbsp;non-Korean&nbsp;Windows. You can find them on the left list window. If you click one of them all the parameters to be used in structure LOGFONT will be shown on the right. On the buttom, you can see the preview.</p>
<h3>How to try on the font with different parameters</h3>
<p> You can also change the parameters in the edit windows or check boxes and then press Enter-Key or click the buttom preview window to see the preview of the result. Check state of the check box except for &quot;height&quot; means that its factor will affect on the font. For example, if you check the check box of italic, the font will be italic. Height uses the unit &quot;twips&quot; but we often use the unit &quot;point&quot;. So, instead of the &quot;height&quot;, you can use the unit point by checking the check box of height. In reality, we more often use the unit of point rather than twips. So, if you click the check box &quot;height&quot;, the parameter name will be changed into point and the value of the width will be 0,&nbsp;which means the proper default value according&nbsp;to the height value. Once you changed the parameters, click the buttom window or press Enter-Key. Then, you can see the changed font shape.</p>
<h3>How to use menu</h3>
<p>You can use the customised system menu by clicking the top-left icon or right-clicking the title bar. Then, a normal system menu with some new menu items will pop up. I'm using Korean Windows so that the system menu items are shown in Korean but it will be shown in your language on your computer. The added menu items will be shown in Korean on Korean Windows and in English on non-Korean Windows. However, for explanation, I&nbsp;temporarily forced it to show all in English even on Korean Windows.</p>
<p><img src="FontEnumerator2.gif" width="576" height="240" border="0"></p>
<h4>Re-Enumerate fonts</h4>
<p>If you select the menu item 'Re-enumerate fonts', it will enumerate fonts again. The result will be same as before.</p>
<h4>Change the sample string</h4>
<p>If you click the menu item 'Change the sample string', you will have the chance to change the sample string as shown bellow. So, if you change the sample string in the edit window, you will have different sample string but it would not be saved on disk so that next time when you execute this program, it will be initialized.</p>
<p><img src="FontEnumerator3.gif" width="332" height="123" border="0"></p>
<h4>Copy the source code for creating font to clipboard</h4>
<p>Finally, if you choose the menu item 'Copy the source code for creating font to clipboard, you will have five choices.&nbsp;::CreateFontIndirect(...) and ::CreateFont(...) are for WIN 32 API functions. CFont::CreateFontIndirect(...) and CFont::CreateFont(...) are for&nbsp;WTL&nbsp;or MFC. Font font(...) is for GDI+. For example, if you choose CFont::CreateFontIndirect(...) and paste on your IDE editor, you will get following code.</p>
<pre lang = "C++">
    LOGFONT	lf;
    lf.lfHeight = 36;
    lf.lfWidth = 14;
    lf.lfEscapement = 0;
    lf.lfOrientation = 0;
    lf.lfWeight = FW_NORMAL;
    lf.lfItalic = FALSE;
    lf.lfUnderline = FALSE;
    lf.lfStrikeOut = FALSE;
    lf.lfCharSet = GREEK_CHARSET;
    lf.lfOutPrecision = OUT_STROKE_PRECIS;
    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    lf.lfQuality = PROOF_QUALITY;
    lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
    _tcscpy(lf.lfFaceName, _T(&quot;Arial&quot;));
    CFont    	font;
    font.CreateFontIndirect(&amp;lf);
</pre>
<h4>About...</h4>
<p>If you click the menu item 'About...',&nbsp;About&nbsp;box&nbsp;will&nbsp;pop&nbsp;up.</p>
<h2>Using the Code</h2>
<h3>using class OSL</h3>
<p>Class OSL is defined in stdafx.h as follows:</p>
<pre lang = "C++">
typedef WindowsHelper::OSLang&lt;&gt;    OSL;
</pre>
<p>The template class <code>OSLang&lt;int mode&gt;</code> is defined in the namespace <code>WindowsHelper</code> in WindowsHelper.hpp as follows:</p>
<pre lang = "C++">
template&lt;int mode = -1&gt;
struct OSLang
{
    WORD    	m_Lang;

    OSLang(void)
    {
        m_Lang = (mode &lt; 0) ? GetSystemDefaultLangID() : mode;
    }

    OSLang(HFONT&amp; hFont, int point)
    {
        m_Lang = (mode &lt; 0) ? GetSystemDefaultLangID() : mode;
        HDC	hDC = ::GetDC(NULL);
        int height = -::MulDiv(point, GetDeviceCaps(hDC, LOGPIXELSY), 72);
        ::ReleaseDC(NULL, hDC);
        switch (PRIMARYLANGID(m_Lang))
        {
        case LANG_KOREAN:
            hFont = ::CreateFont(height, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGUL_CHARSET, 
                                    OUT_STROKE_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
                                    VARIABLE_PITCH | FF_MODERN, _T(&quot;���� ���&quot;));
            break;
        default:
            hFont = ::CreateFont(height, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, 
                                    OUT_STROKE_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
                                    VARIABLE_PITCH | FF_SWISS, _T(&quot;Calibri&quot;));
            break;
        }
    }

    inline operator WORD ()
    {
        return PRIMARYLANGID(m_Lang);
    }

    inline char getSubLang(void)
    {
        return SUBLANGID(m_Lang);
    }
};
</pre>
<p>In its&nbsp;constructor, it determines the system language and creates&nbsp;font according to the language. If you set font for your program, you can reduce the affect on your program from the variation of systems. I categorized system languages into two: Korean and non-Korean. You can do as you wish. There are two global variables: _Font and _Lang. Those global variables affect on the whole program.</p>
<h3>Setting a font to a whole program</h3>
<p>In WindowsHelper.hpp, a set of Font Setting Functions are defined as follows:</p>
<pre lang = "C++">
typedef std::vector&lt;HWND&gt;    HWNDS;

struct SetFontData
{
    HFONT	    hFont;
    HWNDS*	   phWndExcepts;
};

template&lt;bool bInvalidate&gt;
BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
{
 &nbsp;&nbsp;&nbsp;HWNDS*	 &nbsp;&nbsp;&nbsp;excepts = ((SetFontData*) lParam)-&gt;phWndExcepts;
 &nbsp;&nbsp;&nbsp;for (HWNDS::iterator it = excepts-&gt;begin(); it != excepts-&gt;end(); it++)
 &nbsp;&nbsp;&nbsp;{
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (hWnd == *it)
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;excepts-&gt;erase(it);
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return TRUE;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 &nbsp;&nbsp;&nbsp;}
 &nbsp;&nbsp;&nbsp;::SendMessage(hWnd, WM_SETFONT, (WPARAM) (((SetFontData*) lParam)-&gt;hFont), TRUE);
 &nbsp;&nbsp;&nbsp;if (bInvalidate)
 &nbsp;&nbsp;&nbsp;{
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//RECT	rc;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//::GetClientRect(hWnd, &amp;rc);
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//::InvalidateRect(hWnd, &amp;rc, TRUE);
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;::InvalidateRect(hWnd, NULL, TRUE);
 &nbsp;&nbsp;&nbsp;}
 &nbsp;&nbsp;&nbsp;return TRUE;
}

template&lt;bool bInvalidate&gt;
void setFont(HFONT hFont, HWND hWndParent, HWNDS&amp; hWndExcepts)
{
 &nbsp;&nbsp;&nbsp;SetFontData &nbsp;&nbsp;&nbsp;	data;
 &nbsp;&nbsp;&nbsp;data.hFont = hFont;
 &nbsp;&nbsp;&nbsp;data.phWndExcepts = &amp;hWndExcepts;
 &nbsp;&nbsp;&nbsp;::SendMessage(hWndParent, WM_SETFONT, (WPARAM) hFont, TRUE);
 &nbsp;&nbsp;&nbsp;::EnumChildWindows(hWndParent, &amp;EnumChildProc, (LPARAM) &amp;data);
}

template&lt;bool bInvalidate&gt;
void setFont(HFONT hFont, HWND hWndParent, HWND hWndExcept = NULL)
{
 &nbsp;&nbsp;&nbsp;HWNDS		hWnds;
 &nbsp;&nbsp;&nbsp;if (hWndExcept)
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hWnds.push_back(hWndExcept);
 &nbsp;&nbsp;&nbsp;setFont(hFont, hWndParent, hWnds);
}
</pre>
<p>Sample window should not be set to a certain font so that in <code>CMainDlg::OnInitDialog(...)</code> in MainDlg.cpp, a certain font is set as follows:</p>
<pre lang = "C++">WindowsHelper::setFont&lt;true&gt;(_Font, this-&gt;m_hWnd, m_wndButtonExample);</pre>
<h3>Controling the order of font list </h3>
<p>I don't want to show @~ series fonts first in the font list window. So, comparation function was given to&nbsp;the&nbsp;last argument to the function sort(...) when font list is sorted at <code>CMainDlg::enumerateFonts()</code>&nbsp;as follows:</p>
<pre lang = "C++">std::sort(m_FontVec.begin(), m_FontVec.end(), comp);</pre>
<p> The function comp(..) is defined as follows:</p>
<pre lang = "C++">
extern &quot;C&quot; bool comp(FontPair&amp; left, FontPair&amp; right)
{
    if ((_T('@') != left.first.lfFaceName[0]) &amp;&amp; (_T('@') == right.first.lfFaceName[0]))
        return true;
    if ((_T('@') == left.first.lfFaceName[0]) &amp;&amp; (_T('@') != right.first.lfFaceName[0]))
        return false;
    return (_tcscmp(left.first.lfFaceName, right.first.lfFaceName) &lt; 0);
}
</pre>
<p> It make sort(...) to determine the names of @~ series of fonts bigger than normal fonts so that in the list @~ fonts come later than normal fonts.</p>
<h3> std::tstring</h3>
<p><code> std::tstring</code>&nbsp;is not a type of STL but a type definded according to encoding setting whether UNICODE or ANSI in the namespace std. It is defined in stlhelper.hpp as follows:</p>
<pre lang = "C++">
#ifdef _STRING_
#ifndef _STRING_STLHELPER_D4459FC7_15A3_4C5E_8CD8_15BF92D97BF3
#define _STRING_STLHELPER_D4459FC7_15A3_4C5E_8CD8_15BF92D97BF3
#ifdef UNICODE
    typedef     wstring     tstring;
#else
    typedef     string      tstring;
#endif  // UNICODE
#endif  // _STRING_STLHELPER_D4459FC7_15A3_4C5E_8CD8_15BF92D97BF3
#endif  // _STRING_
</pre>

<h2>Environment</h2>
<p>
This application was created with VC++ 2008 Express SP1, WTL and ATL7.1. It has been tested only on Korean Windows XP Home Edition SP3 and Russian Windows XP professional.
</p>

<h2>Acknowledgement</h2>

<p>I want to thank Michael Dunn for his excellent articles on WTL for
MFC programmers. I learned a lot about WTL from his article. His
articles can be found <a href="http://www.codeproject.com/KB/wtl/Nura_Tritris.aspx#Beginners">here</a>. I want to also thank Sergey Solozhentsev for his great work on the WTL Helper and the WTL Wizards. You can get his WTL Helper <a href="http://www.codeproject.com/macro/wtlhelper.asp">here</a> and <a href="http://salos.narod.ru/eng/download.html">here</a>, and its manual <a href="http://www.codeproject.com/macro/wtlhelper.asp">here</a> and <a href="http://salos.narod.ru/eng/WTLHelper/WTLHelper.html">here</a>. Do not be confused. His WTL Wizards are different from the normal WTL App Wizard which can be installed with <em>setup71.js</em>, for instance. His WTL Wizards support a split window framework as well. You can also get his WTL Wizards <a href="http://salos.narod.ru/eng/download.html">here</a> and its manual <a href="http://salos.narod.ru/eng/WtlWiz/WtlWiz.html">here</a>.
It provides me with a lot of convenience when I code using WTL. Most of
all, I really appreciate God and my wife Nura. He gave me her, and she
is always on my side and is my firm supporter.</p>
<h2>History</h2>

<p>24, July, 2009 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Version 1.0.</p>
<p>15, August, 2009 &nbsp;&nbsp;&nbsp;Version 1.1 &nbsp;&nbsp;&nbsp;Point unit of height of font added, Private font used, Fixed a bug of&nbsp;improperly generating source code for&nbsp;Font creation.</p>
<p>23, August, 2009 &nbsp;&nbsp;&nbsp;Version 1.1.1 &nbsp;&nbsp;&nbsp;Fixed a bug of memory access violation.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>

</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Korea (Republic of) Korea (Republic of)
I like programming.
I am teaching at AUCA (American University of Central Asia) now.

Comments and Discussions