Microsoft KB Archive/139652

From BetaArchive Wiki

HOWTO: Print a Document

Q139652



The information in this article applies to:


  • Microsoft Win32 Application Programming Interface (API), used with:
    • Microsoft Windows NT Server versions 3.5, 3.51
    • Microsoft Windows NT Workstation versions 3.5, 3.51
    • Microsoft Windows 95
    • Microsoft Windows CE Services 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:

  • 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_RETURNDEFAULTPD_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() returns 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. Setup 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:

    Q135119 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" ) );
   } 

Additional query words:

Keywords : _IK kbGDI kbOSWinNT350 kbOSWinNT351 kbPrinting kbOSWinCEsearch kbOSWin95 kbDSupport
Issue type : kbhowto
Technology : kbAudDeveloper kbWin32sSearch kbWin32API


Last Reviewed: December 16, 2000
© 2001 Microsoft Corporation. All rights reserved. Terms of Use.