PRINTING GRAPHICS AND TEXT

Printing from a Windows program usually involves more overhead than shown in the FORMFEED program, as well as some GDI calls to actually print something. Let's write a program that prints one page of text and graphics. We'll start with the method shown in the FORMFEED program and then add some enhancements. We'll be looking at four versions of this program called PRINT1, PRINT2, PRINT3, and PRINT4. To avoid a lot of duplicated source code, each of these programs will use functions contained in the PRINT.C file, which is shown in Figure 15-5.

PRINT.C

/*-------------------------------------------------------------------

PRINT.C -- Common Routines for Print1, Print2, Print3, and Print4

(c) Charles Petzold, 1990

-------------------------------------------------------------------*/

#include <windows.h>

#include <string.h>

long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;

BOOL PrintMyPage (HWND) ;

extern HANDLE hInst ;

extern char szAppName [] ;

extern char szCaption [] ;

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,

LPSTR lpszCmdLine, int nCmdShow)

{

HWND hwnd ;

MSG msg ;

WNDCLASS wndclass ;

PRINT4 programs.

if (!hPrevInstance)

{wndclass.style = CS_HREDRAW | CS_VREDRAW ;

wndclass.lpfnWndProc = WndProc ;

wndclass.cbClsExtra = 0 ;

wndclass.cbWndExtra = 0 ;

wndclass.hInstance = hInstance ;

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;

wndclass.lpszMenuName = NULL ;

wndclass.lpszClassName = szAppName ;

RegisterClass (&wndclass) ;

}hInst = hInstance ;

hwnd = CreateWindow (szAppName, szCaption,

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, nCmdShow) ;

UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))

{TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}return msg.wParam ;

}long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)

{HMENU hMenu ;

switch (message)

{case WM_CREATE :

hMenu = GetSystemMenu (hwnd, FALSE) ;

AppendMenu (hMenu, MF_SEPARATOR, 0, NULL) ;

AppendMenu (hMenu, 0, 1, "&Print") ;

return 0 ;

case WM_SYSCOMMAND :

if (wParam == 1)

(continued)

{if (PrintMyPage (hwnd))

MessageBox (hwnd, "Could not print page",

szAppName, MB_OK | MB_ICONEXCLAMATION) ;

return 0 ;

}break ;

case WM_DESTROY :

PostQuitMessage (0) ;

return 0 ;

}return DefWindowProc (hwnd, message, wParam, lParam) ;

}HDC GetPrinterDC (void)

{static char szPrinter [80] ;

char *szDevice, *szDriver, *szOutput ;

GetProfileString ("windows", "device", ",,,", szPrinter, 80) ;

if ((szDevice = strtok (szPrinter, "," )) &&

(szDriver = strtok (NULL, ", ")) &&

(szOutput = strtok (NULL, ", ")))

return CreateDC (szDriver, szDevice, szOutput, NULL) ;

return 0 ;

}void PageGDICalls (HDC hdcPrn, short cxPage, short cyPage)

{static char szTextStr [] = "Hello, Printer!" ;

DWORD dwExtent ;

Rectangle (hdcPrn, 0, 0, cxPage, cyPage) ;

MoveTo (hdcPrn, 0, 0) ;

LineTo (hdcPrn, cxPage, cyPage) ;

MoveTo (hdcPrn, cxPage, 0) ;

LineTo (hdcPrn, 0, cyPage) ;

SaveDC (hdcPrn) ;

SetMapMode (hdcPrn, MM_ISOTROPIC) ;

SetWindowExt (hdcPrn, 1000, 1000) ;

SetViewportExt (hdcPrn, cxPage / 2, -cyPage / 2) ;

SetViewportOrg (hdcPrn, cxPage / 2, cyPage / 2) ;

(continued)

Ellipse (hdcPrn, -500, 500, 500, -500) ;

dwExtent = GetTextExtent (hdcPrn, szTextStr, sizeof szTextStr - 1) ;

TextOut (hdcPrn, LOWORD (dwExtent) / 2, HIWORD (dwExtent) / 2,

szTextStr, sizeof szTextStr - 1) ;

RestoreDC (hdcPrn, -1) ;

}PRINT.C contains the functions WinMain, WndProc, and GetPrinterDC and a function called PageGDICalls, which expects to receive a handle to the printer device context and two variables containing the width and height of the printer page. PageGDICalls draws a rectangle that encompasses the entire page, two lines between opposite corners of the page, a circle in the middle of the page (its diameter half the lesser of the printer height and width), and the text ”Hello, Printer!“ in the center of this ellipse.

During processing of the WM_CREATE message, WndProc adds a Print option to the system menu. Selecting this option causes a call to PrintMyPage, a function that we'll enhance over the course of the four versions of the program. PrintMyPage returns TRUE (nonzero) if it encounters an error during printing and returns FALSE otherwise. If PrintMyPage returns TRUE, WndProc displays a message box to inform you of the error.