How I can print

How I can use printer under Windows ?

NOTE : Before printing you may look at converting DOS characters to Windows.

Printing is one of master necessities of business programming; reports, lists, payrolls, bills, etc.

In oldy – goldy DOS days everything was easy, because everything was simple.

While Windows bring up tons of innovations and possibilities to our life, naturally bring also tons of complexities so difficulties.

Printer usage is one of most important. In DOS, like every system resource, printers too was completely under our control. We could anything possible to OUR printers: print anything in any format ( bold, compressed, emphasized, etc) on anywhere of the paper, page eject, move print head forward ( even backward) etc.

In Windows there isn’t a single machine, single user, single printer. Main philosophy of Windows is “Network everywhere“. Whatever your system configuration is, Window treat it as “Network”. Although we cannot disclaim benefits of this approach, printer issue become problematic to us.

Now, Windows says : “there isn’t YOUR printer, all printers ( even exist only one ) are network printers. If you have something to print, you can’t send it directly to printer; ask me and wait for I’ll do something for you.”

Since we can’t rollback the time (and this isn’t necessary); only way for us is : playing game depending its rules. On printing, we should learn and utilize printing ways of Windows.

Here I would talk about possibilities, ways and opportunities of printing.

Obsolete Ways 

Send to file 

Print File

GUI ways

HMG Print ( Mini Print ) for beginners in 10 easy steps

Print a plain text file by HMG Print – 1

Obsolete Print Ways

Printing – Obsolete Ways

Clipper Language is a masterpiece of simplicity: almost all program output may realize with a single command :  ‘?’; yes, question mark, aka PRINT command.

Unless otherwise stated, this command write everything ( included an empty line ) to the CONSOLE, that is screen / monitor. For writing to printer all we need was simply issue SET PRINTER ON command before ‘?’.

So simplest Clipper program to attempt print may be like this :

SET PRINTER ON

? “This is a line”

And now, this program doesn’t work as expected :

Error TERM/2014 Create error: LPT1 (DOS Error 2)

What are happening ?

The happening is clear : our program attempt to use LPT1 and our system doesn’t have LPT1, our printer is connected via USB port, same as all modern systems.

If you are thinking “I have LPT1” or “I can add a LPT1 card or an adapter to my system”; I have a bad news to you: problem isn’t only LPT1 / USB 😦

Whereas this layout :

 SET CONSOLE OFF 
 SET PRINTER ON 

 GO TOP
 DO WHILE .NOT. EOF()
 ? <FIELD1>, <FIELD2>, <FIELD31>, ...
 SKIP
 ENDDO
 SET PRINTER OFF 
 SET CONSOLE ON

was a standard statement block in almost all Clipper program using Printer.

Second printing way was using @ …, … command instead of ‘?’ :

 SET DEVICE TO PRINTER
 @ 2, 0 SAY "This is a line" 
 SET DEVICE TO SCREEN

Full layout of this method may be like this :

 USE Salesman INDEX Salesman NEW
 SET DEVICE TO PRINTER
 DO WHILE !EOF() // Print all records
 @ 2, 5 SAY RTRIM(FirstName) + ", " + LastName
 @ 3, 5 SAY Street
 @ 4, 5 SAY RTRIM(City) + ", " + State + " " + ;
 PostalCode
 @ 6, 0 SAY SPACE(1) // Move to label bottom
 SETPRC(0, 0) // Suppress page eject
 SKIP // Next record
 ENDDO
 SET DEVICE TO SCREEN
 CLOSE Salesman

The result not changed :

Error TERM/2014 Create error: LPT1 (DOS Error 2)

We have another way to printing :

First send lines to a intermadiate file instead of printer
And than send that file to printer

If you don’t want to change your printing habits, there is a easy way to you: use a external program such as DosPrint or another else. Run this program / wizard before yours, this program will send all your old style print-outs to the modern printer by ways that Windows required.

If this way satisfactory to you, don’t read remaining of this “Printing” issue and as a programmer, continue using third party products for supporting your own program.

Print File

 Send a file to printer

Once builded a file contains lines to print, seems it’s easy sending that file to printer :

COPY FILE command send entire file to another file or a device :

COPY FILE <xcSourceFile> TO <xcTargetFile>|<xcDevice>

Arguments:

<xcSourceFile> is the name of the source file to COPY including the extension.

<xcTargetFile> is the name of the target file including the extension.

<xcDevice> is the name of the device where all subsequent output will be sent. You can specify a device name as a literal character string or a character expression enclosed in parentheses. Additionally, a device can be either local or network. If you COPY TO a non-existing device you create a file with the name of the device. When specifying device names, do not use a trailing colon.

Example :

COPY FILE Prnfile.txt TO LPT1

Remember that above last command doesn’t work under Windows. Almost all Clipper commands and functions are usable in Harbour. You can apply above tests with Harbour too. And the result not changed again. Because problem isn’t compiler, but hardware and OS difference. Harbour offers additional (extended) easy ways to manage printer(s) :

 WIN_PRINTEREXISTS()     (old name: PRINTEREXISTS())
 WIN_PRINTERSTATUS()     (old name: XISPRINTER())
 WIN_PRINTERPORTTONAME() (old name: PRINTERPORTTONAME())
 WIN_PRINTERLIST()       (old name: GETPRINTERS())
 WIN_PRINTERGETDEFAULT() (old name: GETDEFAULTPRINTER())
 WIN_PRINTERSETDEFAULT() (old name: SETDEFAULTPRINTER())
 WIN_PRINTFILERAW()      (old name: PRINTFILERAW())
For sending a file to printer we need only two of above function :
 WIN_PRINTERGETDEFAULT() 
 WIN_PRINTFILERAW()

If we have alredy above Prnfile.txt, sending it to printer seems easy :

 cDefaultPrinter := WIN_PRINTERGETDEFAULT() 
 WIN_PRINTFILERAW( cDefaultPrinter, Prnfile.txt )

Is that all ?

WIN_PRINTFILERAW() returns 1 if sending to printer was successful. If you test this, probably you will get 1.

May be easy like this ?

Unfortunatelly answer is “sometime” …

Although WIN_PRINTFILERAW() said “sending is successful” you may get nothing from printer.

What is meaning of “sometime” ? May be “sometime” in physic ?

In physic no, but in Windows yes !

What ?

Because some printers or some versions of Windows due to something obscure …

… doesn’t support “raw” printing 😦

And a more interesting thing :

You may send your “raw” file to printer via NotePad program of Windows :

cOutFName := "Test_Raw.txt"
cCmd := "NOTEPAD /P " + cOutFName

RUN ( cCmd)

( The “/P” parameter / switch means direct printing;  without NotePad open)

When sent this file by WIN_PRINTFILERAW() to printer noting happen, but by above (notepad) way sending is successful 😦

It seems that NOTEPAD build a “printable” document from our “raw” file and send this document to printer instead of our file.

However, NOTEPAD always add print file name to top, and page number to bottom of document; and treats our “printer control codes” as data, so printers never use them in “right”  way.

Other ways :

EXECUTE FILE "NOTEPAD.EXE" PARAMETERS cFileName

(  EXECUTE FILE   is a HMG command.

SHELLEXECUTE( 0, "print", cFileName )

Send to file

Write data to a file

Sending lines to a file is quite easy :

In addition of SET PRINTER on | OFF | <xlToggle> command, SET PRINTER, (like many other SET commands,) has a second form distinguished by TO keyword:

SET PRINTER TO [<xcDevice> | <xcFile> [ADDITIVE]]

The on|OFF form of SET PRINTER controls whether the output of console commands is echoed to the printer.

TO <xcDevice> identifies the name of the device where all subsequent printed output will be sent.

TO <xcFile> identifies the name of the output file. ( If a file extension is not specified, (.prn) is assumed.)

By using that last method we can send our lines to a file, instead of sending directly to printer:

 SET PRINTER TO Prnfile.txt
 SET DEVICE TO PRINTER
 SET PRINTER ON
 //
 @ 0, 0 SAY "This goes to Prnfile.txt"
 ? "So will this!"
 //
 SET DEVICE TO SCREEN
 SET PRINTER OFF
 SET PRINTER TO // Close the print file

Note that, though our target is not printer, we have use a SETting printer ON.

We have another method for sending someting to a file may be SET ALTERNATE command:

 SET ALTERNATE TO [<xcFile> [ADDITIVE]]
 SET ALTERNATE on | OFF | <xlToggle>

SET ALTERNATE is a console command that lets you write the output of console commands to a text file. Commands such as LIST, REPORT FORM, LABEL FORM, and ? that display to the screen without reference to row and column position are console commands. Most of these commands have a TO FILE clause that performs the same function as SET ALTERNATE. Full-screen commands such as @…SAY cannot be echoed to a disk file using SET ALTERNATE. Instead you can use SET PRINTER TO <xcFile> with SET DEVICE TO PRINTER to accomplish this.

SET ALTERNATE has two basic forms. The TO <xcFile> form creates a DOS text file with a default extension of (.txt) and overwrites any other file with the same name. Alternate files are not related to work areas with only one file open at a time. To close an alternate file, use CLOSE ALTERNATE, CLOSE ALL, or SET ALTERNATE TO with no argument.

The on|OFF form controls the writing of console output to the current alternate file. SET ALTERNATE ON begins the echoing of output to the alternate file. SET ALTERNATE OFF suppresses output to the alternate file but does not close it.

Examples :

This example creates an alternate file and writes the results of the ? command to the file for each record in the Customer database file:

 SET ALTERNATE TO Listfile
 SET ALTERNATE ON
 USE Customer NEW
 DO WHILE !EOF()
 ? Customer->Lastname, Customer->City
 SKIP
 ENDDO
 SET ALTERNATE OFF
 CLOSE ALTERNATE
 CLOSE Customer

A single difficulty may be making choose the best between possible methods

You can download a working example prg with a sample .dbf from here :