1 
2 // ------------------------------------------------------------------
3 // Windows 2000 Graphics API Black Book
4 // Chapter 4 - Listing 4.2 (Font Enumeration Demo)
5 //
6 // Created by Damon Chandler <dmc27@ee.cornell.edu>
7 // Updates can be downloaded at: <www.coriolis.com>
8 //
9 // Please do not hesistate to e-mail me at dmc27@ee.cornell.edu
10 // if you have any questions about this code.
11 // ------------------------------------------------------------------
12 
13 
14 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
15 #include <windows.h>
16 #include <cassert>
17 
18 
19 #ifndef SNDMSG
20 #define SNDMSG ::SendMessage
21 #endif /* ifndef SNDMSG */
22 
23 
24 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
25 
26 
27 HWND hListBox = NULL;
28 const int ID_LISTBOX = 101;
29 
30 HINSTANCE hInst;
31 const char* WndClassName = "GMainWnd";
32 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam,
33    LPARAM lParam);
34 
35 
36 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR,
37    int nCmdShow)
38 {
39    hInst = hInstance;
40 
41    WNDCLASS wc;
42    memset(&wc, 0, sizeof(WNDCLASS));
43 
44    wc.style = CS_VREDRAW | CS_HREDRAW;
45    wc.lpszClassName = WndClassName;
46    wc.lpfnWndProc = MainWndProc;
47    wc.hInstance = hInstance;
48    wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW);
49    wc.hbrBackground = reinterpret_cast<HBRUSH>(
50       COLOR_BTNFACE + 1
51       );
52 
53    if (RegisterClass(&wc))
54    {
55       HWND hWnd =
56          CreateWindow(
57             WndClassName, TEXT("Font Enumeration Demo"),
58             WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION |
59             WS_VISIBLE | WS_CLIPCHILDREN,
60             CW_USEDEFAULT, CW_USEDEFAULT, 295, 285,
61             NULL, NULL, hInst, NULL
62             );
63 
64       if (hWnd)
65       {
66          ShowWindow(hWnd, nCmdShow);
67          UpdateWindow(hWnd);
68 
69          MSG msg;
70          while (GetMessage(&msg, NULL, 0, 0))
71          {
72              TranslateMessage(&msg);
73              DispatchMessage(&msg);
74          }
75       }
76     }
77     return 0;
78 }
79 //-------------------------------------------------------------------------
80 
81 
82 int CALLBACK MyEnumFontFamExProc(ENUMLOGFONTEX *lpelfe,
83    NEWTEXTMETRICEX* lpntme, int FontType, LPARAM lParam)
84 {
85    if (FontType == TRUETYPE_FONTTYPE)
86    {
87       // if the typeface name is not already in the list
88       LPARAM name = reinterpret_cast<LPARAM>(lpelfe->elfFullName);
89       if (SNDMSG(hListBox, LB_FINDSTRINGEXACT, (ULONG)-1, name) == LB_ERR)
90       {
91          // add each font to the list box
92          int index = SNDMSG(hListBox, LB_ADDSTRING, 0, name);
93 
94          // fix the size of the font
95          lpelfe->elfLogFont.lfHeight = -20;
96          lpelfe->elfLogFont.lfWidth = 0;
97 
98          // create a new font and store its handle
99          // as the data of the newly added item
100          HFONT hFont = CreateFontIndirect(&lpelfe->elfLogFont);
101          SNDMSG(hListBox, LB_SETITEMDATA, index,
102                 reinterpret_cast<LPARAM>(hFont));
103       }
104    }
105    return TRUE;
106 }
107 //-------------------------------------------------------------------------
108 
109 
110 void AddScreenFonts()
111 {
112    // grab a handle to the screen's DC
113    HDC hScreenDC = GetDC(NULL);
114    try
115    {
116       //
117       // NOTE: Windows 95, 98 and Me requires that the lpLogfont
118       // (second) parameter of the EnumFontFamiliesEx function is
119       // non-NULL.  This parameter can be NULL on Windows NT/2000.
120       //
121       LOGFONT lf = {0};
122       lf.lfCharSet = DEFAULT_CHARSET;
123 
124       // enumerate the current screen fonts
125       EnumFontFamiliesEx(
126          hScreenDC, &lf,
127          (FONTENUMPROC)MyEnumFontFamExProc,
128          0, 0
129          );
130    }
131    catch (...)
132    {
133       // release the screen's DC
134       ReleaseDC(NULL, hScreenDC);
135    }
136    // release the screen's DC
137    ReleaseDC(NULL, hScreenDC);
138 }
139 //-------------------------------------------------------------------------
140 
141 
142 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam,
143    LPARAM lParam)
144 {
145    switch (msg)
146    {
147       case WM_CREATE:
148       {
149          hListBox =
150             CreateWindowEx(
151                WS_EX_CLIENTEDGE, TEXT("LISTBOX"), TEXT(""),
152                WS_CHILD | WS_VISIBLE | LBS_STANDARD |
153                LBS_HASSTRINGS | LBS_OWNERDRAWFIXED,
154                20, 10, 250, 250,
155                hWnd, reinterpret_cast<HMENU>(ID_LISTBOX),
156                hInst, NULL
157                );
158          if (hListBox)
159          {
160             AddScreenFonts();
161          }
162       }
163       case WM_MEASUREITEM:
164       {
165          // grab a pointer to the MEASUREITEMSTRUCT structure
166          LPMEASUREITEMSTRUCT lpmis =
167             reinterpret_cast<LPMEASUREITEMSTRUCT>(lParam);
168 
169          // test the identifier of the control that
170          // the message is meant for
171          if ((int)lpmis->CtlID == ID_LISTBOX)
172          {
173             // adjust the height
174             lpmis->itemHeight = 25;
175 
176             return TRUE;
177          }
178          break;
179       }
180       case WM_DRAWITEM:
181       {
182          // grab a pointer to the DRAWITEMSTRUCT structure
183          LPDRAWITEMSTRUCT lpdis =
184             reinterpret_cast<LPDRAWITEMSTRUCT>(lParam);
185 
186          // test the identifier of the control that
187          // the message is meant for
188          if ((int)lpdis->CtlID == ID_LISTBOX)
189          {
190             COLORREF OldColor = GetTextColor(lpdis->hDC);
191             int stock = WHITE_BRUSH;
192 
193             // if the item is currently selected
194             if (lpdis->itemState & ODS_SELECTED)
195             {
196                // set the text color to white and
197                // the background color to black
198                COLORREF clrWhite = PALETTERGB(255, 255, 255);
199                OldColor = SetTextColor(lpdis->hDC, clrWhite);
200                stock = BLACK_BRUSH;
201             }
202             FillRect(
203                lpdis->hDC, &lpdis->rcItem,
204                static_cast<HBRUSH>(GetStockObject(stock))
205                );
206 
207             if ((int)lpdis->itemID != -1)
208             {
209                // extract the item's text
210                char text[MAX_PATH];
211                SNDMSG(hListBox, LB_GETTEXT, lpdis->itemID,
212                       reinterpret_cast<LPARAM>(text));
213 
214                // extract the corresponding font handle
215                DWORD value =
216                    SNDMSG(hListBox, LB_GETITEMDATA, lpdis->itemID, 0);
217                HFONT hFont = reinterpret_cast<HFONT>(value);
218 
219                // select the corresponding font
220                // into the device context
221                HFONT HOldFont = static_cast<HFONT>(
222                   SelectObject(lpdis->hDC, hFont)
223                   );
224 
225                // render the text transparently
226                SetBkMode(lpdis->hDC, TRANSPARENT);
227 
228                // render the text
229                RECT RText = lpdis->rcItem;
230                InflateRect(&RText, -2, -2);
231                DrawText(lpdis->hDC, text, strlen(text), &RText,
232                         DT_LEFT | DT_VCENTER | DT_SINGLELINE);
233 
234                // restore the previous font
235                SelectObject(lpdis->hDC, HOldFont);
236             }
237 
238             // render the focus rectangle
239             if (lpdis->itemState & ODS_FOCUS)
240             {
241                DrawFocusRect(lpdis->hDC, &lpdis->rcItem);
242             }
243 
244             // restore the previous color/mode
245             SetTextColor(lpdis->hDC, OldColor);
246             SetBkMode(lpdis->hDC, OPAQUE);
247 
248             return TRUE;
249          }
250          break;
251       }
252       case WM_DESTROY:
253       {
254          // delete each created font object
255          int count = SNDMSG(hListBox, LB_GETCOUNT, 0, 0);
256          for (int index = 0; index < count; ++index)
257          {
258             DWORD value = SNDMSG(hListBox, LB_GETITEMDATA, index, 0);
259             DeleteObject(reinterpret_cast<HFONT>(value));
260          }
261 
262          PostQuitMessage(0);
263          break;
264       }
265    }
266    return DefWindowProc(hWnd, msg, wParam, lParam);
267 }
268 //-------------------------------------------------------------------------
269 
270 
271 
272