0

我在下面有以下功能,用于收集我正在打印的 PDF 的文档属性。出于某种原因,在 Delphi 7(运行 XP)中,这很好用......但是,当我尝试使用 Windows 7 使用 Delphi XE 重新编译时,该功能似乎总是退出失败...... dwRet = IDOK

我注意到我dwNeeded在 Delphi 7 中的对象是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 }
4

2 回答 2

2

以下是我可以在您的代码中看到的问题:

  1. 的返回值DocumentProperties是一个有符号的 32 位整数。它被声明为LONG. 负值表示发生了错误,这就是发生在您身上的事情。只有您看不到负值,因为您已将该值填充到无符号整数中。不幸的是,XE 未能声明LONG. 因此,请更改您的代码以使用Integer
  2. 返回时您不会检查错误DocumentProperties。如果发生错误,则返回负值。确保你检查。
  3. 您将第 4 个和第 5 个参数中的随机垃圾传递给DocumentProperties. 我怀疑您可以nil在第一次调用时同时传递这两个参数DocumentProperties。您当然可以nil在两次调用函数时传递第 5 个参数,因为您从未设置过DM_IN_BUFFER
  4. 当发生错误时,您设置Resultnil,但您继续执行函数的其余部分。不要那样做。调用 exit 退出函数。分配给不会像在类 C 语言中那样Result终止执行。return
  5. 使用try/finally块来确保您调用CloseHandle. 这允许你CloseHandle只写一次。
于 2012-07-31T19:28:15.037 回答
0

这是大卫建议的解决方案……谢谢大卫!

{ ---------------------------------------------------------------------------- }

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 }
于 2012-07-31T19:16:20.390 回答