HOWTO: Use PASSTHROUGH As An Alternative to SpoolFile()Last reviewed: January 15, 1998Article ID: Q111010 |
The information in this article applies to:
SUMMARYApplications written for Windows 3.1 can use either the SpoolFile() function or the PASSTHROUGH printer escape to send a printer-specific file to Print Manager for spooling to a printer. Because there are several caveats to using SpoolFile(), using the PASSTHROUGH printer escape is often a better choice.
MORE INFORMATIONThe following is a list of known limitations of the Windows SDK SpoolFile() function:
Sample CodeThe following sample code demonstrates how to use the PASSTHROUGH escape:
/* FILE: spool.c */ #include <windows.h> #include <print.h> #include <commdlg.h> #include <string.h> // Function prototypes BOOL FAR PASCAL PrintFile(LPSTR, HDC, HGLOBAL, HGLOBAL); VOID SendFile(HDC, LPSTR); HDC GetPrinterDC(HGLOBAL, HGLOBAL); BOOL CALLBACK __export PrintAbortProc(HDC, int); // Play with this number #define BUFSIZE 2048 // Convenient structure for use with PASSTHROUGH escape typedef struct { WORD wSize; BYTE bData[2]; // placeholder } PASSTHROUGHSTRUCT, FAR *LPPTS; BOOL bAbort; // Global printing abort flag //************************************************************* // // PrintFile() // // Purpose: // Reads a file and copies it to a printer using the // PASSTHROUGH escape. // // Parameters: // LPSTR szFile - Pointer to path/filename to print // HDC hPrnDC - Handle to printer DC or NULL // HGLOBAL hDevNames - Handle to DEVNAMES struct or NULL // HGLOBAL hDevMode - Handle to DEVMODE struct or NULL // // Return: // Returns nonzero for success or zero for failure. // // Comments: // hDevNames and hDevMode are only used if hPrnDC is NULL. // If both hPrnDC and hDevNames are NULL, the default // printer is used. // // History: Date Author Comment // 6/03/93 JMS Created // //************************************************************* BOOL FAR PASCAL PrintFile ( LPSTR szFile, HDC hPrnDC, HGLOBAL hDevNames, HGLOBAL hDevMode ) { int iEsc; BOOL bLocalDC = TRUE; // Assume we must create a DC (hPrnDC == NULL) bAbort = FALSE; // Haven't aborted yet // Make sure we have a printer DC if (!hPrnDC) hPrnDC = GetPrinterDC(hDevNames, hDevMode); else bLocalDC = FALSE; // Use passed in hPrnDC if (!hPrnDC) return FALSE; // PASSTHROUGH is required. If driver doesn't support it, bail out. iEsc = PASSTHROUGH; if (!Escape(hPrnDC, QUERYESCSUPPORT, sizeof(int), (LPSTR)&iEsc, NULL)) { bAbort = TRUE; goto MSFCleanUp; } // If we created the DC, install an abort procedure. We don't have // a Cancel dialog box, but the abort proc enables multitasking. // (Use __export and compile with -GA or -GD so we don't need // a MakeProcInstance.) if (bLocalDC) Escape (hPrnDC, SETABORTPROC, 0, (LPSTR) PrintAbortProc, NULL); // Call EPSPRINTING if it is supported (that is, if we're on a // PostScript printer) to suppress downloading the pscript header. iEsc = EPSPRINTING; if (Escape(hPrnDC, QUERYESCSUPPORT, sizeof(int), (LPSTR)&iEsc, NULL)) { iEsc = 1; // 1 == enable PASSTHROUGH (disable pscript header) Escape(hPrnDC, EPSPRINTING, sizeof(int), (LPSTR)&iEsc, NULL); } SendFile(hPrnDC, szFile); // Send file to printer (could do multiple // files) MSFCleanUp: // Done if (bLocalDC) // Only delete DC if we created it DeleteDC(hPrnDC); return !bAbort; } /* PrintFile() */ VOID SendFile(HDC hPrnDC, LPSTR szFile) { static LPPTS lpPTS=NULL; // Pointer to PASSTHROUGHSTRUCT OFSTRUCT ofs; HFILE hFile; hFile = OpenFile((LPSTR) szFile, &ofs, OF_READ); if (hFile == HFILE_ERROR) { bAbort = TRUE; // Can't open file! return; } if (!lpPTS && !(lpPTS = (LPPTS)GlobalLock(GlobalAlloc(GPTR, sizeof(WORD) + BUFSIZE)))) { bAbort = TRUE; // Can't allocate memory for buffer! return; } Escape (hPrnDC, STARTDOC, 0, "", NULL); // Loop through the file, reading a chunk at a time and passing // it to the printer. QueryAbort calls the abort procedure, which // processes messages so we don't tie up the whole system. // We could skip the QueryAbort, in which case we wouldn't need // to set an abort proc at all. do { if ((lpPTS->wSize=_lread(hFile, lpPTS->bData, BUFSIZE)) == HFILE_ERROR) { bAbort = TRUE; // error reading file break; } Escape(hPrnDC, PASSTHROUGH, NULL, (LPSTR)lpPTS, NULL); } while ((lpPTS->wSize == BUFSIZE) && QueryAbort(hPrnDC, 0)); if (!bAbort) Escape(hPrnDC, ENDDOC, NULL, NULL, NULL); _lclose(hFile); } /* SendFile() */ HDC GetPrinterDC(HGLOBAL hDevNames, HGLOBAL hDevMode) { HDC hdc; char szPrinter[64]; LPSTR szDevice=NULL, szDriver=NULL, szOutput=NULL; LPDEVMODE lpdm; if (hDevNames) { LPDEVNAMES lpdn = (LPDEVNAMES) GlobalLock(hDevNames); szDriver = (LPSTR) lpdn + lpdn->wDriverOffset; szDevice = (LPSTR) lpdn + lpdn->wDeviceOffset; szOutput = (LPSTR) lpdn + lpdn->wOutputOffset; if (hDevMode) lpdm = (LPDEVMODE) GlobalLock(hDevMode); } else { // Get default printer info GetProfileString ("windows", "device", "", szPrinter, 64); if (!((szDevice = strtok (szPrinter, "," )) && (szDriver = strtok (NULL, ", ")) && (szOutput = strtok (NULL, ", ")))) return NULL; // No default printer lpdm = NULL; // Don't use DEVMODE with default printer } hdc = CreateDC(szDriver, szDevice, szOutput, lpdm); if (hDevMode && lpdm) GlobalUnlock(hDevMode); if (hDevNames) GlobalUnlock(hDevNames); return hdc; } /* GetPrinterDC() */ BOOL CALLBACK __export PrintAbortProc(HDC hdc, int code) { MSG msg; while (!bAbort && PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (!bAbort); } /* PrintAbortProc() */ /*** EOF: spool.c ***/The PrintFile() function in the above sample code can be used instead of SpoolFile(). PrintFile() uses the PASSTHROUGH printer escape to send a file to the printer. This method has several advantages over SpoolFile():
For more information about the driver RAW.DRV, please see the following article in the Microsoft Knowledge Base:
ARTICLE-ID: Q35708 TITLE : SAMPLE: Using a Device Driver to Send Binary Data to a PrinterThere have been reports of problems using the PASSTHROUGH escape with the driver HPPCL5A.DRV. This is the version of the printer driver for the HP LaserJet III series that shipped with Windows 3.1. A more recent version of the driver (HPPCL5MS.DRV), which has no known problems with the PASSTHROUGH escape, is available in the Windows Driver Library (WDL). To obtain the latest driver for the HP LaserJet III series, download the self-extracting file HPPCL5.EXE from the WDL. Intermixing the PASSTHROUGH escape with calls to GDI output functions can be problematic. It is best to print using either the PASSTHROUGH approach or using the "normal" Windows printing method using GDI output functions. If you must intermix the two approaches, you will get best results if you use the NEXTBAND escape and send the raw data via the PASSTHROUGH escape on each first (all text) band and call the GDI output functions on subsequent printer bands. NOTE: The Win32 API provides APIs for spooling raw print jobs.
|
Additional query words: RAW gpf gp-fault
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |