2012-07-31 24 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