1
2 // ------------------------------------------------------------------
3 // Windows 2000 Graphics API Black Book
4 // Chapter 5 - Listing 5.1 (Output Primitives 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 // for the MakeFont() function...
19 #include "mk_font.h"
20 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
21
22
23 HINSTANCE hInst;
24 const char* WndClassName = "GMainWnd";
25 LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam,
26 LPARAM LParam);
27
28
WinMain(HINSTANCE hInstance,HINSTANCE,LPTSTR,int nCmdShow)29 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR,
30 int nCmdShow)
31 {
32 hInst = hInstance;
33
34 WNDCLASS wc;
35 memset(&wc, 0, sizeof(WNDCLASS));
36
37 wc.style = CS_VREDRAW | CS_HREDRAW;
38 wc.lpszClassName = WndClassName;
39 wc.lpfnWndProc = MainWndProc;
40 wc.hInstance = hInst;
41 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
42 wc.hbrBackground = reinterpret_cast<HBRUSH>(
43 COLOR_BTNFACE + 1
44 );
45
46 if (RegisterClass(&wc))
47 {
48 HWND hWnd =
49 CreateWindow(
50 WndClassName, TEXT("Output Primitives Demo"),
51 WS_OVERLAPPEDWINDOW | WS_CAPTION |
52 WS_VISIBLE | WS_CLIPCHILDREN,
53 CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
54 NULL, NULL, hInst, NULL
55 );
56
57 if (hWnd)
58 {
59 ShowWindow(hWnd, nCmdShow);
60 UpdateWindow(hWnd);
61
62 MSG msg;
63 while (GetMessage(&msg, NULL, 0, 0))
64 {
65 TranslateMessage(&msg);
66 DispatchMessage(&msg);
67 }
68 }
69 }
70 return 0;
71 }
72 //------------------------------------------------------------------
73
74
75 enum OutPrimitive {
76 opLine, opBezier, opRectangle, opRoundRect,
77 opEllipse, opArc, opPie, opChord, opCustom
78 };
79
DrawPrimitive(IN HDC hDC,IN const RECT & RPrimitive,IN OutPrimitive PrimitiveID)80 void DrawPrimitive(IN HDC hDC, IN const RECT& RPrimitive,
81 IN OutPrimitive PrimitiveID)
82 {
83 RECT R = RPrimitive;
84 InflateRect(&R, -10, -10);
85
86 switch (PrimitiveID)
87 {
88 case opLine:
89 {
90 const POINT PLine[] = {{R.left, R.top}, {R.right, R.bottom}};
91 Polyline(hDC, PLine, 2);
92 break;
93 }
94 case opBezier:
95 {
96 const POINT PControlPoints[] = {
97 {R.left, R.top},
98 {(R.right - R.left) / 2, R.top},
99 {(R.right - R.left) / 2, R.bottom},
100 {R.right, R.bottom}
101 };
102 PolyBezier(hDC, PControlPoints, 4);
103 break;
104 }
105 case opRectangle:
106 {
107 Rectangle(hDC, R.left, R.top, R.right, R.bottom);
108 break;
109 }
110 case opRoundRect:
111 {
112 RoundRect(hDC, R.left, R.top, R.right, R.bottom, 20, 20);
113 break;
114 }
115 case opEllipse:
116 {
117 Ellipse(hDC, R.left, R.top, R.right, R.bottom);
118 break;
119 }
120 case opArc:
121 {
122 const POINT PRads[] = {
123 {(R.right - R.left) / 3 + R.left, R.top},
124 {(R.right - R.left) / 3 + R.left, R.bottom}
125 };
126 Arc(hDC, R.left, R.top, R.right, R.bottom,
127 PRads[0].x, PRads[0].y, PRads[1].x, PRads[1].y);
128 break;
129 }
130 case opPie:
131 {
132 const POINT PRads[] = {
133 {(R.right - R.left) / 3 + R.left, R.top},
134 {(R.right - R.left) / 3 + R.left, R.bottom}
135 };
136 Pie(hDC, R.left, R.top, R.right, R.bottom,
137 PRads[0].x, PRads[0].y, PRads[1].x, PRads[1].y);
138 break;
139 }
140 case opChord:
141 {
142 const POINT PRads[] = {
143 {(R.right - R.left) / 3 + R.left, R.top},
144 {(R.right - R.left) / 3 + R.left, R.bottom}
145 };
146 Chord(hDC, R.left, R.top, R.right, R.bottom,
147 PRads[0].x, PRads[0].y, PRads[1].x, PRads[1].y);
148 break;
149 }
150 case opCustom:
151 {
152 const POINT PVertices[] = {
153 {R.left, (R.bottom - R.top) / 2 + R.top},
154 {(R.right - R.left) / 2 + R.left, R.top},
155 {R.right, (R.bottom - R.top) / 2 + R.top},
156 {(R.right - R.left) / 2 + R.left, R.bottom}
157 };
158 Polygon(hDC, PVertices, 4);
159 break;
160 }
161 }
162 }
163 //------------------------------------------------------------------
164
165
166 HWND hListBox = NULL; // handle to the list box
167 HBRUSH hListBrush = NULL; // handle to the list box brush
168 HPEN hListPen = NULL; // handle to the list box pen
169 HFONT hListFont = NULL; // handle to the list box font
170
MainWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)171 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam,
172 LPARAM lParam)
173 {
174 switch (msg)
175 {
176 case WM_CREATE:
177 {
178 hListBox =
179 CreateWindowEx(
180 WS_EX_CLIENTEDGE, TEXT("LISTBOX"), TEXT(""),
181 WS_CHILD | WS_VISIBLE | WS_VSCROLL |
182 LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT |
183 LBS_OWNERDRAWFIXED,
184 0, 0, 640, 480,
185 hWnd, NULL, hInst, NULL
186 );
187 assert(hListBox != NULL);
188
189 SetWindowLongPtr(
190 hListBox, GWL_ID, reinterpret_cast<LONG_PTR>(hListBox)
191 );
192
193 SNDMSG(hListBox, LB_ADDSTRING, 0,
194 reinterpret_cast<LPARAM>(TEXT("Line")));
195 SNDMSG(hListBox, LB_ADDSTRING, 0,
196 reinterpret_cast<LPARAM>(TEXT("Bezier Curve")));
197 SNDMSG(hListBox, LB_ADDSTRING, 0,
198 reinterpret_cast<LPARAM>(TEXT("Rectangle")));
199 SNDMSG(hListBox, LB_ADDSTRING, 0,
200 reinterpret_cast<LPARAM>(TEXT("Rounded Rectangle")));
201 SNDMSG(hListBox, LB_ADDSTRING, 0,
202 reinterpret_cast<LPARAM>(TEXT("Ellipse")));
203 SNDMSG(hListBox, LB_ADDSTRING, 0,
204 reinterpret_cast<LPARAM>(TEXT("Arc")));
205 SNDMSG(hListBox, LB_ADDSTRING, 0,
206 reinterpret_cast<LPARAM>(TEXT("Pie Slice")));
207 SNDMSG(hListBox, LB_ADDSTRING, 0,
208 reinterpret_cast<LPARAM>(TEXT("Chord")));
209 SNDMSG(hListBox, LB_ADDSTRING, 0,
210 reinterpret_cast<LPARAM>(TEXT("Custom")));
211
212 hListBrush = CreateSolidBrush(PALETTERGB(64, 192, 64));
213 hListPen = CreatePen(PS_SOLID, 3, PALETTERGB(0, 0, 0));
214 HDC hScreenDC = GetDC(NULL);
215 #if 0
216 try
217 #endif
218 {
219 // MakeFont() from Chapter 4
220 hListFont = font::MakeFont(
221 hScreenDC, "Impact", 20, ANSI_CHARSET,
222 font::FS_BOLD | font::FS_UNDERLINE
223 );
224 }
225 #if 0
226 catch (...)
227 #endif
228 {
229 ReleaseDC(NULL, hScreenDC);
230 }
231 ReleaseDC(NULL, hScreenDC);
232
233 break;
234 }
235 case WM_MEASUREITEM:
236 {
237 LPMEASUREITEMSTRUCT lpmis =
238 reinterpret_cast<LPMEASUREITEMSTRUCT>(lParam);
239 assert(lpmis != NULL);
240
241 if (lpmis->CtlID == reinterpret_cast<UINT_PTR>(hListBox))
242 {
243 lpmis->itemHeight = 150;
244 return TRUE;
245 }
246 break;
247 }
248 case WM_DRAWITEM:
249 {
250 LPDRAWITEMSTRUCT lpdis =
251 reinterpret_cast<LPDRAWITEMSTRUCT>(lParam);
252 assert(lpdis != NULL);
253
254 if (lpdis->CtlID == reinterpret_cast<UINT_PTR>(hListBox))
255 {
256 SaveDC(lpdis->hDC);
257 #if 0
258 try
259 #endif
260 {
261 SelectObject(lpdis->hDC, hListBrush);
262 SelectObject(lpdis->hDC, hListPen);
263 SelectObject(lpdis->hDC, hListFont);
264
265 bool selected = (lpdis->itemState & ODS_SELECTED);
266 COLORREF clrText = GetSysColor(
267 selected ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT
268 );
269 HBRUSH hListBrush = GetSysColorBrush(
270 selected ? COLOR_HIGHLIGHT : COLOR_WINDOW
271 );
272
273 // fill the background
274 FillRect(lpdis->hDC, &lpdis->rcItem, hListBrush);
275
276 // render the output primitive
277 RECT RPrimitive = lpdis->rcItem;
278 InflateRect(&RPrimitive, -5, -5);
279 RPrimitive.right = static_cast<int>(
280 0.6 * lpdis->rcItem.right + 0.5
281 );
282 FillRect(
283 lpdis->hDC, &RPrimitive,
284 reinterpret_cast<HBRUSH>(COLOR_BTNFACE + 1)
285 );
286 DrawPrimitive(
287 lpdis->hDC, RPrimitive,
288 static_cast<OutPrimitive>(lpdis->itemID)
289 );
290 if (selected) InvertRect(lpdis->hDC, &RPrimitive);
291 DrawEdge(lpdis->hDC, &RPrimitive, EDGE_SUNKEN, BF_RECT);
292
293 // render the text
294 TCHAR text[13];
295 if (SNDMSG(hListBox, LB_GETTEXT, lpdis->itemID,
296 reinterpret_cast<LPARAM>(&text)) != LB_ERR)
297 {
298 RECT RText = RPrimitive;
299 RText.left = RPrimitive.right;
300 RText.right = lpdis->rcItem.right;
301
302 SelectObject(lpdis->hDC, hListFont);
303 SetBkMode(lpdis->hDC, TRANSPARENT);
304 SetTextColor(lpdis->hDC, clrText);
305
306 DrawText(lpdis->hDC, text, -1, &RText,
307 DT_CENTER | DT_VCENTER | DT_SINGLELINE);
308 }
309
310 // indicate keyboard focus
311 if (lpdis->itemState & ODS_FOCUS)
312 {
313 RECT RFocus = lpdis->rcItem;
314 InflateRect(&RFocus, -1, -1);
315 DrawFocusRect(lpdis->hDC, &RFocus);
316 }
317 }
318 #if 0
319 catch (...)
320 #endif
321 {
322 RestoreDC(lpdis->hDC, -1);
323 }
324 RestoreDC(lpdis->hDC, -1);
325 return TRUE;
326 }
327 break;
328 }
329 case WM_SIZE:
330 {
331 MoveWindow(
332 hListBox, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE
333 );
334 return 0;
335 }
336 case WM_DESTROY:
337 {
338 if (hListBrush) DeleteObject(hListBrush);
339 if (hListPen) DeleteObject(hListPen);
340 if (hListFont) DeleteObject(hListFont);
341
342 PostQuitMessage(0);
343 return 0;
344 }
345 }
346 return DefWindowProc(hWnd, msg, wParam, lParam);
347 }
348 //-------------------------------------------------------------------------
349
350
351
352