Microsoft KB Archive/304639

= How to find PaperSize for custom print sizes under Windows NT and later versions by using Windows API functions =

Article ID: 304639

Article Last Modified on 2/2/2005

-

APPLIES TO


 * Microsoft Visual FoxPro 6.0 Professional Edition
 * Microsoft Visual FoxPro 7.0 Professional Edition
 * Microsoft Visual FoxPro 8.0 Professional Edition
 * Microsoft Visual FoxPro 9.0 Professional Edition

-



This article was previously published under Q304639



SUMMARY
Microsoft Windows NT 4.0, Windows 2000, Windows XP, and Windows Server 2003 do not respect custom paper sizes as Windows 95 and later do. The custom paper size is stored in the report header, under PaperSize in the EXPR field. Under Windows 95 and later, the PaperSize for custom is 256, with PaperLength and PaperWidth controlling the actual size. Under Windows NT 4.0 and later, the custom size must correspond to a predefined form.

To determine the correct PaperSize to use for a Windows NT 4.0 report or a report in a later version of Windows, you must use Windows API calls. This article includes code that demonstrates how to determine the name and size of the forms that are installed on your system.



MORE INFORMATION
In Windows 95, you can select the paper size Custom, and then select the page height and width. Under NT-based systems, to print to a custom size, you must select a printer form, which specifies the paper size. To view the different forms that are available on your system, open the Printers window, and click Server Properties on the File menu. You may not be able to directly select all of these from Visual FoxPro.

The number of the form is stored in the report header, under PaperSize in the EXPR field. To view this, USE the report as a table (USE myReport.frx), BROWSE it, and double-click the Memo in the first line of the EXPR field. The default PaperSize can also be displayed with the PRTINFO(2) function.

This code requires Christof Lange's STRUCT.VCX class, which can be downloaded at various sites on the Internet, including the following:

Universal thread

http://www.universalthread.com

SET PATH TO c:\STRUCT && Change this to be wherever you unzipped the class. SET CLASSLIB TO STRUCT.vcx

CLEAR ALL CLEAR

DECLARE LONG EnumFormsA IN winspool.drv AS EnumForms ; LONG hPrinter, LONG Level, LONG pForm, ; LONG cbBuf, LONG @pcbNeeded, ; LONG @ pcReturned DECLARE LONG OpenPrinterA IN winspool.drv AS OpenPrinter ; STRING pPrinterName, LONG @ phPrinter, LONG pDefault
 * !* Windows API call to list printer forms.
 * !* Windows API call to get a printer handle.

phPrinter = 0 && Define printer handle for pass-by-reference pPrinterName = 0 && Use UNC printer name for network printers lnRetVal = OpenPrinter(0, @phPrinter, 0)
 * !* If you pass 0 here, rather than a specific printer name as
 * !* pPrinterName, you will get custom forms defined on
 * !* the local computer. To get forms on a network printer, pass
 * !* a UNC printer name (i.e. from GetPrinter or APrinters)
 * !* as a string for pPrinterName to OpenPrinter below.

IF lnRetVal = 0 MESSAGEBOX(&quot;OpenPrinter failed!&quot;) RETURN ENDIF

loForms = CREATEOBJECT(&quot;clsPrinterForms&quot;)
 * !* Create structure to hold returned printer forms.

lnFormsPtr = loForms.GetPointer(255) lnBytesNeeded = 0 lnFormCount = 0
 * !* Define variables for pass-by-reference.

lnRetVal = EnumForms(phPrinter, 1, lnFormsPtr, 0, @lnBytesNeeded, ;  @lnFormCount) loForms.FreePointer(lnFormsPtr) && clean up memory
 * !* lnRetVal will indicate that this next call failed. This is because
 * !* it was told to return 0-length information.
 * !* The second call should work properly.

lnFormsPtr = loForms.GetPointer(lnBytesNeeded) lnRetVal = EnumForms(phPrinter, 1, lnFormsPtr, lnBytesNeeded, ;  @lnBytesNeeded, @lnFormCount) IF lnRetVal = 0 MESSAGEBOX(&quot;EnumForms call failed&quot;) loForms.FreePointer(lnFormsPtr) && clean up memory RETURN ENDIF
 * !* Get the proper memory size reserved, and call EnumForms.

DIMENSION loForms.aForms[lnFormCount] FOR i = 1 TO lnFormCount loForms.aForms[i] = CREATEOBJECT(&quot;clsFormInfo&quot;) ENDFOR
 * !* When you defined the PrinterForms class, you didn't know how many forms
 * !* were being returned. Now that you do, you need to redimension the array
 * !* property to hold the proper number of forms, and get them ready to hold
 * !* the form information.

loForms.SetPointer(lnFormsPtr)
 * !* Take the memory pointer you received, and break it up into the objects you
 * !* defined below.

loForms.FreePointer(lnFormsPtr) && clean up memory

FOR i = 1 TO lnFormCount loForm = loForms.aForms[i] *!* i is what you would see in PaperSize in the Expr field, or in   *!* the PRTINFO function. The Size.cx and cy values are in 1000ths *!* of a millimeter: there are 25.4 millimeters to an inch. ? i, PADR(loForm.pName, 30), loForm.Size.cx / 25400, loForm.Size.cy / 25400 ENDFOR

RETURN

DEFINE CLASS clsPrinterForms AS STRUCT DIMENSION aForms[1] cMembers = &quot;o:aForms&quot;
 * !* The class properties correspond to the members of the structures,
 * !* and cMembers indicates what type of variables are in the return
 * !* from the API call. &quot;l:&quot; indicates a long, &quot;o:&quot; indicates
 * !* a structure, and &quot;pz:&quot; indicates a pointer to a null-terminated
 * !* string.
 * !* See Struct.vcx documentation for more information about the STRUCT
 * !* class and its settings.

nMemorySize = 100000 && Reserve memory for pointers

PROCEDURE INIT This.aForms[1] = CREATEOBJECT(&quot;clsFormInfo&quot;) DODEFAULT ENDPROC ENDDEFINE

DEFINE CLASS clsFormInfo AS STRUCT nflags = 0 pName = &quot;&quot;     && form name Size = .NULL. && paper size ImageableArea = .NULL.

cMembers = &quot;l:nflags, pz:pName, o:size, o:imageableArea&quot;

PROCEDURE INIT This.Size = CREATEOBJECT(&quot;clsSizeL&quot;) This.ImageableArea = CREATEOBJECT(&quot;clsRectL&quot;) DODEFAULT ENDPROC ENDDEFINE

DEFINE CLASS clsSizeL AS STRUCT cx = 0  && paper width cy = 0  && paper height

cMembers = &quot;l:cx, l:cy&quot; ENDDEFINE

DEFINE CLASS clsRectL AS STRUCT nLeft = 0 nTop = 0 nRight = 0 nBottom = 0

cMembers = &quot;l:nLeft, l:nTop, l:nRight, l:nBottom&quot; ENDDEFINE

The third-party products that are discussed in this article are manufactured by companies that are independent of Microsoft. Microsoft makes no warranty, implied or otherwise, regarding the performance or reliability of these products.

