Using standard printing from windows
There are many applications where I don't really want to use the usual windows page print. Instead I want output to go directly to the printer using standard print i/o. It's actually a topic that is hard to find in any of the books on Windows, at least I've never found anything on it. But to my surprise I recently learned that standard (DOS/UNIX) printing is alive and well underneath windows. All we need to do is open a printer port and print to it.
If the printer is directly attached to the computer it's trivial. The method for obtaining a printer port when the printer is on the network isn't hard either.
The example below shows how I use the Windows NET USE command to re-direct LPT1 to a shared printer on an NT Server. The same technique applies for Novell networks with a slightly different syntax.
Try this out by creating a new MFC Form-based project. Put a button on the form and attach this code to it. You can actually print with only 3 lines of code:
FILE *fp = fopen("LPT1", "w");
fprintf(fp,"What's up, Doc?\n");
fclose(fp);
Instant print gratification!!
While the program is open it hogs the printer port. In my shop that isn't a problem but be aware of the effect on your windows spooled output.
*********************************************************
THE CODE
*********************************************************
// the headers for the conventional i/o routines
#include
#include
#include
using namespace std; // makes string and ofstream
// work without std:: qualifier
void CLineprtView::OnButton1()
{
// I could have used a CString instead of the buff[]
// but I wanted to show how this is used with lightweight
// ATL code and STD library
char buff[MAX_BUFF_SIZE];
// My printer is located on another server so I must re-direct the
// printer port. If the printer is directly attached this extra step
// is not needed.
// on my network the printer is published as \\GREEN\hp5annex
// All those back-slashes escape the backslash in the path name
if (PRINTER_IS_REMOTE)
{
system("NET USE LPT1 /d"); // free up the port
system("net use lpt1 \\\\green\\hp5annex");
}
// old fashioned file handle with
// old fashioned open of the printer port
FILE *ptr = fopen("LPT1","w");
// laser printer setup string
sprintf(buff,"\033E\033(s0p4102t1b16.66H\033&l1O");
fprintf(ptr,buff);
// old fashioned print
fprintf(ptr,"Who of late doth make a thimble.\n");
fprintf(ptr,"Is a lower bunk a status symbol??\n");
// old fashioned close
fclose(ptr);
// now the same thing with stream io
ofstream optr("LPT1", ios::out);
string str_text = "Hey Doc, Ain't this a print test from windows\n";
str_text += "with more lines to follow?\n";
optr << str_text << endl;
optr << "Quiet, wabbit. I'm conversing with my muse!!\n";
optr << "That's all folks." << "\f" << flush; // add a formfeed
// the printer connection is still open so close it
optr.close();
// drop the network link
if (PRINTER_IS_REMOTE)
{
system("net use lpt1 /d");
}
}
In practice I get printer path information from the registry on each machine, so the real live code is a little busier than this example, but not much.

Comments
PRINTER_IS_REMOTE
Posted by Legacy on 02/26/2004 12:00amOriginally posted by: sushma
what is this defined as?
ReplyHelp with commtimeouts
Posted by Legacy on 10/01/2003 12:00amOriginally posted by: Benny
ReplyProblem with GetJob Function.
Posted by Legacy on 07/04/2003 12:00amOriginally posted by: lray
How can use the GetJob function to retrieve the document Name from the printer.
your help is highly appreciated.
ReplyWant to print a Image on CWnd
Posted by Legacy on 03/04/2003 12:00amOriginally posted by: Mallikarjun
Hay I want to print a Picture which is one the CWnd and
Replyalso print preview
how to print a picture
Posted by Legacy on 12/28/2002 12:00amOriginally posted by: linxs
In this example, it print text. If i want to print a picture, how to do it ?
ReplyPlease use SetCommTimeouts first, and u can ....
Posted by Legacy on 09/16/2002 12:00amOriginally posted by: kevin chen
Please use SetCommTimeouts first,
After you execute the ::CreateFile(...),
you can use SetCommTimeouts to set the TimeOut of read/write. by default, it will blocks when the device is Off-line or has some other errors.
So, when you use WriteFile/ReadFile, you will "timeout" if the error occurs, and next call the GetLastError(), you will get the detail error info.
for example:
------------------------------------------------
HANDLE hPrinter = ::CreateFile( "LPT1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL );
if ( hPrint == INVALID_HANDLE_VALUE {
nErrID = ERR_OPENPORT;
return FALSE;
}
//set timeout to 3 seconds ... 设置超时, 3秒
COMMTIMEOUTS timeout;
memset(&timeout, 0, sizeof(COMMTIMEOUTS));
timeout.ReadTotalTimeoutMultiplier = 3000;
timeout.ReadTotalTimeoutConstant = 3000;
timeout.WriteTotalTimeoutConstant = 3000;
timeout.WriteTotalTimeoutMultiplier = 3000;
SetCommTimeouts(hPrinter, &timeout);
if ( !::WriteFile( hPrinter, lpBuf, dwLen, &dwBytes, NULL ) ) {
strcpy(szErrText, "From Printer: ");
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
szErrText + strlen(szErrText),
240,
NULL);
AfxMessageBox(szErrText);
}
::CloseHandle(hPrinter);
return TRUE;
-----------------------------------------
good luck!
ReplyWant to know if a printrer is attached
Posted by Legacy on 09/13/2002 12:00amOriginally posted by: Steve Lee
I have a program that scans a system and collects data on any given system. This program will also collect all the configured printers even if they are not attached to the LPT port.
All of our Windows systems are configured with every printer driver that are oranization has. Meaning, they could not have the printer installed to LPT1 but the drivers are present.
What I need to know is there a utlity that will allow me to report the printer is attached to LPT1 and then pipe this output to a file.
Steve Lee
ReplyWant to know if a printrer is attached
Posted by Legacy on 09/13/2002 12:00amOriginally posted by: Steve Lee
I have a program that scans a system and collects data on any given system. This program will also collect all the configured printers even if they are not attached to the LPT port.
All of our Windows systems are configured with every printer driver that are oranization has. Meaning, they could not have the printer installed to LPT1 but the drivers are present.
What I need to know is there a utlity that will allow me to report the printer is attached to LPT1 and then pipe this output to a file.
Steve Lee
ReplyHow I can send to the printer a value, but I used Developer Forms 6i.
Posted by Legacy on 08/27/2002 12:00amOriginally posted by: Gabriela Silvestri
ReplyPrint to file
Posted by Legacy on 07/25/2002 12:00amOriginally posted by: geronimo
Hallo,
ReplyCan you advise me, how can I send the file directly into the "print to file"?
Thank's a lot.
Geronimo
Loading, Please Wait ...