HOWTO: Print a Document

Last reviewed: March 4, 1998
Article ID: Q139652
The information in this article applies to:

- Microsoft Win32 Application Programming Interface (API)

  included with:
   - Microsoft Windows NT versions 3.5, 3.51
   - Microsoft Windows 95
   - Windows CE version 2.0

SUMMARY

This article describes each of the seven steps required to print a document to a printer in Windows programming. Note that while Windows CE version 2.0 and later do provide printing support, you need to consider the following caveats:

  • Windows CE provides no support for spooling or printing multiple copies.
  • Some PRINTDLG structure members have different names in Windows CE.
  • You need to use the PD_RETURNDEFAULTDC flag instead of PD_RETURNDEFAULT PD_RETURNDC.

MORE INFORMATION

  1. Obtain a Printer Device Context. To draw graphics or text on the printer device, an application needs to obtain a printer device context. The PrintDlg() function can be used to obtain the printer DC. PrintDlg() can display a Print Dialog box to allow the user to select a printer, or it can return information about the default printer. In addition to other information about the printer, PrintDlg() will return a printer device context in the PRINTDLG structure when PD_RETURNDC is specified as one of the flags. This device context matches the selections the user made in the dialog box. The GetPrinterDC function in the sample code at the end of this article illustrates the use of PrintDlg() to obtain a printer DC.

    If you want to create a printer DC without displaying the Print dialog box, then you need to specify PD_RETURNDEFAULT | PD_RETURNDC flags as shown in the sample code in this article. The PD_RETURNDEFAULT flag is used to retrieve information about the default printer without displaying the Print dialog box. PD_RETURNDC flag is used to direct PrintDlg to automatically create a device or information context for the printer.

  2. Set Up the Abort Function. An application must use the SetAbortProc function to set the application-defined abort function that allows a print job to be canceled during spooling. In the AbortProc function, the abort procedure can check the error code to see if an error occurred while printing. The error code is zero if no error has occurred.

  3. Use StartDoc() to Start the Print Job. The StartDoc function starts a print job. A DOCINFO structure is initialized and passed to the StartDoc function. It is a good idea to initialize the DOCINFO structure by filling it with zeros. For more information, please see the following article in the Microsoft Knowledge Base:

          ARTICLE-ID: Q135119
    
          TITLE     : PRB: StartDoc() Fails with Non-Zeroed DOCINFO
    
       The InitDocStruct function illustrated later in this article performs
       this initialization.
    
    

  4. Call StartPage(). The StartPage function prepares the printer driver to accept data. For example:

          StartPage( hDC );
    

  5. Draw on the Device Context. Draw graphics or text on the printer device. For example, DrawStuff() illustrates how to draw text on the printer DC.

  6. Call EndPage(). The EndPage function informs the device that the application has finished writing to a page. This function is typically used to direct the device driver to advance to a new page. To print multiple pages, Steps 4, 5, and 6 must be used for every page of the document as in this example:

          for( i = START_PAGE; i <= END_PAGE; i++)
    
            {
              StartPage();
              DrawStuff();
              EndPage();
            }
    
    

  7. Call EndDoc(). The EndDoc function ends a print job. For additional information on this topic, please refer to the Win32 SDK documentation Overviews section.

Sample Code

The following PrintStuff() function illustrates the printing process:

   /*==============================================*/
   /* Sample code :  Typical printing process      */
   /* =============================================*/
   
   void PrintStuff( HWND hWndParent )
   {
       HDC        hDC;
       DOCINFO    di;
   
       // Need a printer DC to print to.
       hDC = GetPrinterDC();
   
       // Did you get a good DC?
       if( !hdc)
       {
           MessageBox(NULL, "Error creating DC", "Error",
                                       MB_APPLMODAL | MB_OK );
           return;
       }
   
       // You always have to use an AbortProc().
       if( SetAbortProc( hDC, AbortProc ) == SP_ERROR )
       {
           MessageBox( NULL, "Error setting up AbortProc",
                                       "Error", MB_APPLMODAL | MB_OK);
           return;
       }
   
       // Init the DOCINFO and start the document.
       InitDocStruct( &di, "MyDoc");
       StartDoc( hDC, &di );
   
       // Print one page.
       StartPage( hDC );
       DrawStuff( hDC );
       EndPage( hDC );
   
       // Indicate end of document.
       EndDoc( hDC );
   
       // Clean up
       DeleteDC( hDC );
   }
   
   /*===============================*/
   /* Obtain printer device context */
   /* ==============================*/
   HDC GetPrinterDC(void)
   {
       PRINTDLG pdlg;
   
       // Initialize the PRINTDLG structure.
       memset( &pdlg, 0, sizeof( PRINTDLG ) );
       pdlg.lStructSize = sizeof( PRINTDLG );
       // Set the flag to return printer DC.
       pdlg.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
   
       // Invoke the printer dialog box.
       PrintDlg( &pdlg );
       // hDC member of the PRINTDLG structure contains
       // the printer DC.
       return pdlg.hDC;
   }
   
   /*===============================*/
   /* The Abort Procudure           */
   /* ==============================*/
   BOOL CALLBACK AbortProc( HDC hDC, int Error )
   {
       MSG   msg;
       while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
       {
           TranslateMessage( &msg );
           DispatchMessage( &msg );
       }
       return TRUE;
   }
   
   /*===============================*/
   /* Initialize DOCINFO structure  */
   /* ==============================*/
   void InitDocStruct( DOCINFO* di, char* docname)
   {
       // Always zero it before using it.
       memset( di, 0, sizeof( DOCINFO ) );
       // Fill in the required members.
       di->cbSize = sizeof( DOCINFO );
       di->lpszDocName = docname;
   }
   
   /*===============================*/
   /* Drawing on the DC             */
   /* ==============================*/
   void DrawStuff( HDC hdc)
   {
       // This is the function that does draws on a given DC.
       // You are printing text here.
       TextOut(hdc, 0,0, "Test Printing", lstrlen( "Test Printing" ) );
   }
Keywords          : GdiPrn kbcode
Version           : WINNT:3.5,3.51;WIN95
Platform          : Win95 winnt
Issue type        : kbhowto


================================================================================


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: March 4, 1998
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.