c++ - Printer output problem
- Heinz-Peter Nuettgens (14/14) Sep 18 2001 Hi,
- Arjan Knepper (163/177) Sep 18 2001 Hope this helps:
- Heinz-Peter Nuettgens (33/216) Sep 18 2001 Hi Arjan,
- Walter (15/296) Sep 18 2001 I'm afraid the stdprn is only suitable for primitive writes to the print...
- Cesar Rabak (17/33) Sep 22 2001 Heinz-Peter,
Hi, there is a problem occurring, when I try to send data via fopen(..; fwrite(.. to a stream leading to a printer port, for example "LPT1". It's working, if everything is alright, BUT when printer isn't ready (no paper or some other prob) or even not present, the following behaviour occurrs: fopen takes some time, but works, and the following fwrite call never returns and causes the application to hang. I know that this way to output data is quite old fashioned. But how can I avoid such a problem? I think there should be some timeout in the fwrite routines, after which they abort and return to the calling program. Best wishes and condolences for what happened last tuesday I saw it on tv but still can't believe what I saw Heinz-Peter
Sep 18 2001
Hope this helps: See MSDN KB:Windows Development HOWTO: Print a Document ID: Q139652 -------------------------------------------------------------------------------- The information in this article applies to: Microsoft Win32 Application Programming Interface (API), used with: Microsoft Windows NT, 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 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. 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. 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. Call StartPage(). The StartPage function prepares the printer driver to accept data. For example: StartPage( hDC ); 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. 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(); } 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 : kbcode kbGDI kbNTOS350 kbNTOS351 kbPrinting kbWinCE kbWinOS95 kbDSupport Version : winnt:3.5,3.51 Platform : winnt Issue type : kbhowto Last Reviewed: July 6, 1999 © 2000 Microsoft Corporation. All rights reserved. Terms of Use. Heinz-Peter Nuettgens wrote:Hi, there is a problem occurring, when I try to send data via fopen(..; fwrite(.. to a stream leading to a printer port, for example "LPT1". It's working, if everything is alright, BUT when printer isn't ready (no paper or some other prob) or even not present, the following behaviour occurrs: fopen takes some time, but works, and the following fwrite call never returns and causes the application to hang. I know that this way to output data is quite old fashioned. But how can I avoid such a problem? I think there should be some timeout in the fwrite routines, after which they abort and return to the calling program. Best wishes and condolences for what happened last tuesday I saw it on tv but still can't believe what I saw Heinz-Peter
Sep 18 2001
Hi Arjan, thank you for your suggestion. But my problem isn't the output to the printer. I am using the described way in other parts of the program, which do it right even when a printer error occurs. BUT I just want to do standard old fashioned stream output to the printer, just to print a few lines of text without positioning, scaling, handling DCs and more. If the printer is ready, the output works like it should. But if there is any error condition, the whole thread stops running. That shouldn't be, imho. I think the stdlib should be able to return an error condition and shouldn't wait for Godot to come. :-(( Heinz-Peter "Arjan Knepper" <arjan jak.nl> schrieb im Newsbeitrag news:3BA72CCA.B6FFCAC4 jak.nl...Hope this helps: See MSDN KB:Windows Development HOWTO: Print a Document ID: Q139652 --------------------------------------------------------------------------------The information in this article applies to: Microsoft Win32 Application Programming Interface (API), used with: Microsoft Windows NT, 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 adocumentto a printer in Windows programming. Note that while Windows CE version2.0and 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 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 itcanreturn information about the default printer. In addition to other information about the printer, PrintDlg() returns a printer device contextinthe PRINTDLG structure when PD_RETURNDC is specified as one of the flags. This device context matches the selections the user made in the dialogbox.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 dialogbox,then you need to specify PD_RETURNDEFAULT | PD_RETURNDC flags as shown inthesample 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. Setup the Abort function. An application must use the SetAbortProcfunctionto set the application-defined Abort function that allows a print job tobecanceled during spooling. In the AbortProc function, the abort procedurecancheck the error code to see if an error occurred while printing. The error code is zero if no error has occurred. Use StartDoc() to Start the Print Job. The StartDoc function starts aprintjob. A DOCINFO structure is initialized and passed to the StartDocfunction.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. Call StartPage(). The StartPage function prepares the printer driver to accept data. For example: StartPage( hDC ); Draw on the Device Context. Draw graphics or text on the printer device.Forexample, DrawStuff() illustrates how to draw text on the printer DC. Call EndPage(). The EndPage function informs the device that theapplicationhas finished writing to a page. This function is typically used to directthedevice 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(); } 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 : kbcode kbGDI kbNTOS350 kbNTOS351 kbPrinting kbWinCE kbWinOS95 kbDSupport Version : winnt:3.5,3.51 Platform : winnt Issue type : kbhowto Last Reviewed: July 6, 1999 © 2000 Microsoft Corporation. All rights reserved. Terms of Use. Heinz-Peter Nuettgens wrote:IHi, there is a problem occurring, when I try to send data via fopen(..; fwrite(.. to a stream leading to a printer port, for example "LPT1". It's working, if everything is alright, BUT when printer isn't ready (no paper or some other prob) or even not present, the following behaviour occurrs: fopen takes some time, but works, and the following fwrite call never returns and causes the application to hang. I know that this way to output data is quite old fashioned. But how canavoid such a problem? I think there should be some timeout in the fwrite routines, after which they abort and return to the calling program. Best wishes and condolences for what happened last tuesday I saw it on tv but still can't believe what I saw Heinz-Peter
Sep 18 2001
I'm afraid the stdprn is only suitable for primitive writes to the printer. More advanced control over it means you'll need to write some code... Heinz-Peter Nuettgens wrote in message <9o7sjd$2ir4$1 digitaldaemon.com>...Hi Arjan, thank you for your suggestion. But my problem isn't the output to the printer. I am using the described way in other parts of the program, which do it right even when a printer error occurs. BUT I just want to do standard old fashioned stream output to the printer, just to print a few lines of text without positioning, scaling, handlingDCsand more. If the printer is ready, the output works like it should. But if there is any error condition, the whole thread stops running. That shouldn't be, imho. I think the stdlib should be able to return an error condition and shouldn't wait for Godot to come. :-(( Heinz-Peter "Arjan Knepper" <arjan jak.nl> schrieb im Newsbeitrag news:3BA72CCA.B6FFCAC4 jak.nl...-Hope this helps: See MSDN KB:Windows Development HOWTO: Print a Document ID: Q139652 --------------------------------------------------------------------------------The information in this article applies to: Microsoft Win32 Application Programming Interface (API), used with: Microsoft Windows NT, versions 3.5, 3.51 Microsoft Windows 95 Microsoft Windows CE Services version 2.0 -------------------------------------------------------------------------------following:SUMMARY This article describes each of the seven steps required to print adocumentto a printer in Windows programming. Note that while Windows CE version2.0and later do provide printing support, you need to consider thecontextWindows 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 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 itcanreturn information about the default printer. In addition to other information about the printer, PrintDlg() returns a printer deviceinretrievethe PRINTDLG structure when PD_RETURNDC is specified as one of the flags. This device context matches the selections the user made in the dialogbox.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 dialogbox,then you need to specify PD_RETURNDEFAULT | PD_RETURNDC flags as shown inthesample code in this article. The PD_RETURNDEFAULT flag is used toainformation about the default printer without displaying the Print dialog box. PD_RETURNDC flag is used to direct PrintDlg to automatically createerrordevice or information context for the printer. Setup the Abort function. An application must use the SetAbortProcfunctionto set the application-defined Abort function that allows a print job tobecanceled during spooling. In the AbortProc function, the abort procedurecancheck the error code to see if an error occurred while printing. Thethiscode is zero if no error has occurred. Use StartDoc() to Start the Print Job. The StartDoc function starts aprintjob. A DOCINFO structure is initialized and passed to the StartDocfunction.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(noinitialization. Call StartPage(). The StartPage function prepares the printer driver to accept data. For example: StartPage( hDC ); Draw on the Device Context. Draw graphics or text on the printer device.Forexample, DrawStuff() illustrates how to draw text on the printer DC. Call EndPage(). The EndPage function informs the device that theapplicationhas finished writing to a page. This function is typically used to directthedevice 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(); } 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 : kbcode kbGDI kbNTOS350 kbNTOS351 kbPrinting kbWinCE kbWinOS95 kbDSupport Version : winnt:3.5,3.51 Platform : winnt Issue type : kbhowto Last Reviewed: July 6, 1999 © 2000 Microsoft Corporation. All rights reserved. Terms of Use. Heinz-Peter Nuettgens wrote:Hi, there is a problem occurring, when I try to send data via fopen(..; fwrite(.. to a stream leading to a printer port, for example "LPT1". It's working, if everything is alright, BUT when printer isn't readycallpaper or some other prob) or even not present, the following behaviour occurrs: fopen takes some time, but works, and the following fwritefwriteInever returns and causes the application to hang. I know that this way to output data is quite old fashioned. But how canavoid such a problem? I think there should be some timeout in theroutines, after which they abort and return to the calling program. Best wishes and condolences for what happened last tuesday I saw it on tv but still can't believe what I saw Heinz-Peter
Sep 18 2001
Heinz-Peter Nuettgens wrote:Hi Arjan, thank you for your suggestion. But my problem isn't the output to the printer. I am using the described way in other parts of the program, which do it right even when a printer error occurs. BUT I just want to do standard old fashioned stream output to the printer, just to print a few lines of text without positioning, scaling, handling DCs and more. If the printer is ready, the output works like it should. But if there is any error condition, the whole thread stops running. That shouldn't be, imho. I think the stdlib should be able to return an error condition and shouldn't wait for Godot to come. :-((Heinz-Peter, You've been stuck by a maze of paradigm clashes... Standard C (and it library) does not offer any portable primitive to ascertain the status of the printer. In the old days, programming in DOS mode, to be able to inform to the user such additional information we needed to resort to some platfform specific calls (something related to the BIOS), and IIRC, at least Microsoft had a _bios_printer call which allowed to these raw checks. This obviously will not work if you're using the Win32 API. If you think the call to fprintf are OK, I would suggest you browse the Win API around the terrain Jan pointed out and create a simple wrapper function to do printer_check or similar and give a better behaviour to your application. Perhaps, you could inspire yourself in the functionality ot _bios_printer call. HTH Cesar
Sep 22 2001