 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
AlanGLLoyd Guest
|
Posted: Mon Dec 22, 2003 12:42 pm Post subject: Delphi's DocumentProperties() Declaration |
|
|
DocumentProperties() is declared in MSDN as ...
LONG DocumentProperties(
HWND hWnd, // handle to parent window
HANDLE hPrinter, // handle to printer object
LPTSTR pDeviceName, // device name
PDEVMODE pDevModeOutput, // modified device mode
PDEVMODE pDevModeInput, // original device mode
DWORD fMode // mode options
);
... but in my Delphi 3 WinSpool.pas it is declared as ...
function DocumentProperties(hWnd: HWND; hPrinter: THandle; pDeviceName: PChar;
const pDevModeOutput: TDeviceMode; var pDevModeInput: TDeviceMode;
fMode: DWORD): Longint; stdcall;
... and I have coded ...
{initial memory allocation}
PtrDMIn := AllocMem(DMMemSize);
DMIn := PtrDMIn^;
PtrDMOut := AllocMem(DMMemSize);
DMOut := PtrDMOut^;
if not OpenPrinter('HP Laserjet 5P/5MP (HP)', hndPrinter, nil) then
ShowMessage('Opened Printer failed');
Exit;
end;
{get total memory size}
DMMemSize := DocumentProperties(Self.Handle, hndPrinter, 'HP Laserjet 5P/5MP
(HP)',
DMIn, DMOut, 0);
{reallocate memory to total size}
PtrDMIn := ReAllocMem(ptrDMIn, DMMemSize);
DMIn := PtrDMIn^;
PtrDMOut := ReAllocMem(ptrDMOut, DMMemSize);
DMOut := PtrDMOut^;
{get printer devmode}
DocumentProperties(Self.Handle, hndPrinter, 'HP Laserjet 5P/5MP (HP)',
DMIn, DMOut, DM_OUT_BUFFER);
But this causes an AV unless I redeclare DocumentProperties() as ...
function DocumentProperties(hWnd: HWND; hPrinter: THandle; pDeviceName:
PChar;
const pDevModeOutput: PDeviceMode; var pDevModeInput: TDeviceMode;
fMode: DWORD): Longint; stdcall;
.... and call appropriately.
This seems to be a bug in Delphi 3. Is it otherwise known, or am I doing
something incorrectly. The AV definitely occurs at the second
DocumentProperties() call.
Is my correction of the Delphi declaration correct or should I really be
declaring that parameter as "var pDevModeOutput : TDeviceMode".
In any case, declaring the parameters as "var ...TDeviceMode" seems perverse
when one considers that a variable amount of memory (usually much more than
SizeOf(TDeviceMode)) must be provided. Declaring as PDeviceMode would make for
much easier code.
Alan Lloyd
[email]alanglloyd (AT) aol (DOT) com[/email]
|
|
| Back to top |
|
 |
Rob Kennedy Guest
|
Posted: Mon Dec 22, 2003 4:29 pm Post subject: Re: Delphi's DocumentProperties() Declaration |
|
|
AlanGLLoyd wrote:
| Quote: | {initial memory allocation}
PtrDMIn := AllocMem(DMMemSize);
DMIn := PtrDMIn^;
PtrDMOut := AllocMem(DMMemSize);
DMOut := PtrDMOut^;
|
The contents of DMIn and DMOut are all-bits-zero, but they hold
absolutely no relation to PtrDMIn and PtrDMOut.
Don't forget to protect those memory allocations with try-finally blocks
so the memory gets freed when OpenPrinter fails below.
| Quote: | if not OpenPrinter('HP Laserjet 5P/5MP (HP)', hndPrinter, nil) then
ShowMessage('Opened Printer failed');
Exit;
end;
{get total memory size}
DMMemSize := DocumentProperties(Self.Handle, hndPrinter, 'HP Laserjet 5P/5MP
(HP)',
DMIn, DMOut, 0);
{reallocate memory to total size}
PtrDMIn := ReAllocMem(ptrDMIn, DMMemSize);
DMIn := PtrDMIn^;
PtrDMOut := ReAllocMem(ptrDMOut, DMMemSize);
DMOut := PtrDMOut^;
|
Once again, DMIn and DMOut are zeroed, but have no connection to the
pointers. I see no need to have allocated or initialized the variables
the first time since they aren't used to call OpenPrinter or
DocumentProperties.
| Quote: | {get printer devmode}
DocumentProperties(Self.Handle, hndPrinter, 'HP Laserjet 5P/5MP (HP)',
DMIn, DMOut, DM_OUT_BUFFER);
|
Since you already have pointers to TDeviceMode records, pass those
instead; get rid of DMIn and DMOut altogether.
DocumentProperties(..., PtrDMIn^, PtrDMOut^, dm_Out_Buffer);
According to MSDN, you're passing the In and Out variables in the
reverse order. Also, one of those parameters is ignored unless you use
the dm_In_Buffer mode.
I agree that Borland's declaration is lousy. The variable size of the
buffer makes const and var parameters very clumsy to use. Here's how it
should have been declared:
function DocumentProperties(hWnd: HWND; hPrinter: THandle; pDeviceName:
PChar; pDevModeOutput, pDevModeInput: PDeviceMode; fMode: DWORD):
Longint; stdcall; external winspl name 'DocumentPropertiesA';
You can add that to your own unit and it should hide the declaration
from WinSpool.
--
Rob
|
|
| Back to top |
|
 |
AlanGLLoyd Guest
|
Posted: Mon Dec 22, 2003 6:06 pm Post subject: Re: Delphi's DocumentProperties() Declaration |
|
|
In article <vue6vosd3fg961 (AT) corp (DOT) supernews.com>, Rob Kennedy <.> writes:
| Quote: | Since you already have pointers to TDeviceMode records, pass those
instead; get rid of DMIn and DMOut altogether.
DocumentProperties(..., PtrDMIn^, PtrDMOut^, dm_Out_Buffer);
|
For some reason I thought that a var Parameter must be passed as a variable,
not as a "PointerToStructure-Contents". That's what lead me down the DMIn and
DMOut path.
<snip>
| Quote: | I agree that Borland's declaration is lousy. The variable size of the
buffer makes const and var parameters very clumsy to use. Here's how it
should have been declared:
Thats what I did and it all worked OK. |
Thanks for the comments.
I really started out getting the paper bin names and values. Getting and
changing printer attributes is incredibly messy with complex APIs. Does it get
any better after D3 ?
OTOH is it possible to use a TDevMode with a non-standard
unknown-at-design-time size (ie other than declaring the larger buffer and then
using "PointerToDevMode-Contents")
Having sussed out the bin names and values GetPrinter and SetPrinter is a not
too bad way of doing it.
Alan Lloyd
[email]alanglloyd (AT) aol (DOT) com[/email]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|