Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Odd printer setup problem

86 views
Skip to first unread message

CodeTroll

unread,
Jan 10, 2003, 3:50:16 PM1/10/03
to
I'm having a problem that bugs me for a longer time now
(and now it's getting urgent to fix it) with printer setup.

I'm using this function to set printer paper and orientation but it's
produces
Access violations when I use it on printers installed which print only to
file
(I don't really have that printer - for example I have installed HP LaserJet
1100
printer driver to print into file).

---
procedure TfrmMain.SetPrinterPaper(Orientation:integer);
var
hDMode: THandle;
Device, Driver, Port: array [0..PrinterCharArraySize] of Char;
DevMode: PDevMode;
begin
Printer.PrinterIndex := Printer.PrinterIndex;

Printer.GetPrinter(Device, Driver, Port, hDMode);
if hdMode<>0 then begin
DevMode := GlobalLock(hDMode);
if Assigned(DevMode) then begin
with DevMode^ do begin
dmFields := DM_PAPERSIZE or DM_ORIENTATION;

dmPaperSize:=DMPAPER_A4;

if Orientation = 0 then dmOrientation := DMORIENT_PORTRAIT else
dmOrientation := DMORIENT_LANDSCAPE;
end;

Printer.SetPrinter(Device, Driver, Port, hDMode);
GlobalUnlock(hDMode);
end;
end;

Printer.PrinterIndex := Printer.PrinterIndex;
end;
---

I managed to locate Access violations to this section of SetState procedure
in Printers.pas:
---
if Assigned(CreateHandleFunc) then begin
with TPrinterDevice(Printers.Objects[PrinterIndex]) do begin
DC := CreateHandleFunc(PChar(Driver), PChar(Device), PChar(Port),
DevMode); { !!! it crashes here :-( }
if DC = 0 then RaiseError(SInvalidPrinter);

if FCanvas <> nil then FCanvas.Handle := DC; { !!! or here :-( }
end;
end;
---

I tried to change this line
DC := CreateHandleFunc(PChar(Driver), PChar(Device), PChar(Port),
DevMode);
into this (replaced DevMode with nil) just to see what happens
DC := CreateHandleFunc(PChar(Driver), PChar(Device), PChar(Port), nil);
and then it doesn't crash - but of course - it doesn't do anything either
and that's not good.

Could someone please give me a clue what's going on?

Thanks in advance.

--
CodeTroll


Maynard Philbrook

unread,
Jan 11, 2003, 1:35:34 AM1/11/03
to
if its printing into a file then how do you expect it
to behave like a printer.
what you should do is simply treat it like a file.
OpenFile('LPT1:'.....
and use the "Escape" on it.
etc..

Bas Ruiter

unread,
Jan 11, 2003, 4:24:59 AM1/11/03
to

> if its printing into a file then how do you expect it
> to behave like a printer.

Because it's installed as a printer??

I would have done (tried) exactly the same thing as the
other poster. I would have assumed that the OS / printer
driver took care of the fact that it's actually not a
real printer but a file.

Bas Ruiter

--

[ l o r d s n o w @home.nl http://members.home.nl/ l o r d s n o w ]

Only when the population of 50 mysteriously dropped to 7 did the
remainder start to suspect Hungry.

Bas Ruiter

unread,
Jan 11, 2003, 4:26:23 AM1/11/03
to

> if its printing into a file then how do you expect it
> to behave like a printer.

As an addition: I find it decidedly odd that you
*can't* treat it as just a printer, if what you say
is correct.

CodeTroll

unread,
Jan 11, 2003, 7:39:32 AM1/11/03
to

"Maynard Philbrook" <jam...@mindspring.com> wrote in message
news:3E1FBB36...@mindspring.com...

> if its printing into a file then how do you expect it
> to behave like a printer.
> what you should do is simply treat it like a file.
> OpenFile('LPT1:'.....
> and use the "Escape" on it.
> etc..
>
>

OS should really take care of this for me.
If I'm wrong then something other than my logic is completely wrong here.

The interesting thing is when I do the same with MS Publisher Color Printer
(also virtual printer)
then everything works fine - well, most of the time (after 5 or 10 tries I
also get a Access violation).
This is why I belive that there is some sort of error in my code but that
HP's drivers
are more "gentle" and MS's driver is working with few exceptions.

I really don't know - but I'm sure that virtual printer, since it can be
installed,
should, at least as far as my application is concerned, be treaded like
absolutely normal,
existing, printer.

So ... does anybody know what the problem could be (in code)?

<snip>

--
CodeTroll


David Reeve

unread,
Jan 12, 2003, 7:55:02 AM1/12/03
to
CodeTroll wrote:
>
[snip]

>
> Could someone please give me a clue what's going on?
>

Take this as an uninformed opinion. Because you are still waiting an
answer, and because I had a few idle moments I delved into the
documentation.

I'd say the DevMode structure is where things are going wrong. According
to my reading of W32 help, this structure varies in size reflecting the
options ticked in PrintUsing dialog (whether or not you actually use
it). Over and above this the docs explicitly warn that the drivers
themselves also add private sections to this structure. Given this, your
method of making changes to it seems hazardous.

In W32 help for the DocumentProperties() function, there is given a
recommended method for changing printer settings. This involves making a
call to the OS to get the max size of the DevMode structure, allocating
space for it, mapping the current (possibly different) structure to the
allocated space, changing the required parameters in this temporary
copy, then mapping the copy back to the global DevMode.

Your code seems to write straight to the global DevMode instance which
seems unsafe in light of what W32 help says. But then, maybe I've got it
all wrong, in which case maybe someone will be kind enough to enlighten
me..... :-)

Dave

CodeTroll

unread,
Jan 12, 2003, 11:46:01 AM1/12/03
to
"David Reeve" <drscie...@powerup.com.au> wrote in message
news:3E2165A6...@powerup.com.au...

You got the things from help correctly, but [:-)] I've been reading it also
and I've been trying to get the recommended method running and didn't
succeed.
Then I've found some source snippets for which author claimed that they
solve
every problem with printer setup directly from code - but as you presume -
they didn't.
Then I tried this current approach and got best results than before.
I found similar (or almost the same) code as a "definitive solution" on the
net
but nowhere can I find that "thing" which would really fix all potential
problems.

So ... once again ... I'm clueless. But thanks for the nice try.

--
CodeTroll


Julian Eriksen

unread,
Jan 12, 2003, 7:11:15 PM1/12/03
to
This is the code I use. Works fine for 16,500 clients.

procedure tPrnBOut.SetPrinter(const InfoOnly : boolean);
var
StubDevMode : tDevMode; {throw away - values irrelevant}
ExtDeviceMode: tExtDeviceMode;
DriverName: array[0..255] of char;
begin
{load printer name, driver and port from windows into local fields}
if fPrinterIndex = -1 then GetDefaultPrinter
else GetSelectedPrinter;

{append the drv suffix to the driver}
StrCat(StrCopy(DriverName,fDriver), '.DRV');

{load the printer driver library module to fDeviceHandle}
fDeviceHandle := WinProcs.LoadLibrary(DriverName);

if fDeviceHandle <= 16 then fDeviceHandle := 0;

{if it was loaded correctly}
if fDeviceHandle <> 0 then begin

{get the entry point to the driver code}
@ExtDeviceMode :=
WinProcs.GetProcAddress(fDeviceHandle,'ExtDeviceMode');

{and if located}
if assigned(ExtDeviceMode) then begin

{find out the size of tDevMode for this printer by setting the
last parameter, Mode, to zero}
fDevModeSize :=
ExtDeviceMode(0,fDeviceHandle,StubDevMode,fDevice,fPort,StubDevMode,nil,0);

{and now allocate and initialise dynamic variables for the input
& output device buffers}
GetMem(pDevModeOutput,fDevModeSize);
GetMem(pDevModeInput,fDevModeSize);
fillchar(pDevModeOutput^,fDevModeSize,0);
fillchar(pDevModeInput^,fDevModeSize,0);

{read the default printer driver settings into the first
pDevModeInput variable}
if ExtDeviceMode(0,fDeviceHandle,pDevModeInput^,fDevice,fPort,pDevModeInput^,nil,DM_OUT_BUFFER)
> 0 then begin

if InfoOnly then begin
{just reading current settings - create an information
context rather
than a device context 11/10/2002}
fDC := CreateIC(fDriver,fDevice,fPort,pDevModeOutput);
end else begin
{we are setting the printer to print out data}

(*
{$IFDEF WINPAY}
{if we have not told the printer object to not initialise
the paper size
and orientation, then force these to the required values.
otherwise the
default values for the printer are used 14/11/2002}
if not fUseDefWinPaperOrient then begin
{$ENDIF}
*)
if fCanSetPaperOrient then begin
{firstly force paper to A4}
pDevModeInput^.dmFields := DM_PAPERSIZE;
pDevModeInput^.dmPaperSize := DMPAPER_A4;

{force the orientation to whatever required. prior to
3.17H we only set
if landscape, but by always forcing we catch clients that
have landscape
set as their default 11/08/2002}
pDevModeInput^.dmFields := (pDevModeInput^.dmFields or
DM_ORIENTATION);
if fIsLandscape then pDevModeInput^.dmOrientation :=
DMORIENT_LANDSCAPE
else pDevModeInput^.dmOrientation := DMORIENT_PORTRAIT;
end;
(*
{$IFDEF WINPAY}
end;
{$ENDIF}
*)

{now pass the possibly changed DevModeInput back to the
function - updated
settings are returned in pDevModeOutput}
if ExtDeviceMode(0,fDeviceHandle,pDevModeOutput^,fDevice,fPort,pDevModeInput^,nil,
DM_IN_BUFFER OR DM_OUT_BUFFER) > 0 then begin

{and we use the updated settings when creating the device
context}
fDC := CreateDC(fDriver,fDevice,fPort,pDevModeOutput);
if fDC = 0 then fError := true
{and then redirect the canvas handle so it writes to the
printer}
else Canvas.Handle := fDC; {using property to ensure
instantiated}
end;
end;
end;
end;
end;
end;

Regards
Julian Eriksen
www.acepay.co.nz

CodeTroll

unread,
Jan 13, 2003, 1:47:13 AM1/13/03
to
"Julian Eriksen" <ace...@hotmail.com> wrote in message
news:cff8119c.03011...@posting.google.com...

> This is the code I use. Works fine for 16,500 clients.
>

Is this code for Win 3.1?
I presume it is, since ExtDeviceMode doesn't exist (or I can not find it
defined anywhere) in Delphi 5.0.
There are also a lot of variables which don't exist any more - or are
defined in old Printers unit.
Unfortunately, in this case, this doesn't help me - although I'm thankful
for trying.

--
CodeTroll


CodeTroll

unread,
Jan 13, 2003, 2:57:17 AM1/13/03
to
"CodeTroll" <nom...@neverland.com> wrote in message
news:avnbmo$cjn3$1...@as201.hinet.hr...

> I'm having a problem that bugs me for a longer time now
> (and now it's getting urgent to fix it) with printer setup.
<snip>
<snip>

I just found a solution so if any one is interested ...

Change this:


dmFields := DM_PAPERSIZE or DM_ORIENTATION;

into this:
dmFields := dmFields or DM_PAPERSIZE or DM_ORIENTATION;

As is was said a lot of times, we often don't see the most obvious solution
:-)
It seems that some (or all) drivers fill dmFields with all bits on and in my
case
it originally was set to 92335939 and after original line it was 3.

Now it works. Finally.

Thanks again to all who replied on my original post.

> --
> CodeTroll
>


David Reeve

unread,
Jan 13, 2003, 4:34:10 AM1/13/03
to
CodeTroll wrote:
>
[snip]

>
> I just found a solution so if any one is interested ...
>
> Change this:
> dmFields := DM_PAPERSIZE or DM_ORIENTATION;
> into this:
> dmFields := dmFields or DM_PAPERSIZE or DM_ORIENTATION;
>
> As is was said a lot of times, we often don't see the most obvious solution
> :-)


Oh no....... now that hurts .. :-)

Dave

CodeTroll

unread,
Jan 13, 2003, 7:33:01 AM1/13/03
to
"David Reeve" <drscie...@powerup.com.au> wrote in message
news:3E228812...@powerup.com.au...
> CodeTroll wrote:
> >

<snip>

> Oh no....... now that hurts .. :-)
>
> Dave

Not any more :-D

But I have another problem (fortunatelly, not that urgent) which I'll post
in new thread.

--
CodeTroll


0 new messages