|
|
1.1 root 1: /******************************************************************************\
2: *
3: * PROGRAM: PRINTER.C
4: *
5: * PURPOSE: This is a sample application demostrating some of the new
6: * printing functionality in Windows NT. This app allows the
7: * user to select between various GDI graphics primitives,
8: * to choose pen & brush colors, styles, and sizes, and to
9: * the print these graphics to a printer. Also, the app
10: * provides the user the ability to query information (reso-
11: * lution, etc.) about the various printers & drivers by
12: * making calls to GetDeviceCaps, etc.
13: *
14: * Functionality for PRINTER is split into six different
15: * modules as follows:
16: *
17: * printer.c - main event loop
18: * main window procedure
19: * about & abort dialog procedures
20: * printing thread
21: *
22: * paint.c - handles all painting printers & most painting
23: * to window
24: *
25: * enumprt.c - manages the display of information returned
26: * from calling EnumPrinters, EnumPrinterDrivers
27: *
28: * devcapsx.c- manages the display of information returned
29: * from calling DeviceCapabilitiesEx
30: *
31: * getpdriv.c- manages the display of information returned
32: * from calling GetPrinterDriver
33: *
34: * getcaps.c - manages the display of information returned
35: * from calling GetDeviceCaps
36: *
37: * FUNCTIONS: WinMain - initialization, create window, msg loop
38: * MainWndProc - processes main window msgs
39: * AboutDlgProc - processes About dlg msgs
40: * InvalidateClient - invalidates graphics part of client wnd
41: * RefreshPrinterCombobox- updates list of printers
42: * PrintThread - printing done here
43: * AbortProc - msg loop for abort
44: * AbortDlgProc - processes abort dialog messages
45: *
46: *
47: * Microsoft Developer Support
48: * Copyright (c) 1992 Microsoft Corporation
49: *
50: \******************************************************************************/
51:
52: #include <windows.h>
53: #include <stdio.h>
54: #include <string.h>
55: #include <winspool.h>
56: #include <commdlg.h>
57: #include "common.h"
58: #include "printer.h"
59:
60:
61:
62: /******************************************************************************\
63: *
64: * FUNCTION: WinMain (standard WinMain INPUTS/RETURNS)
65: *
66: * COMMENTS: Register & create main window, loop for messages
67: *
68: \******************************************************************************/
69:
70: int WINAPI WinMain (HANDLE ghInstance, HANDLE hPrevInstance, LPSTR lpCmdLine,
71: int nCmdShow)
72: {
73: MSG msg;
74:
75: ghInst = ghInstance;
76:
77: if (!hPrevInstance)
78: {
79: WNDCLASS wc;
80:
81: wc.style = MAIN_CLASS_STYLE;
82: wc.lpfnWndProc = (WNDPROC) MainWndProc;
83: wc.cbClsExtra = 0;
84: wc.cbWndExtra = 0;
85: wc.hInstance = ghInst;
86: wc.hIcon = LoadIcon (ghInst, MAKEINTRESOURCE(MAIN_ICON));
87: wc.hCursor = LoadCursor (NULL, IDC_ARROW);
88: wc.hbrBackground = NULL;
89: wc.lpszMenuName = (LPCSTR) MAIN_MENU_NAME;
90: wc.lpszClassName = (LPCSTR) MAIN_CLASS_NAME;
91:
92: if (!RegisterClass (&wc))
93: {
94: MessageBox (NULL, "WinMain(): RegisterClass() failed",
95: ERR_MOD_NAME, MB_OK | MB_ICONHAND);
96:
97: return FALSE;
98: }
99: }
100:
101: if (!(ghwndMain = CreateWindow ((LPCSTR) MAIN_CLASS_NAME,
102: (LPCSTR) MAIN_WND_TITLE,
103: MAIN_WND_STYLE,
104: CW_USEDEFAULT, CW_USEDEFAULT,
105: CW_USEDEFAULT, CW_USEDEFAULT,
106: NULL, NULL, ghInst, NULL)))
107: return FALSE;
108:
109: ShowWindow (ghwndMain, nCmdShow);
110:
111: while (GetMessage (&msg, NULL, NULL, NULL))
112: {
113: TranslateMessage (&msg);
114: DispatchMessage (&msg);
115: }
116:
117: return msg.wParam;
118: }
119:
120:
121:
122: /******************************************************************************\
123: *
124: * FUNCTION: MainWndProc (standard window procedure INPUTS/RETURNS)
125: *
126: * COMMENTS: Handles main app window msg processing
127: *
128: \******************************************************************************/
129:
130: LRESULT CALLBACK MainWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
131: {
132: static HMENU hMappingModesSubMenu;
133: static HMENU hGraphicsSubMenu;
134: static HMENU hPenWidthSubMenu;
135: static HMENU hPenStyleSubMenu;
136: static HMENU hBrushStyleSubMenu;
137: static HWND hwndCombobox;
138: static int iComboboxWidth;
139: static LONG lTextHeight;
140:
141: int i;
142:
143: switch (msg)
144: {
145: case WM_COMMAND:
146:
147: switch (LOWORD (wParam))
148: {
149: case IDM_PRINT:
150: case IDM_PRINTDLG:
151: {
152: DWORD threadId;
153:
154: if (!CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) PrintThread,
155: (LPVOID) wParam, NULL, &threadId))
156:
157: MessageBox (hwnd,
158: "MainWndProc(): Error creating print thread",
159: ERR_MOD_NAME, MB_OK | MB_ICONHAND);
160: break;
161: }
162:
163: case IDM_GETDEVICECAPS:
164:
165: DialogBox (ghInst, (LPCTSTR) "List", hwnd,
166: (DLGPROC) GetDeviceCapsDlgProc);
167: break;
168:
169: case IDM_ENUMPRINTERS:
170:
171: DialogBox (ghInst, (LPCTSTR) "List", hwnd,
172: (DLGPROC) EnumPrintersDlgProc);
173: break;
174:
175: case IDM_GETPRINTERDRIVER:
176:
177: if (strcmp (gszDeviceName, "Display"))
178:
179: DialogBox (ghInst, (LPCTSTR) "List", hwnd,
180: (DLGPROC) GetPrinterDriverDlgProc);
181: else
182:
183: MessageBox (hwnd, (LPCTSTR) "Please select a printer",
184: (LPCTSTR) "PRINTER.EXE:", MB_OK);
185:
186: break;
187:
188: case IDM_ENUMPRINTERDRIVERS:
189:
190: DialogBox (ghInst, (LPCTSTR) "List", hwnd,
191: (DLGPROC) EnumPrinterDriversDlgProc);
192: break;
193:
194: case IDM_REFRESH:
195:
196: RefreshPrinterCombobox (hwndCombobox);
197: break;
198:
199: case IDM_ABOUT:
200:
201: DialogBox (ghInst, (LPCTSTR) "About", hwnd, (DLGPROC) AboutDlgProc);
202: break;
203:
204: case IDM_HIENGLISH:
205: case IDM_HIMETRIC:
206: case IDM_LOENGLISH:
207: case IDM_LOMETRIC:
208: case IDM_TWIPS:
209: case IDM_ISOTROPIC:
210: case IDM_ANISOTROPIC:
211: case IDM_TEXT:
212:
213: //
214: // Uncheck the last map mode menuitem, check the new map mode
215: // menuitem, set iMappingMode according to menu id, cause a
216: // repaint
217: //
218:
219: for (i = 0; i < MAX_MAP_MODES; i++)
220:
221: if (giMapMode == gaMMLookup[i].iMapMode)
222: {
223: CheckMenuItem (hMappingModesSubMenu, gaMMLookup[i].wMenuItem,
224: MF_UNCHECKED | MF_BYCOMMAND);
225: break;
226: }
227:
228: CheckMenuItem (hMappingModesSubMenu, LOWORD (wParam),
229: MF_CHECKED | MF_BYCOMMAND);
230:
231: for (i = 0; i < MAX_MAP_MODES; i++)
232:
233: if (LOWORD (wParam) == gaMMLookup[i].wMenuItem)
234: {
235: giMapMode = gaMMLookup[i].iMapMode;
236: break;
237: }
238:
239: //
240: // invalidate the entire client so toolbar text gets updated
241: //
242:
243: InvalidateRect (hwnd, NULL, TRUE);
244: break;
245:
246: case IDM_ARC:
247: case IDM_ELLIPSE:
248: case IDM_LINETO:
249: case IDM_PIE:
250: case IDM_PLGBLT:
251: case IDM_POLYBEZIER:
252: case IDM_POLYGON:
253: case IDM_POLYLINE:
254: case IDM_POLYPOLYGON:
255: case IDM_RECTANGLE:
256: case IDM_ROUNDRECT:
257: case IDM_STRETCHBLT:
258: {
259: //
260: // Retrieve the DWORD flag value for the particular menuitem,
261: // toggle (un/check) the menuitem, set/clear the flag in
262: // gdwGraphicsOptions, cause a repaint
263: //
264:
265: DWORD dwGraphic;
266:
267: for (i = 0; i < MAX_GRAPHICS; i++)
268:
269: if (LOWORD (wParam) == gaGraphicLookup[i].wMenuItem)
270: {
271: dwGraphic = gaGraphicLookup[i].dwGraphic;
272: break;
273: }
274:
275: if (GetMenuState (hGraphicsSubMenu, LOWORD(wParam), MF_BYCOMMAND)
276: & MF_CHECKED)
277:
278: {
279: gdwGraphicsOptions &= ~dwGraphic;
280: CheckMenuItem (hGraphicsSubMenu, LOWORD(wParam),
281: MF_UNCHECKED | MF_BYCOMMAND);
282: }
283: else
284: {
285: //
286: // Clear/uncheck the ENUMFONTS flag/menuitem
287: //
288:
289: gdwGraphicsOptions &= ~ENUMFONTS;
290: CheckMenuItem (hGraphicsSubMenu, IDM_ENUMFONTS,
291: MF_UNCHECKED | MF_BYCOMMAND);
292:
293: gdwGraphicsOptions |= dwGraphic;
294: CheckMenuItem (hGraphicsSubMenu, LOWORD(wParam),
295: MF_CHECKED | MF_BYCOMMAND);
296: }
297: InvalidateClient ();
298: break;
299: }
300:
301: case IDM_ALLGRAPHICS:
302:
303: //
304: // Clear/uncheck the ENUMFONTS flag/menuitem, set/check all
305: // other graphics flags/menuitems, cause a repaint
306: //
307:
308: CheckMenuItem (hGraphicsSubMenu, IDM_ENUMFONTS,
309: MF_UNCHECKED | MF_BYCOMMAND);
310:
311: for (i = 0; i < MAX_GRAPHICS; i++)
312:
313: CheckMenuItem (hGraphicsSubMenu, IDM_ARC + i,
314: MF_CHECKED | MF_BYCOMMAND);
315:
316: gdwGraphicsOptions = ALLGRAPHICS | (gdwGraphicsOptions & DRAWAXIS);
317:
318: InvalidateClient ();
319: break;
320:
321: case IDM_NOGRAPHICS:
322:
323: //
324: // Clear/uncheck all graphics flags/menuitems, cause a repaint
325: //
326:
327: for (i = 0; i < MAX_GRAPHICS; i++)
328:
329: CheckMenuItem (hGraphicsSubMenu, IDM_ARC + i,
330: MF_UNCHECKED | MF_BYCOMMAND);
331:
332: gdwGraphicsOptions &= (DRAWAXIS | ENUMFONTS);
333:
334: InvalidateClient ();
335: break;
336:
337: case IDM_ENUMFONTS:
338:
339: //
340: // Set/clear ENUMFONTS flag, toggle (un/check) menuitem, if
341: // checking IDM_ENUMFONTS then uncheck all other items,
342: // cause a repaint
343: //
344:
345: if (GetMenuState (hGraphicsSubMenu, IDM_ENUMFONTS, MF_BYCOMMAND)
346: & MF_CHECKED)
347: {
348: gdwGraphicsOptions &= DRAWAXIS;
349:
350: CheckMenuItem (hGraphicsSubMenu, IDM_ENUMFONTS,
351: MF_UNCHECKED | MF_BYCOMMAND);
352: }
353:
354: else
355: {
356: SendMessage (hwnd, WM_COMMAND, IDM_NOGRAPHICS, 0);
357:
358: gdwGraphicsOptions = ENUMFONTS | (gdwGraphicsOptions & DRAWAXIS);
359:
360: CheckMenuItem (hGraphicsSubMenu, IDM_ENUMFONTS,
361: MF_CHECKED | MF_BYCOMMAND);
362: }
363: InvalidateClient ();
364: break;
365:
366: case IDM_DRAWAXIS:
367:
368: //
369: // Set/clear DRAWAXIS flag, toggle (un/check) menuitem,
370: // cause a repaint
371: //
372:
373: if (GetMenuState (hGraphicsSubMenu, IDM_DRAWAXIS, MF_BYCOMMAND)
374: & MF_CHECKED)
375: {
376: gdwGraphicsOptions &= ~DRAWAXIS;
377:
378: CheckMenuItem (hGraphicsSubMenu, IDM_DRAWAXIS,
379: MF_UNCHECKED | MF_BYCOMMAND);
380: }
381:
382: else
383: {
384: gdwGraphicsOptions |= DRAWAXIS;
385:
386: CheckMenuItem (hGraphicsSubMenu, IDM_DRAWAXIS,
387: MF_CHECKED | MF_BYCOMMAND);
388: }
389: InvalidateClient ();
390: break;
391:
392: case IDM_SETPENCOLOR:
393: case IDM_SETBRUSHCOLOR:
394: case IDM_TEXTCOLOR:
395: {
396: CHOOSECOLOR cc;
397:
398: static DWORD adwCustColors[16];
399:
400: memset (&cc, 0, sizeof (CHOOSECOLOR));
401:
402: cc.lStructSize = sizeof (CHOOSECOLOR);
403: cc.hwndOwner = hwnd;
404: cc.Flags = CC_RGBINIT;
405: cc.lpCustColors = adwCustColors;
406:
407: if (LOWORD (wParam) == IDM_SETPENCOLOR)
408:
409: cc.rgbResult = gdwPenColor;
410:
411: else if (LOWORD (wParam) == IDM_SETBRUSHCOLOR)
412:
413: cc.rgbResult = gdwBrushColor;
414:
415: else
416:
417: cc.rgbResult = gdwTextColor;
418:
419: //
420: // bring up choose color common dialog
421: //
422:
423: ChooseColor (&cc);
424:
425: if (LOWORD (wParam) == IDM_SETPENCOLOR)
426:
427: gdwPenColor = cc.rgbResult;
428:
429: else if (LOWORD (wParam) == IDM_SETBRUSHCOLOR)
430:
431: gdwBrushColor = cc.rgbResult;
432:
433: else
434:
435: gdwTextColor = cc.rgbResult;
436:
437: InvalidateClient ();
438: break;
439: }
440:
441: case IDM_PENWIDTH_1:
442: case IDM_PENWIDTH_2:
443: case IDM_PENWIDTH_3:
444: case IDM_PENWIDTH_4:
445: case IDM_PENWIDTH_5:
446: case IDM_PENWIDTH_6:
447: case IDM_PENWIDTH_7:
448: case IDM_PENWIDTH_8:
449:
450: //
451: // uncheck old pen width menuitem, check new one, cause a repaint
452: //
453:
454: for (i = 0; i < MAX_PENWIDTHS; i++)
455:
456: if (giPenWidth == gaPenWidths[i].iPenWidth)
457: {
458: CheckMenuItem (hPenWidthSubMenu, gaPenWidths[i].wMenuItem,
459: MF_UNCHECKED | MF_BYCOMMAND);
460: break;
461: }
462:
463: for (i = 0; i < MAX_PENWIDTHS; i++)
464:
465: if (LOWORD(wParam) == gaPenWidths[i].wMenuItem)
466: {
467: CheckMenuItem (hPenWidthSubMenu, gaPenWidths[i].wMenuItem,
468: MF_CHECKED | MF_BYCOMMAND);
469:
470: giPenWidth = gaPenWidths[i].iPenWidth;
471:
472: break;
473: }
474:
475: InvalidateClient ();
476: break;
477:
478: case IDM_PENCOLOR_SOLID:
479: case IDM_PENCOLOR_DASH:
480: case IDM_PENCOLOR_DOT:
481: case IDM_PENCOLOR_DASHDOT:
482: case IDM_PENCOLOR_DASHDOTDOT:
483: case IDM_PENCOLOR_NULL:
484: case IDM_PENCOLOR_INSIDEFRAME:
485:
486: //
487: // uncheck old pen style menuitem, check new one, cause a repaint
488: //
489:
490: for (i = 0; i < MAX_PENSTYLES; i++)
491:
492: if (giPenStyle == gaPenStyles[i].iPenStyle)
493: {
494: CheckMenuItem (hPenStyleSubMenu, gaPenStyles[i].wMenuItem,
495: MF_UNCHECKED | MF_BYCOMMAND);
496: break;
497: }
498:
499: for (i = 0; i < MAX_PENSTYLES; i++)
500:
501: if (LOWORD(wParam) == gaPenStyles[i].wMenuItem)
502: {
503: CheckMenuItem (hPenStyleSubMenu, gaPenStyles[i].wMenuItem,
504: MF_CHECKED | MF_BYCOMMAND);
505:
506: giPenStyle = gaPenStyles[i].iPenStyle;
507:
508: break;
509: }
510:
511: InvalidateClient ();
512: break;
513:
514: case IDM_BRUSHSTYLE_SOLID:
515: case IDM_BRUSHSTYLE_BDIAGONAL:
516: case IDM_BRUSHSTYLE_CROSS:
517: case IDM_BRUSHSTYLE_DIAGCROSS:
518: case IDM_BRUSHSTYLE_FDIAGONAL:
519: case IDM_BRUSHSTYLE_HORIZONTAL:
520: case IDM_BRUSHSTYLE_VERTICAL:
521: case IDM_BRUSHSTYLE_FDIAGONAL1:
522: case IDM_BRUSHSTYLE_BDIAGONAL1:
523: case IDM_BRUSHSTYLE_DENSE1:
524: case IDM_BRUSHSTYLE_DENSE2:
525: case IDM_BRUSHSTYLE_DENSE3:
526: case IDM_BRUSHSTYLE_DENSE4:
527: case IDM_BRUSHSTYLE_DENSE5:
528: case IDM_BRUSHSTYLE_DENSE6:
529: case IDM_BRUSHSTYLE_DENSE7:
530: case IDM_BRUSHSTYLE_DENSE8:
531: case IDM_BRUSHSTYLE_NOSHADE:
532: case IDM_BRUSHSTYLE_HALFTONE:
533:
534: //
535: // uncheck old brush style menuitem, check new one, cause a repaint
536: //
537:
538: for (i = 0; i < MAX_BRUSHSTYLES; i++)
539:
540: if (giBrushStyle == gaBrushStyles[i].iBrushStyle)
541: {
542: CheckMenuItem (hBrushStyleSubMenu, gaBrushStyles[i].wMenuItem,
543: MF_UNCHECKED | MF_BYCOMMAND);
544: break;
545: }
546:
547: for (i = 0; i < MAX_BRUSHSTYLES; i++)
548:
549: if (LOWORD(wParam) == gaBrushStyles[i].wMenuItem)
550: {
551: CheckMenuItem (hBrushStyleSubMenu, gaBrushStyles[i].wMenuItem,
552: MF_CHECKED | MF_BYCOMMAND);
553:
554: giBrushStyle = gaBrushStyles[i].iBrushStyle;
555:
556: break;
557: }
558:
559: InvalidateClient ();
560: break;
561:
562: case ID_COMBOBOX:
563:
564: switch (HIWORD(wParam))
565: {
566: case CBN_SELCHANGE:
567: {
568: DWORD dwIndex;
569: char buf[BUFSIZE];
570:
571: //
572: // User clicked on one of the items in the toolbar combobox;
573: // figure out which item, then parse the text apart and
574: // copy it to the gszDriverName, gszDeviceName, and gszPort
575: // variables.
576: //
577:
578: dwIndex = (DWORD) SendMessage ((HWND) lParam,
579: CB_GETCURSEL, 0, 0);
580: SendMessage ((HWND) lParam, CB_GETLBTEXT, dwIndex,
581: (LONG) buf);
582:
583: if (!strcmp (buf, "Display"))
584: {
585: strcpy (gszDeviceName, "Display");
586:
587: gszPort[0] =
588: gszDriverName[0] = '\0';
589: }
590: else
591: { int j = 0;
592:
593: i = -1;
594:
595: while (buf[++i] != ';') gszDeviceName[i] = buf[i];
596: gszDeviceName[i] = '\0';
597: while (buf[++i] != ';') gszPort[j++] = buf[i];
598: gszPort[j] = '\0';
599: j = 0;
600: while (buf[++i] != '\0') gszDriverName[j++] = buf[i];
601: gszDriverName[j] = '\0';
602: }
603: break;
604: }
605: }
606: break;
607: }
608: break;
609:
610: case WM_PAINT:
611: {
612: PAINTSTRUCT ps;
613: RECT rect;
614: HRGN hrgn;
615: HPEN hpen, hpenSave;
616: HBRUSH hbr;
617: char buf[BUFSIZE];
618: POINT p;
619:
620: BeginPaint (hwnd, &ps);
621:
622: //
623: // paint 3d toolbar background & client size text
624: //
625:
626: GetClientRect (hwnd, &rect);
627: rect.bottom = 2*glcyMenu;
628: FillRect (ps.hdc, &rect, GetStockObject (LTGRAY_BRUSH));
629: SelectObject (ps.hdc, GetStockObject (WHITE_PEN));
630: MoveToEx (ps.hdc, 0, 2*glcyMenu - 2, NULL);
631: LineTo (ps.hdc, 0, 0);
632: LineTo (ps.hdc, (int) rect.right, 0);
633: hpen = CreatePen (PS_SOLID, 1, 0x808080);
634: hpenSave = SelectObject (ps.hdc, hpen);
635: MoveToEx (ps.hdc, 0, (int) 2*glcyMenu-1, NULL);
636: LineTo (ps.hdc, (int) rect.right - 1, (int) 2*glcyMenu-1);
637: LineTo (ps.hdc, (int) rect.right - 1, 1);
638: SelectObject (ps.hdc, hpenSave);
639: DeleteObject (hpen);
640:
641: GetClientRect (hwnd, &rect);
642:
643: //
644: // positioning of the string based upon x,y,cx,cy of combobox
645: //
646:
647: SetBkMode (ps.hdc, TRANSPARENT);
648:
649: p.x = rect.right;
650: p.y = (rect.bottom - 2*glcyMenu < 0 ? 0 : rect.bottom - 2*glcyMenu);
651: SetMapMode (ps.hdc, giMapMode);
652: DPtoLP (ps.hdc, &p, 1);
653:
654: if (giMapMode != MM_TEXT && giMapMode != MM_ANISOTROPIC)
655:
656: //
657: // p.y will come out negative because we started with origin in
658: // upper left corner
659: //
660:
661: p.y = -p.y;
662:
663: SetMapMode (ps.hdc, MM_TEXT);
664: sprintf (buf, "cxClient = %ld (%ld)", rect.right, p.x);
665: TextOut (ps.hdc, iComboboxWidth + (int) 3*glcyMenu/2, (int) glcyMenu/8,
666: buf, strlen (buf));
667: sprintf (buf, "cyClient = %ld (%ld)",
668: rect.bottom - 2*glcyMenu < 0 ? 0 : rect.bottom - 2*glcyMenu,
669: p.y);
670: TextOut (ps.hdc, iComboboxWidth + (int) 3*glcyMenu/2,
671: (int) (glcyMenu/8 + lTextHeight),
672: buf, strlen (buf));
673:
674: //
675: // paint graphics background white
676: //
677:
678: rect.top += 2*glcyMenu;
679: FillRect (ps.hdc, &rect, GetStockObject (WHITE_BRUSH));
680:
681:
682: if (rect.bottom <= 4*glcyMenu)
683:
684: //
685: // we don't want to overpaint the toolbar, so just skip Paint() call
686: //
687:
688: goto done_painting;
689:
690: //
691: // set up a clip region so we don't draw all over our toolbar
692: //
693:
694: GetClientRect (hwnd, &rect);
695: rect.top += 2*glcyMenu;
696: hrgn = CreateRectRgnIndirect (&rect);
697: SelectClipRgn (ps.hdc, hrgn);
698: DeleteObject (hrgn);
699:
700: //
701: // set up view port, pens/brushes, & map mode, then paint
702: //
703:
704: rect.top -= 2*glcyMenu;
705:
706: if (giMapMode == MM_TEXT || giMapMode == MM_ANISOTROPIC)
707:
708: SetViewportOrgEx (ps.hdc, glcyMenu, 3*glcyMenu, NULL);
709:
710: else
711:
712: SetViewportOrgEx (ps.hdc, glcyMenu, rect.bottom - glcyMenu, NULL);
713:
714: rect.bottom -= 4*glcyMenu;
715: rect.right -= 2*glcyMenu;
716:
717: hpen = CreatePen (giPenStyle, giPenWidth, gdwPenColor);
718: SelectObject (ps.hdc, hpen);
719: hbr = CreateHatchBrush (giBrushStyle, gdwBrushColor);
720: SelectObject (ps.hdc, hbr);
721:
722: SetTextColor (ps.hdc, gdwTextColor);
723:
724: SetMapMode (ps.hdc, giMapMode);
725: Paint (ps.hdc, &rect);
726:
727: DeleteObject (hpen);
728: DeleteObject (hbr);
729:
730: done_painting:
731:
732: EndPaint (hwnd, &ps);
733: break;
734: }
735:
736: case WM_CREATE:
737: {
738: HDC hdc;
739: TEXTMETRIC tm;
740: SIZE size;
741: HMENU hmenu, hPenSubMenu, hBrushSubMenu;
742:
743: //
744: // initialize the globals
745: //
746:
747: glcyMenu = (LONG) GetSystemMetrics (SM_CYMENU);
748:
749: hmenu = GetMenu (hwnd);
750: hMappingModesSubMenu = GetSubMenu (hmenu, 1);
751: hGraphicsSubMenu = GetSubMenu (hmenu, 2);
752: hPenSubMenu = GetSubMenu (hmenu, 3);
753: hPenWidthSubMenu = GetSubMenu (hPenSubMenu, 1);
754: hPenStyleSubMenu = GetSubMenu (hPenSubMenu, 2);
755: hBrushSubMenu = GetSubMenu (hmenu, 4);
756: hBrushStyleSubMenu = GetSubMenu (hBrushSubMenu, 1);
757:
758: GetTextMetrics ((hdc = GetDC (hwnd)), &tm);
759: lTextHeight = tm.tmHeight;
760:
761: //
762: // create combobox to display current printers in. the width
763: // is caluculated by getting the text extent of a typical
764: // entry in the listbox.
765: //
766:
767:
768: #define ASTRING "long printer name;long port name;long driver name"
769:
770: GetTextExtentPoint (hdc, ASTRING, sizeof (ASTRING), &size);
771:
772: iComboboxWidth = (int) size.cx;
773:
774: ReleaseDC (hwnd, hdc);
775:
776: hwndCombobox = CreateWindow ((LPCSTR) "COMBOBOX", (LPCSTR) "",
777: WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
778: (int) glcyMenu/2,
779: (int) glcyMenu/2 - 2, // - 2 = fudge factor
780: iComboboxWidth,
781: (int) 6*glcyMenu,
782: hwnd, NULL, ghInst, NULL);
783:
784: SetWindowLong (hwndCombobox, GWL_ID, ID_COMBOBOX);
785:
786: PostMessage (hwnd, WM_COMMAND,
787: (WPARAM) MAKELONG (IDM_REFRESH, 0),
788: (LPARAM) 0);
789: PostMessage (hwnd, WM_COMMAND,
790: (WPARAM) MAKELONG (IDM_POLYPOLYGON, 0),
791: (LPARAM) 0);
792: break;
793: }
794:
795: case WM_DESTROY:
796:
797: PostQuitMessage (NULL);
798: break;
799:
800: default:
801:
802: return (DefWindowProc (hwnd, msg, wParam, lParam));
803: }
804: return 0;
805: }
806:
807:
808:
809: /******************************************************************************\
810: *
811: * FUNCTION: AboutDlgProc (standard dialog procedure INPUTS/RETURNS)
812: *
813: * COMMENTS: Handles "About" dialog messages
814: *
815: \******************************************************************************/
816:
817: LRESULT CALLBACK AboutDlgProc (HWND hwnd, UINT msg, WPARAM wParam,
818: LPARAM lParam)
819: {
820: switch (msg)
821: {
822: case WM_INITDIALOG:
823:
824: return TRUE;
825:
826: case WM_COMMAND:
827:
828: switch (LOWORD (wParam))
829: {
830: case IDOK:
831:
832: EndDialog (hwnd, TRUE);
833:
834: return 1;
835: }
836: break;
837: }
838: return 0;
839: }
840:
841:
842:
843: /******************************************************************************\
844: *
845: * FUNCTION: InvalidateClient
846: *
847: * COMMENTS: Eliminates the flashing of the toolbar when we redraw
848: *
849: \******************************************************************************/
850:
851: void InvalidateClient ()
852: {
853: RECT rect;
854:
855: GetClientRect (ghwndMain, &rect);
856:
857: rect.top += 2*glcyMenu;
858:
859: InvalidateRect (ghwndMain, &rect, TRUE);
860: }
861:
862:
863:
864: /******************************************************************************\
865: *
866: * FUNCTION: RefreshPrinterCombobox
867: *
868: * INPUTS: hwndCombobox- handle of the toolbar combobox
869: *
870: * COMMENTS: The idea here is to enumerate all printers & list them in
871: * then combobox in the form: "DEVICE_NAME;PORT;DRIVER_NAME".
872: * Then later, when a user selects one of these, we just
873: * query out the string & parse it apart, sticking the
874: * appropriate parts into the DriverName, DeviceName, and
875: * Port variables.
876: *
877: * Also, the "Display" option is added to the combobox so
878: * that user can get DevCaps info about it.
879: *
880: \******************************************************************************/
881:
882: void RefreshPrinterCombobox (HWND hwndCombobox)
883: {
884: DWORD dwFlags = PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL;
885: LPPRINTER_INFO_2 pPrinters;
886: DWORD cbPrinters;
887: DWORD cReturned, i;
888: char buf[256];
889:
890: SendMessage (hwndCombobox, CB_RESETCONTENT, 0, 0);
891:
892: //
893: // add the "Display" option to the combobox
894: //
895:
896: strcpy (buf, "Display");
897: SendMessage (hwndCombobox, CB_INSERTSTRING, (UINT)-1, (LONG) buf);
898:
899: //
900: // get byte count needed for buffer, alloc buffer, the enum the printers
901: //
902:
903: EnumPrinters (dwFlags, NULL, 2, NULL, 0, &cbPrinters,
904: &cReturned);
905:
906: if (!(pPrinters = (LPPRINTER_INFO_2) LocalAlloc (LPTR, cbPrinters + 4)))
907: {
908: MessageBox (ghwndMain, (LPCTSTR) "LocalAlloc failed",
909: (LPCTSTR) ERR_MOD_NAME, MB_OK | MB_ICONEXCLAMATION);
910: goto done_refreshing;
911: }
912:
913:
914: if (!EnumPrinters (dwFlags, NULL, 2, (LPBYTE) pPrinters,
915: cbPrinters, &cbPrinters, &cReturned))
916: {
917: MessageBox (ghwndMain, (LPCTSTR) "EnumPrinters failed",
918: (LPCTSTR) ERR_MOD_NAME, MB_OK | MB_ICONEXCLAMATION);
919: goto done_refreshing;
920: }
921:
922: if (cReturned > 0)
923:
924: for (i = 0; i < cReturned; i++)
925: {
926: //
927: // for each printer in the PRINTER_INFO_2 array: build a string that
928: // looks like "DEVICE_NAME;PORT;DRIVER_NAME"
929: //
930:
931: strcpy (buf, (pPrinters + i)->pPrinterName);
932: strcat (buf, ";");
933: strcat (buf, (pPrinters + i)->pPortName);
934: strcat (buf, ";");
935: strcat (buf, (pPrinters + i)->pDriverName);
936:
937: SendMessage (hwndCombobox, CB_INSERTSTRING, (UINT)-1, (LONG) buf);
938: }
939:
940: else
941:
942: MessageBox (ghwndMain, "No printers listed", "PRINTER.EXE", MB_OK);
943:
944: done_refreshing:
945:
946: SendMessage (hwndCombobox, CB_SELECTSTRING, (UINT) -1, (LONG) buf);
947:
948: PostMessage (ghwndMain, WM_COMMAND,
949: (WPARAM) MAKELONG (ID_COMBOBOX, CBN_SELCHANGE),
950: (LPARAM) hwndCombobox);
951:
952: LocalFree (LocalHandle (pPrinters));
953: }
954:
955:
956:
957: /******************************************************************************\
958: *
959: * FUNCTION: PrintThread
960: *
961: * INPUTS: wParam - wParam of a WM_COMMAND message containing menuitem id
962: *
963: * COMMENTS: This is the code for the print thread created when the user
964: * selects the "Print" or "PrintDlg" menuitems. A thread is used
965: * here more demostration purposes only, since we really don't
966: * have any background processing to do. A real app would want
967: * to have alot more error checking here (e.g. check return of
968: * StartDoc, StartPage...).
969: *
970: \******************************************************************************/
971:
972: void PrintThread (LPVOID wParam)
973: {
974: DOCINFO di;
975: RECT rect;
976: HPEN hpen;
977: HBRUSH hbr;
978:
979: switch (LOWORD((WPARAM) wParam))
980: {
981: case IDM_PRINT:
982: {
983: if (!strcmp (gszDeviceName, "Display"))
984: {
985: MessageBox (ghwndMain, "Please select a printer",
986: "PRINTER.EXE:", MB_OK);
987: return;
988: }
989: else if (!(ghdc = CreateDC (gszDriverName, gszDeviceName, gszPort, NULL)))
990: {
991: MessageBox (ghwndMain, "PrintThread(): CreateDC() failed",
992: ERR_MOD_NAME, MB_OK);
993: return;
994: }
995: break;
996: }
997:
998: case IDM_PRINTDLG:
999: {
1000: PRINTDLG pd;
1001:
1002: //
1003: // Initialize a PRINTDLG struct and call PrintDlg to allow user to
1004: // specify various printing options...
1005: //
1006:
1007: memset (&pd, 0, sizeof(PRINTDLG));
1008:
1009: pd.lStructSize = sizeof(PRINTDLG);
1010: pd.hwndOwner = ghwndMain;
1011: pd.Flags = PD_RETURNDC;
1012: pd.hInstance = NULL;
1013:
1014: PrintDlg(&pd);
1015: ghdc = pd.hDC;
1016:
1017: if (pd.hDevMode)
1018:
1019: GlobalFree (pd.hDevMode);
1020:
1021: if (pd.hDevNames)
1022:
1023: GlobalFree (pd.hDevNames);
1024:
1025: if (!ghdc)
1026: {
1027: MessageBox (ghwndMain, "PrintDlg (PD_RETURNDC) failed",
1028: ERR_MOD_NAME, MB_OK);
1029: return;
1030: }
1031: }
1032: }
1033:
1034: //
1035: // put up Abort & install the abort procedure
1036: //
1037:
1038: gbAbort = FALSE;
1039: ghwndAbort = CreateDialog (ghInst, (LPCTSTR) "Abort", ghwndMain,
1040: (DLGPROC) AbortDlgProc);
1041: EnableWindow (ghwndMain, FALSE);
1042: SetAbortProc (ghdc, AbortProc);
1043:
1044: //
1045: // create & select pen/brush
1046: //
1047:
1048: hpen = CreatePen (giPenStyle, giPenWidth, gdwPenColor);
1049: SelectObject (ghdc, hpen);
1050: hbr = CreateHatchBrush (giBrushStyle, gdwBrushColor);
1051: SelectObject (ghdc, hbr);
1052:
1053: SetTextColor (ghdc, gdwTextColor);
1054:
1055: SetMapMode (ghdc, giMapMode);
1056: rect.top =
1057: rect.left = 0;
1058: rect.right = GetDeviceCaps (ghdc, HORZRES);
1059: rect.bottom = GetDeviceCaps (ghdc, VERTRES);
1060: di.cbSize = sizeof(DOCINFO);
1061: di.lpszDocName = "print test";
1062: di.lpszOutput = NULL;
1063:
1064: StartDoc (ghdc, &di);
1065: StartPage (ghdc);
1066:
1067: if (gdwGraphicsOptions)
1068:
1069: Paint (ghdc, &rect);
1070:
1071: else
1072:
1073: TextOut (ghdc, 5, 5, (LPCTSTR) "A blank page!", sizeof("A blank page!"));
1074:
1075: EndPage (ghdc);
1076: EndDoc (ghdc);
1077: DeleteDC (ghdc);
1078:
1079: if (!gbAbort)
1080: {
1081: EnableWindow (ghwndMain, TRUE);
1082: DestroyWindow (ghwndAbort);
1083: }
1084: }
1085:
1086:
1087:
1088: /******************************************************************************\
1089: *
1090: * FUNCTION: AbortProc
1091: *
1092: * COMMENTS: Standard printing abort proc
1093: *
1094: \******************************************************************************/
1095:
1096: BOOL CALLBACK AbortProc (HDC hdc, int error)
1097: {
1098: MSG msg;
1099:
1100: while (!gbAbort && PeekMessage (&msg, NULL, NULL, NULL, PM_REMOVE))
1101:
1102: if (!ghwndAbort || !IsDialogMessage (ghwndAbort, &msg))
1103: {
1104: TranslateMessage (&msg);
1105: DispatchMessage (&msg);
1106: }
1107:
1108: return !gbAbort;
1109: }
1110:
1111:
1112:
1113: /******************************************************************************\
1114: *
1115: * FUNCTION: AbortDlgProc (standard dialog procedure INPUTS/RETURNS)
1116: *
1117: * COMMENTS: Handles "Abort" dialog messages
1118: *
1119: \******************************************************************************/
1120:
1121: LRESULT CALLBACK AbortDlgProc (HWND hwnd, UINT msg, WPARAM wParam,
1122: LPARAM lParam)
1123: {
1124: switch (msg)
1125: {
1126: case WM_INITDIALOG:
1127:
1128: ghwndAbort = hwnd;
1129: EnableMenuItem (GetSystemMenu (hwnd, FALSE), SC_CLOSE, MF_GRAYED);
1130: break;
1131:
1132: case WM_COMMAND:
1133:
1134: switch (LOWORD (wParam))
1135: {
1136: case DID_CANCEL:
1137:
1138: gbAbort = TRUE;
1139: AbortDoc (ghdc);
1140: EnableWindow (ghwndMain, TRUE);
1141: DestroyWindow (hwnd);
1142: return TRUE;
1143: }
1144: break;
1145: }
1146: return 0;
1147: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.