2012-07-31 27 views
0

我在下面收集了我打印的PDF文档属性的以下功能。 由于某些原因,在Delphi 7(运行XP)中,这很好...但是,当我尝试使用Windows 7重新编译Delphi XE时,该函数总是似乎退出失败... dwRet = IDOKPDevMode和DocumentProperties。在Delphi 7 + XE之间迁移时出错

我注意到我在Delphi 7中的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 } 
+0

'dwNeeded'应声明为'LONG'。它已签署。负值意味着功能失败。这正是你发生的事情。当您调用“DocumentProperties”时不检查错误。 'DocumentProperties'的Delphi头文件翻译很可能是虚假的。 – 2012-07-31 18:35:29

+0

所以我可以使用Int64而不是dwNeeded的DWord? – 2012-07-31 19:04:51

+1

不,就像我说的那样,它应该被声明为'LONG'。我还想知道把垃圾传给第四和第五参数是否明智。 – 2012-07-31 19:06:41

回答

2

这里是我可以用你的代码中看到的问题:

  1. DocumentProperties返回值是32位有符号整数。它被宣布为LONG。负值表示发生错误,这就是发生在您身上的事情。只有你没有看到负值,因为你已经将值填入无符号整数。不幸的是,XE未能声明LONG。因此改变你的代码来代替使用Integer
  2. DocumentProperties返回时,您不检查错误。如果发生错误,则返回负值。确保你检查。
  3. 您正在将第4个和第5个参数中的随机垃圾传递给DocumentProperties。我怀疑你可以通过nil这两个参数你第一次打电话DocumentProperties。您肯定可以通过nil作为第五个参数,因为您从未设置过DM_IN_BUFFER
  4. 发生错误时,您将Result设置为nil,但您继续执行该功能的其余部分。不要这样做。呼叫退出以打破该功能。分配给Result不会以类似C语言的return的方式终止执行。
  5. 使用try/finally块可确保您致电CloseHandle。这允许你只写一次CloseHandle
0

下面是David建议的解决方案......感谢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 } 
+1

这绝对不是我建议的!我建议使用'LONG'而不是传递像'pDevModeVar2 ^'这样的随机垃圾。我也建议正确处理错误。当您调用“DocumentProperties”时不检查错误。当你检查错误时,你不会正确地做。 – 2012-07-31 19:17:11

+0

XE不支持LONG类型。所以我坚持Int64的。至于错误处理...你有什么建议?我对这种编程水平相当陌生。 – 2012-07-31 19:25:24

+0

的确我在windows.pas中也找不到LONG。使用'Longint',这就是'winspool.pas'中声明'DocumentProperties'的方式。或者,建议使用'Integer'.. – 2012-07-31 19:41:29