Solved

how to send escape codes to the printer?

Posted on 1998-05-17
5
1,955 Views
Last Modified: 2012-06-22
Hi,

a friend of mine has to work with a printer that uses the generic Windows printer driver. To change font attributes like 'bold' he has to send an escape sequence to the printer. However, the printer driver replaces the non-printable characters by '@', making such changes impossible. Now there are two questions:

1- is there a 'neutral' windows printer driver available wich does not filter out the escapes?
2- (if 1 does not work) he tried to use windows API calls like ExtEscape, but could not get them to work. How could he use the TPrinter object and mix this with ExtEscape?

I know he could write directly to the printer port, but ofcourse it would be preferable to use as much Delphi + windows as possible.

Thanks,

Wim
0
Comment
Question by:cadenza
  • 3
5 Comments
 
LVL 8

Accepted Solution

by:
ZifNab earned 200 total points
ID: 1346043
Hi cadenza, directly from borland technical information :

3196:Direct Commands to Printer - Passthrough/Escape

KEYWORDS: passthrough, escape, printers AREA: General

Although Delphi's TPrinter unit makes it easy to interface
to a given printer, there are times when you may need
to drop down to the printers level and send device specific
escape sequences. Under 16-bit versions of Windows, this
was as easy as opening the printer port, but under Windows NT,
directly accessing the hardware is is illegal. One solution
is to use the Windows "PASSTHROUGH" escape to send an escape
sequence directly to the printer. In order to use the
"PASSTHROUGH" escape, it must be supported by the printer
driver. Be forwarned that not all printer drivers will support
this feature.

It's worth noting that the "PASSTHROUGH" escape is documented
as obsolete for thirty-two bit applications. It should be a
number of years before this escape goes by the way, since
it is used in many commercial applications.

The example code presented is not targeted to any specific
printer model. You will need to know the correct escape
sequences to send to the printer you are interfacing to.
Note that you must still call the BeginDoc and EndDoc methods
of TPrinter. During the BeginDoc call, the printer driver
initializes the printer as necessary, and during the EndDoc
call, the printer driver will uninitialize the printer and
eject the page. When you do make your escape call, the printer
may be set for the current windows mapping mode if the printer
supports scaling internaly. Technically, you should not do
anything that would cause the printer memory to be reset,
or eject a page with an escape sequence. In other words,
try to leave the printer in the same state it was in when
you made your escape. This is more important on intellegent
printers (Postscript printers), and not important at all on
a standard TTY line printer, where you can do just about
anything you like, including ejecting pages.

Code Example:

You will need to declare a structure to hold the buffer you are
sending. The structure of the buffer is defined as a word containing
the length of the buffer, followed by the buffer containing the data.

Before making the escape call to pass the data, we will use
the escape "QUERYESCSUPPORT" to determine if the "PASSTHROUGH"
escape is supported by the print driver.

Finally, be aware that your data will be inserted directly into
the printers data stream. On some printer models (Postscript),
you may need to add a space to the start and end of your data
to separate your data from the printer drivers data.

(Postscript is a Registered Trademark of Adobe Systems Incorporated)


unit Esc1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{ add the printers unit }
uses
   Printers;

{$R *.DFM}

{ declare the "PASSTHROUGH" structure }
type TPrnBuffRec = record
  BuffLength : word;
  Buffer : array [0..255] of char;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  Buff : TPrnBuffRec;
  TestInt : integer;
  s : string;
begin

{ Test to see if the "PASSTHROUGH" escape is supported }
  TestInt := PASSTHROUGH;
  if Escape(Printer.Handle,
            QUERYESCSUPPORT,
            sizeof(TestInt),
            @TestInt,
            nil) > 0 then begin

  { Start the printout }
    Printer.BeginDoc;

  { Make a string to passthrough }
    s := ' A Test String ';

  { Copy the string to the buffer }
    StrPCopy(Buff.Buffer, s);

  { Set the buffer length }
    Buff.BuffLength := StrLen(Buff.Buffer);

  { Make the escape}
    Escape(Printer.Canvas.Handle,
           PASSTHROUGH,
           0,
           @Buff,
           nil);

  { End the printout }
    Printer.EndDoc;
  end;
end;

end.

        TI

Regards, ZiF.
0
 

Author Comment

by:cadenza
ID: 1346044
Hi ZifNab,

Jules Verne let one of his characters say:

"use what you've got, so that you won't need what you've not"

and this seems to hold for us too! I passed your answer to my friend and he is testing it at the moment. I think that if it does not work for him (because maybe the generic windows printer driver does not have this capability ?) he is out of luck. I'll be back soon,

Wim
0
 

Expert Comment

by:smico
ID: 1346045
If you still have problems sending code directly to the printer, simle solution I've been using lattely is to write text to a temporary text file and copy file to the LPT at the end of the printing job.
It works perfectly with Delphi 2.0 and NT 4.0.
0
 

Author Comment

by:cadenza
ID: 1346046
ZifNab:

The generic windows printer driver does not have the PASSTHROUGH capability, so I am afraid that is not the way to go. Strange, though, since this driver is the one most likely to need passthrough!!

Smico:

Thanks. I'll pass your answer to my friend and will be back soon.

Wim
0
 

Author Comment

by:cadenza
ID: 1346047
ZifNab: you answered the question, and although it did not give the definitive solution, I'll give you the points.

Smico: thanks for your suggestion. It amounts more or less to writing to the port directly, a thing we wanted to avoid, and was implied in the question already. Unfortunately I don't see a way to give you points too. Sorry.

Wim
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now