1 
2 // ------------------------------------------------------------------
3 // Windows 2000 Graphics API Black Book
4 // Chapter 8 - Listing 8.1 (Scaled Text 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 <commctrl.h>
17 #include <cassert>
18 
19 // for the MakeFont() function...
20 #include "mk_font.h"
21 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
22 
23 
24 HINSTANCE hInst;
25 const char* WndClassName = "GMainWnd";
26 LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam,
27    LPARAM LParam);
28 
29 
30 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR,
31    int nCmdShow)
32 {
33    hInst = hInstance;
34 
35    WNDCLASS wc;
36    memset(&wc, 0, sizeof(WNDCLASS));
37 
38    wc.style = CS_HREDRAW | CS_VREDRAW;
39    wc.lpszClassName = WndClassName;
40    wc.lpfnWndProc = MainWndProc;
41    wc.hInstance = hInst;
42    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
43    wc.hbrBackground = reinterpret_cast<HBRUSH>(
44       COLOR_BTNFACE + 1
45       );
46 
47    if (RegisterClass(&wc))
48    {
49       HWND hWnd =
50          CreateWindow(
51             WndClassName, TEXT("Scaled Text Demo"),
52             WS_OVERLAPPEDWINDOW | WS_CAPTION |
53             WS_VISIBLE | WS_CLIPCHILDREN,
54             CW_USEDEFAULT, CW_USEDEFAULT, 800, 300,
55             NULL, NULL, hInst, NULL
56             );
57 
58       if (hWnd)
59       {
60          ShowWindow(hWnd, nCmdShow);
61          UpdateWindow(hWnd);
62 
63          MSG msg;
64          while (GetMessage(&msg, NULL, 0, 0))
65          {
66              TranslateMessage(&msg);
67              DispatchMessage(&msg);
68          }
69       }
70     }
71     return 0;
72 }
73 //-------------------------------------------------------------------------
74 
75 
76 HWND hTrackBar = NULL;
77 HFONT hTTFont = NULL;
78 double scale = 0.0;
79 LPCSTR pText = TEXT("The Scaled Text!");
80 
81 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam,
82    LPARAM lParam)
83 {
84    switch (msg)
85    {
86       case WM_CREATE:
87       {
88          INITCOMMONCONTROLSEX icx;
89          icx.dwSize = sizeof(INITCOMMONCONTROLSEX);
90          icx.dwICC = ICC_BAR_CLASSES;
91 
92          InitCommonControlsEx(&icx);
93 
94          hTrackBar =
95             CreateWindow(
96                TRACKBAR_CLASS, "",
97                TBS_HORZ | TBS_BOTH | TBS_AUTOTICKS |
98                TBS_FIXEDLENGTH | TBS_ENABLESELRANGE |
99                WS_CHILD | WS_VISIBLE,
100                10, 260, 375, 40,
101                hWnd, NULL, hInst, NULL
102                );
103 
104          assert(hTrackBar != NULL);
105          SNDMSG(hTrackBar, TBM_SETTHUMBLENGTH, 20, 0);
106          SNDMSG(hTrackBar, TBM_SETRANGEMAX, TRUE, 100);
107 
108          // create the TrueType (scalable) font
109          HDC hDC = GetDC(hWnd);
110          try
111          {
112             // see Chapter 4 for the definition of MakeFont
113             hTTFont = font::MakeFont(hDC, "Impact", 72);
114             if (!hTTFont) throw;
115          }
116          catch (...)
117          {
118             ReleaseDC(hWnd, hDC);
119          }
120          ReleaseDC(hWnd, hDC);
121          break;
122       }
123       case WM_HSCROLL:
124       {
125          if (reinterpret_cast<HWND>(lParam) == hTrackBar)
126          {
127             //
128             // adjust the scaling factor according to
129             // the position of the trackbar's slider
130             //
131             scale = static_cast<double>(
132                (SNDMSG(hTrackBar, TBM_GETPOS, 0, 0) + 1) / 50.0
133                );
134             InvalidateRect(hWnd, NULL, true);
135          }
136          break;
137       }
138       case WM_ERASEBKGND:
139       {
140          LRESULT res = DefWindowProc(hWnd, msg, wParam, lParam);
141 
142          HDC hDC = reinterpret_cast<HDC>(wParam);
143          HFONT hOldFont = static_cast<HFONT>(
144             SelectObject(hDC, hTTFont)
145             );
146          try
147          {
148             SetBkMode(hDC, TRANSPARENT);
149 
150             // open a path bracket
151             if (!BeginPath(hDC)) throw;
152 
153             // record the text to the path
154             TextOut(hDC, 10, 10, pText, lstrlen(pText));
155 
156             // close the path bracket and
157             // select the path into hDC
158             EndPath(hDC);
159 
160             // determine the number of endpoints in the path
161             const int num_points = GetPath(hDC, NULL, NULL, 0);
162             if (num_points > 0)
163             {
164                // make room for the POINTs and vertex types
165                POINT* pPEnds = new POINT[num_points];
166                unsigned char* pTypes = new unsigned char[num_points];
167                try
168                {
169                   // get the path's description
170                   int num_got = GetPath(hDC, pPEnds, pTypes, num_points);
171                   if (num_got > 0)
172                   {
173                      // start a new path bracket
174                      if (!BeginPath(hDC)) throw;
175 
176                      // scale each point in the description
177                      int iPoint;
178                      for (iPoint = 0; iPoint < num_got; ++iPoint)
179                      {
180                         pPEnds[iPoint].x = static_cast<LONG>(
181                            scale * pPEnds[iPoint].x + 0.5
182                            );
183                         pPEnds[iPoint].y = static_cast<LONG>(
184                            scale * pPEnds[iPoint].y + 0.5
185                            );
186                      }
187 
188                      for (iPoint = 0; iPoint < num_points; ++iPoint)
189                      {
190                         // handle the MoveToEx case
191                         if (pTypes[iPoint] == PT_MOVETO)
192                         {
193                            MoveToEx(
194                              hDC, pPEnds[iPoint].x, pPEnds[iPoint].y, NULL
195                              );
196                         }
197                         // handle the LineTo case
198                         else if (
199                            pTypes[iPoint] == PT_LINETO ||
200                            pTypes[iPoint] == (PT_LINETO | PT_CLOSEFIGURE)
201                            )
202                         {
203                            LineTo(hDC, pPEnds[iPoint].x, pPEnds[iPoint].y);
204                         }
205                         // handle the PolyBezierTo case
206                         else if (
207                            pTypes[iPoint] == PT_BEZIERTO ||
208                            pTypes[iPoint] == (PT_BEZIERTO | PT_CLOSEFIGURE)
209                            )
210                         {
211                            PolyBezierTo(hDC, pPEnds + iPoint, 3);
212                            iPoint += 2;
213                         }
214                      }
215 
216                      // close the new path bracket
217                      EndPath(hDC);
218 
219                      // stroke and fill the new path
220                      StrokeAndFillPath(hDC);
221                   }
222                }
223                catch (...)
224                {
225                   // clean up
226                   delete [] pTypes;
227                   delete [] pPEnds;
228                   throw;
229                }
230                // clean up
231                delete [] pTypes;
232                delete [] pPEnds;
233             }
234             // ...
235          }
236          catch (...)
237          {
238             SelectObject(hDC, hOldFont);
239          }
240          SelectObject(hDC, hOldFont);
241          return res;
242       }
243       case WM_SIZE:
244       {
245          MoveWindow(
246             hTrackBar,
247             0, HIWORD(lParam) - 40, LOWORD(lParam), 40,
248             false
249             );
250          break;
251       }
252       case WM_DESTROY:
253       {
254          // clean up
255          DeleteObject(hTTFont);
256          PostQuitMessage(0);
257          break;
258       }
259    }
260    return DefWindowProc(hWnd, msg, wParam, lParam);
261 }
262 //-------------------------------------------------------------------------
263 
264 
265 
266 
267