转贴
近日因项目需要接触了打印机,自定义纸张的大小问题困扰了我一个多星期,还以为XP系统无法自定义纸张,后来在网上搜索时无意中发现,打印机都有最小纸张的标准,如果小于或大于这个标准,就算自定义好了页面,都无法选择它(不会显示出来),如果用程序强制设置打印的话,它会按A4的标准走纸,比如我用的Epson LQ-300K+这款打印机,最小纸张是10CM*10.16CM,而我要的宽度正好小于10CM,后来我改成10CM后,就能正常打印了。使用下面第一段例子就可以搞定了!
转自:http://delphi.ktop.com.tw/board.php?cid=30&fid=100&tid=75503
在
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.