The Joel on Software Discussion Group (CLOSED)

A place to discuss Joel on Software. Now closed.

This community works best when people use their real names. Please register for a free account.

Other Groups:
Joel on Software
Business of Software
Design of Software (CLOSED)
.NET Questions (CLOSED)
TechInterview.org
CityDesk
FogBugz
Fog Creek Copilot


The Old Forum


Your hosts:
Albert D. Kallal
Li-Fan Chen
Stephen Jones

Why is stdprn not defined under Windows?

I am trying to print to the printer. I am using a VC++ 6.0 compiler on Win 2K, but I get an error saying that stdprn is not defined. Why is that? Is it because of Windows, I am guessing? Do I have to use only the GDI32 functions for printing under Windows? Can I not use the stdprn under Windows to print from memory to the window?
Sathyaish Chakravarthy Send private email
Tuesday, October 05, 2004
 
 
Ok, in traditional C programming for consoles and character mode devices, stdprn means "the standard printer" - right. I never really thought about this after making the transition to Windows programming, but things should work analogously to DOS.

I just did an experiment (Windows XP.) Opened a DOS window, and entered the following:

C:\>copy con prn:
ashdaskjhdlaksjdhaslkdh
as;das;ldkja;lskdj;laksdj
aslkdj;laskjd;laskdj
^Z
        1 file(s) copied.
C:\

And lo and behold, the printer light started to flash.

Now, what is complaining that stdprn is undefined? The compiler?

If so, my guess is that if you changed your code to do an fopen() of "PRN:" and fprintf()'d against the file handle, you'd see what you are wanting.

(I suppose that the currently selected default Windows printer is being used as the destination of PRN:.)
Bored Bystander Send private email
Wednesday, October 06, 2004
 
 
Thanks for undeleting this post, Joel. And thanks for replying, BB.

Yes, I didn't fopen the printer device because the book I am reading, "Let Us C" by an Indian author, Yashwant Kanetkar, says that these five streams are always open by default.

Then later, I tried doing that as well. I tried to open a network printer using the LPT1 or PRN I/O devices, but my program hung there, and I had to Ctr+C to kill the process.

What's all this about?
Sathyaish Chakravarthy Send private email
Wednesday, October 06, 2004
 
 
I left a sentence incomplete there:

Yes, I didn't fopen the printer device because the book I am reading, "Let Us C" by an Indian author, Yashwant Kanetkar, says that these five streams are always open by default.

stdin
stdout
stderr
stdprn
stdaux
Sathyaish Chakravarthy Send private email
Wednesday, October 06, 2004
 
 
Nice guess, BB.

From the VC++ 6.0 help....

Sending Output to a Printer
Last reviewed: July 22, 1997
Article ID: Q23976
5.10 6.00 6.00a 6.00ax 7.00 | 1.00 1.50 | 1.00 2.00 2.10 4.00
MS-DOS                      | WINDOWS  | WINDOWS NT
kbprg kbfasttip

The information in this article applies to:

Microsoft C for MS-DOS, versions 5.1, 6.0, 6.0a, and 6.0ax
Microsoft C/C++ for MS-DOS, version 7.0
Microsoft Visual C++ for Windows, versions 1.0 and 1.5
Microsoft Visual C++ 32-bit Edition, versions 1.0, 2.0, and 4.0


SUMMARY
This article presents three methods an application can use to send output to
a printer.



MORE INFORMATION


Method 1
The first method uses the fprintf() function with the preopened "stdprn"
stream. The following code example demonstrates this technique:


  #include <stdio.h>
  main()
  {
      fprintf(stdprn, "a line of text\n");
  }

This method works only in the MS-DOS operating system because the "stdprn"
stream is not defined by Microsoft Windows or Microsoft Windows NT.


Method 2
Another method uses the fopen() function to open the LPT1, LPT2, or PRN
device as a file and uses the fprintf() function to write data to the file
handle returned by fopen(). The following code example demonstrates this
technique:


  #include <stdio.h>
  main()
  {
      FILE *stream;

      stream = fopen("PRN", "w");
      fprintf(stream, "a line of text\n");
  }

This method works in Windows NT as well as the MS-DOS and Windows operating
systems.


Method 3
Finally, in MS-DOS, an application can use the int86() or int86x() functions
to call one of the following BIOS printer services provided by Interrupt
17h:


  service 0: send byte to the printer.
  service 1: initialize the printer.
  service 2: get printer status.

REFERENCES
For more information on the int86() and int86x() functions, refer to the
Microsoft C "Run-Time Library Reference" manual.
r1ch Send private email
Wednesday, October 06, 2004
 
 
Nice summary on PRN.

I believe these methods only work on locally connected (parallel port) printers.  If you want to use the Windows 'Print' interface, you'll need to go through more hoops.

The 'winspool.drv' DLL is where most of the helpful, low-level stuff to send to a networked printer through the Windows interface is put.

Calls I've used (under VB, unfortunately)

Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" _
    (ByVal PrinterName As String, PrinterHandleRet As Long, _
    ByVal pDefault As Long) As Long
   
Private Declare Function StartDocPrinter Lib "winspool.drv" Alias "StartDocPrinterA" _
    (ByVal hPrinter As Long, ByVal Level As Long, pDocInfo As DOC_INFO_1) As Long
   
Private Declare Function StartPagePrinter Lib "winspool.drv" _
    (ByVal hPrinter As Long) As Long
   
Private Declare Function WritePrinter Lib "winspool.drv" _
    (ByVal hPrinter As Long, pBuf As Any, ByVal cdBuf As Long, pcWritten As Long) As Long
   
Private Declare Function EndDocPrinter Lib "winspool.drv" _
    (ByVal hPrinter As Long) As Long
   
Private Declare Function EndPagePrinter Lib "winspool.drv" _
    (ByVal hPrinter As Long) As Long

Private Declare Function ClosePrinter Lib "winspool.drv" _
    (ByVal hPrinter As Long) As Long

Hopefully, that will give you a place to start.
AllanL5
Wednesday, October 06, 2004
 
 
Oy, Sathayish, just saw "print to a window".  I don't know that the Windows API supports this -- others may know more.
AllanL5
Wednesday, October 06, 2004
 
 
Thanks, people. I am still trying and do not have the answers yet.

AllanL5, those are the printing and spooling API under GDI32 that I was refering to. I've used them. But I was wondering if Standard C had any provision for device I/O to a printer. The book I was reading said, "well, yes!". I tried and it did not work. I guessed the same thing, the stdprn might not work under Windows because of the Hardware Abstraction Layer of Windows, which has given us another object to refer to a printer rather than a stream or I/O device -  a Device Context. But that was going to be boring, because I'd already used it.

R1ch, I tried the PRN thing also last night. Didn't work. My program hung and I had to kill the process (Ctrl+C). The printer I am refering to is a network printer, and is set up as my default printer.


Thanks very much for your input, friends. More input welcome.
Sathyaish Chakravarthy Send private email
Wednesday, October 06, 2004
 
 
The courts have been trying to define standard porn (std prn) for years.
muppet 3.11 platinum edition Send private email
Wednesday, October 06, 2004
 
 
Are you perhaps trying to open the printer in 'raw' mode?  So you can send any arbitrary data to the printer?  Under Windows?

This can be done.  The following VB opens a printer in 'binary' or 'raw' mode:

Sub BinOpen(PrnFile As Long, PrnName As String, DocName As String, _
            Status As Boolean)
  Dim RetVal As Long
  Dim JobID As Long
  Dim DocInfo As DOC_INFO_1
 
  Status = OpenPrinter(PrnName, PrnFile, 0)  ' .DeviceName is default
  If Status = 0 Then
    Exit Sub
  End If
  DocInfo.pDocName = DocName
  DocInfo.pOutputFile = vbNullString
  DocInfo.pDatatype = vbNullString
  JobID = StartDocPrinter(PrnFile, 1, DocInfo)
  Call StartPagePrinter(PrnFile)
End Sub

The following line prints to the PrnFile:
  LocString = OutString
  Status = WritePrinter(PrnFile, _
          ByVal LocString, Len(LocString), NumWritten)

The 'DocInfo' thing is:

Private Type DOC_INFO_1
    pDocName As String
    pOutputFile As String
    pDatatype As String
End Type

Put it all together, and now you can send arbitrary bytes to the printer.  Of course, now you have to do all the HPGL commands yourself -- but maybe that's what you wanted to do?
AllanL5
Wednesday, October 06, 2004
 
 
>> But I was wondering if Standard C had any provision for device I/O to a printer. The book I was reading said, "well, yes!".

Throw away that book and get one that actually knows the standard.

ISO Standard C (and K&R C before that) has only ever had 3 predefined files - stdin, stdout, and stderr. 

Microsoft added 2 more with their original C compiler - stdaux, and stdprn. stdaux went to the first serial port and stdprn went to the first printer port.

Looking at the MSDN Library, there really hasn't been any mention of stdaux or stdprn since Windows went to 32bit.
RocketJeff Send private email
Wednesday, October 06, 2004
 
 
Sathyaish,

forget all they said;)

If you don't have Petzold, buy it. Combine his Printing
example with MetaFile example and you have it all.

Create a MetaFaile, draw into it, put text, bitmaps,...
end then display it on screen or send it to printer or
save it to a file, move it to the clipboard and paste it
in any other app. You can even save metafiles in a
database. When your'e done with it all, modify the
part where you put text into a metafile and save a
copy of that text in another buffer, so you can even
collect it into separate xml or html document.

Forget stdprn.
VPC
Wednesday, October 06, 2004
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz