在 WindowsNT/200 環境下要自訂紙張尺寸所使用的方法與 Win9x 不同, 你必須先為目前的印表機定義一個自訂的 "Form"(呼叫 API: AddForm, 此 API 宣告於 WinSpool 單元中),然後把這個 Form 的名稱設定給 DEVMODES 結構中的 dmFormName 欄位。以下的函式可以直接拿來使用: uses Windows, WinSpool, Printers; (*------------------------------------------------------ Define a new Form (WinNT/2000 only). If FormName already exists, do nothing and return. If failed, an exception will be raised. ------------------------------------------------------*) procedure PrnAddForm(const FormName: string; PaperWidth, PaperLength: integer); var PrintDevice, PrintDriver, PrintPort : array[0..255] of Char; hDMode : THandle; hPrinter: THandle; FormInfo: TFormInfo1; PaperSize: TSize; PaperRect: TRect; errcode: integer; s: string; begin Printer.GetPrinter(PrintDevice, PrintDriver, PrintPort, hDMode); OpenPrinter(PrintDevice, hPrinter, nil); if hPrinter = 0 then raise Exception.Create('Failed to open printer!'); FormInfo.Flags := FORM_USER; FormInfo.pName := PChar(FormName); PaperSize.cx := PaperWidth; PaperSize.cy := PaperLength; PaperRect.Left := 0; PaperRect.Top := 0; PaperRect.Right := PaperWidth; PaperRect.Bottom := PaperLength; FormInfo.Size := PaperSize; FormInfo.ImageableArea := PaperRect; if not AddForm(hPrinter, 1, @FormInfo) then begin errcode := GetLastError; if errcode <> ERROR_FILE_EXISTS then // Form name exists? begin case errcode of ERROR_ACCESS_DENIED: s := 'Access is denied'; ERROR_INVALID_HANDLE: s := 'The handle is invalid'; ERROR_NOT_READY: s := 'The device is not ready'; ERROR_CALL_NOT_IMPLEMENTED: s := 'Function "AddForm" is not supported on this system'; else s := 'Failed to add a Form (paper) name!'; end; raise Exception.Create(s); end; end; ClosePrinter(hPrinter); end; (* Set custom paper size for WinNT/2000. Make sure FormName is supported by current printer, You can call PrnAddForm to define a new Form. *) procedure PrnSetPaperSizeNT(FormName: string; PaperWidth, PaperLength: integer); var Device, Driver, Port: array[0..80] of Char; DevMode: THandle; pDevmode: PDeviceMode; begin // Get printer device name etc. Printer.GetPrinter(Device, Driver, Port, DevMode); // force reload of DEVMODE Printer.SetPrinter(Device, Driver, Port, 0) ; // get DEVMODE handle Printer.GetPrinter(Device, Driver, Port, DevMode); if DevMode <> 0 then begin // lock it to get pointer to DEVMODE record pDevMode := GlobalLock( DevMode ); if pDevmode <> nil then try with pDevmode^ do begin // modify form StrLCopy( dmFormName, PChar(FormName), CCHFORMNAME-1 ); // tell printer driver that dmFormname field contains // data it needs to inspect. dmPaperWidth := PaperWidth; dmPaperLength := PaperLength; dmFields := dmFields or DM_FORMNAME or DM_PAPERWIDTH or DM_PAPERLENGTH; end; finally GlobalUnlock( Devmode ); // unlock devmode handle. end; end; { If } end; procedure TForm1.Button1Click(Sender: TObject); begin PrnAddForm( edFormName.Text, StrToInt(edPaperWidth.Text), StrToInt(edPaperLength.Text) ); PrnSetPaperSizeNT( edFormName.Text, StrToInt(edPaperWidth.Text), StrToInt(edPaperLength.Text) ); Printer.BeginDoc; Printer.Canvas.TextOut(10, 10, 'Printer test!'); Printer.EndDoc; end;