我有下面的函数,它收集我正在打印的PDF的文档属性。出于某种原因,在Delphi7(运行XP)中,这项功能非常好。。。然而,当我尝试使用Windows 7使用Delphi XE重新编译时,函数似乎总是失败退出。。。dwRet = IDOK
!
我注意到我在Delphi7中的dwNeeded
对象是7332
,在XE中是4294967295
!!
知道我如何快速解决这个问题吗?
Function TPrintPDF.GetPrinterDevMode ( pDevice: PChar ): PDevMode;
Var
pDevModeVar : PDevMode;
pDevModeVar2 : PDevMode;
dwNeeded : DWord;
dwRet : DWord;
Begin
{ Start by opening the printer }
If (Not OpenPrinter (pDevice, PrinterHandle, Nil))
Then Result := Nil;
{ Step 1: Allocate a buffer of the correct size }
dwNeeded := DocumentProperties (0,
PrinterHandle, { Handle to our printer }
pDevice, { Name of the printer }
pDevModevar^, { Asking for size, so these are not used }
pDevModeVar^,
0); { Zero returns buffer size }
GetMem (pDevModeVar, dwNeeded);
{ Step 2: Get the default DevMode for the printer }
dwRet := DocumentProperties (0,
PrinterHandle,
pDevice,
pDevModeVar^, { The address of the buffer to fill }
pDevModeVar2^, { Not using the input buffer }
DM_OUT_BUFFER); { Have the output buffer filled }
{ If failure, cleanup and return failure }
If (dwRet <> IDOK) Then Begin
FreeMem (pDevModeVar);
ClosePrinter (PrinterHandle);
Result := Nil;
End;
{ Finished with the printer }
ClosePrinter (PrinterHandle);
{ Return the DevMode structure }
Result := pDevModeVar;
End; { GetPrinterDevMode Function }
以下是我在您的代码中看到的问题:
DocumentProperties
的返回值是一个有符号的32位整数。它被声明为LONG
。负值意味着发生了错误,这就是发生在你身上的情况。只是你看不到负值,因为你把这个值塞进了一个无符号整数。遗憾的是XE未能声明LONG
。因此,请将代码更改为使用Integer
- 当
DocumentProperties
返回时,您不检查错误。如果发生错误,则返回负值。一定要检查一下 - 您正在将第4个和第5个参数中的随机垃圾传递给
DocumentProperties
。我怀疑您在第一次调用DocumentProperties
时可以为这两个参数传递nil
。您当然可以在两次调用函数时都为第5个参数传递nil
,因为您从未设置DM_IN_BUFFER
- 当出现错误时,可以将
Result
设置为nil
,但可以继续执行函数的其余部分。不要那样做。调用exit以中断函数。分配给Result
不会像return
在类C语言中那样终止执行 - 使用
try/finally
块确保调用CloseHandle
。这允许您只写一次CloseHandle
以下是David建议的解决方案。。。谢谢大卫!
{ ---------------------------------------------------------------------------- }
Function TPrintPDF.GetPrinterDevMode ( pDevice: PChar ): PDevMode;
Var
pDevModeVar : PDevMode;
pDevModeVar2 : PDevMode;
dwNeeded : Long64;
dwRet : Long64;
Begin
Result := Nil;
{ Start by opening the printer }
If (OpenPrinter (pDevice, PrinterHandle, Nil)) Then Begin
Try
{ Step 1: Allocate a buffer of the correct size }
dwNeeded := DocumentProperties (0,
PrinterHandle, { Handle to our printer }
pDevice, { Name of the printer }
Nil, { Asking for size, so these are not used }
Nil,
0); { Zero returns buffer size }
{ Exit if this fails }
If (dwNeeded < 0)
Then Exit;
GetMem (pDevModeVar, dwNeeded);
{ Step 2: Get the default DevMode for the printer }
dwRet := DocumentProperties (0,
PrinterHandle,
pDevice,
pDevModeVar^, { The address of the buffer to fill }
pDevModeVar2^, { Not using the input buffer }
DM_OUT_BUFFER); { Have the output buffer filled }
{ If failure, cleanup and return failure }
If (dwRet <> IDOK) Then Begin
FreeMem (pDevModeVar);
ClosePrinter (PrinterHandle);
Result := Nil;
End;
{ Finished with the printer }
Finally
ClosePrinter (PrinterHandle);
End; { Try }
{ Return the DevMode structure }
Result := pDevModeVar;
End; { If we could open the printer }
End; { GetPrinterDevMode Function }