Saturday, March 15, 2008

Getting PaperSize ID programmatically

In my previous tips, I've shown you how to add a custom paper size programmatically. Then you can modify the report and use the Page Setup to set your report to the custom paper size you have just created. VFP will automatically save the PaperSize ID according the ID when it is created in your PC. Now, when you add a custom paper in some PC, sometimes you can get a different PaperSize ID, because maybe it already have another custom paper size. So you have to hack the FRX to reflect the PaperSize ID in that computer. Here is how to get the PaperSize ID programmatically.

Notes:
- As usual, cut & paste the code below into PRG, then run "beautify" to make the code readable
CToBin()  function shown in the code is an Enhancements function in VFP9. It doesn't work on earliear version. For VFP8 and lower, use Str2Num UDF to replace the function. You can find the UDF on Universal Thread or many other VFP forums.

[CODE]
** Updated: July 07, 2008
** Bug fixed by: Julio Veloz

#Define DC_PAPERS 2
#Define DC_PAPERS_Size 2
#Define DC_PAPERNAMES 16
#Define DC_PAPERNAMES_Size 64
Declare Long DeviceCapabilities in WinSpool.drv ;
String cPrinterName, String cPort, Short nCapFlags, ;
String @O_cBuffer, Long pDevMode

Local array la_Printer[1]
Local ln_Row, ln_Result, ln_I, ln_Index
Local lc_PrinterName, lc_Buffer
Local lc_FindPaperName, lc_PaperName, lc_PaperSizeID
lc_PrinterName = set( 'Printer', 2 ) && Get default windows printer
= APrinters( la_Printer )
ln_Row = AScan( la_Printer, lc_PrinterName, 1, 0, 0, 9 )
ln_Result = DeviceCapabilities( la_Printer[ ln_Row, 1 ], ;
la_Printer[ ln_Row, 2 ], DC_PAPERNAMES, 0, 0 )
If (ln_Result > 0)
ln_Index = -1
lc_FindPaperName = upper( 'MyCustom - Half A4' )
lc_Buffer = replicate( chr(0), ln_Result * DC_PAPERNAMES_Size )
ln_Result = DeviceCapabilities( la_Printer[ ln_Row, 1 ], ;
la_Printer[ ln_Row, 2 ], DC_PAPERNAMES, @lc_Buffer, 0 )
For ln_I = 0 to ln_Result-1
lc_PaperName = upper( substr( lc_Buffer, (ln_I * DC_PAPERNAMES_Size )+1, ;
DC_PAPERNAMES_Size ))
If (lc_FindPaperName $ lc_PaperName)
ln_Index = ln_I
Exit
endif
Next
If (ln_Index != -1)
** Paper Name found, Get The PaperSize ID

ln_Result = DeviceCapabilities( la_Printer[ ln_Row, 1 ], ;
la_Printer[ ln_Row, 2 ], DC_PAPERS, 0, 0 )
If (ln_Result > 0)
lc_Buffer = replicate( chr(0), ln_Result * DC_PAPERS_Size )
ln_Result = DeviceCapabilities( la_Printer[ ln_Row, 1 ], ;
la_Printer[ ln_Row, 2 ], DC_PAPERS, @lc_Buffer, 0 )
lc_PaperSizeID = substr( lc_Buffer, (ln_Index * DC_PAPERS_Size )+1, DC_PAPERS_Size )
? 'PaperSize ID for "' + lc_FindPaperName + '" is', CToBin( lc_PaperSizeID, '2rs' )
endif
endif
endif

[/CODE]

Happy coding!