用程序设置打印机缺省纸张大小的问题解决了,请斑竹WingSun领奖: 300分!
BCB 2001-07-23 02:44:08 回复人:netware() (2001-4-12 16:46:00) 得50分
TPrinter 类是Delphi 对Windows 打印处理系统的封装,它能够帮助程序员在开发打印程序时尽可能地减少工作量。在程序中使用TPrinter,只要在单元的Use 子句后面添加Printers 即可。当前打印机的DevMode 结构的句柄可以通过调用Tprinter 类中的GetPrinter 方法来获取。当程序获得DevMode 结构的句柄后,就调用GlobalLock 函数来得到指向该结构的指针,随后可对结构中的某些成员进行修改。下面就举一个例子来说明这一问题:假设当前打印机的默认纸张尺寸是A3 纸,现在要打印长度为114mm、宽度为190mm 的纸张。为了简单起见,我们只在Form1 上放置一个Button1 按钮,增加一个OnClick 事件,在Use 子句后添加Printers。程序的代码如下:
Procedure TForm1.Button1Click(Sender: TObject);
var
Device : array[0..cchDeviceName -1] of Char;
Driver : array[0..(MAX_PATH -1)] of Char;
Port : array[0..32]of Char;
hDMode : THandle;
pDMode : PDevMode;
begin
Printer.GetPrinter(Device,Driver,Port,hDMode);
// 获取打印机DevMode 结构的句柄值,
存放在hDMode 中
if hDMode < > 0 then begin
pDMode := GlobalLock(hDMode);
// 获取指向打印机DevMode 结构的// 指针
if pDMode < > nil then begin
pDMode^.dmPaperSize := 256; //要设为其它可查API 中的DevMode
// 如果要将当前打印机纸张变为自定义
dmPaperSize 必须设置成256
pDMode^.dmPaperLength := 1140;
pDMode^.dmPaperWidth := 1900;
pDMode^.dmFields := pDMode^.dmFields or
DM_PAPERSIZE;
pDMode^.dmFields :=
pDMode^.dmFields or DM_PAPERLENGTH;
pDMode^.dmFields :=
pDMode^.dmFields or DM_PAPERWIDTH;
{ 以上三条语句是对相应
的dmFields 成员进行置位。}
ResetDC(Printer.Handle,pDMode^);
// 设置打印机设备环境句柄的值
GlobalUnlock(hDMode);
end;
end;
{ 下面的代码是为了测试打印机是否
按190 *114 纸张大小来打印}
with Printer do begin
BeginDoc;
Canvas.TextOut(10,10,'Hello, My Friend!');
EndDoc;
end;
end;
回复人: BCB(:)) (2001-7-23 13:23:25) 得0分
好的,孙班主:
试好后总结一下,到时候我另上一200分的贴子
回复人: Wingsun(孙春阳) (2001-7-23 13:49:17) 得0分
我修改成功一部分,经过测试成功。
char Device[CCHDEVICENAME];
char Driver[MAX_PATH];
char Port[32];
PDevMode pDev;
THandle hDev;
TPrinter *Prntr = Printer();
HANDLE hPrinter;
Prntr->GetPrinter(Device,Driver,Port,hDev);
if(hDev!=0)
{
pDev =(PDevMode)GlobalLock((void*)hDev);
if(pDev!=NULL)
{
pDev->dmPaperSize=DMPAPER_USER;
pDev->dmPaperLength = 1500;//这儿的值不能太大了,太大了就有问题,这也是我以前不成功的原因。
pDev->dmPaperWidth = 2000;//同样这儿的数值也不能太大。
pDev->dmFields = (pDev->dmFields)¦(DM_PAPERSIZE);
pDev->dmFields = (pDev->dmFields)¦(DM_PAPERLENGTH);
pDev->dmFields = (pDev->dmFields)¦(DM_PAPERWIDTH);
}
ResetDC(Prntr->Handle,pDev);
GlobalUnlock((void*)hDev);
}
Prntr->BeginDoc();
Prntr->Title="hello";
Prntr->Canvas->Font->Size = 20;
Prntr->Canvas->TextOutA(100,100,"生石膏的大概撒搞活");
Prntr->EndDoc();
回复人: BCB(:)) (2001-7-23 14:07:06) 得0分
#include "printers.hpp"
void __fastcall TForm1::Button1Click(TObject *Sender)
{
char Device[CCHDEVICENAME];
char Driver[MAX_PATH];
char Port[32];
THandle hDMode;
PDevMode pDMode;
TPrinter *Prn = Printer();
Prn->GetPrinter(Device,Driver,Port,hDMode);
pDMode=(PDevMode)GlobalLock((HGLOBAL &)hDMode);
pDMode->dmPaperSize= 256;
pDMode->dmFields=pDMode->dmFields ¦ DM_PAPERSIZE;
pDMode->dmPaperLength =1016; //高:4英寸=101.6mm
pDMode->dmFields =pDMode->dmFields¦ DM_PAPERLENGTH;
pDMode->dmPaperWidth = 2540; //宽:10英寸=25.40mm
pDMode->dmFields =pDMode->dmFields¦ DM_PAPERWIDTH;
ResetDC(Prn->Handle,pDMode);
GlobalUnlock((HGLOBAL &)hDMode);
Prn->BeginDoc();
Prn->Canvas->Font->Name = "宋体";
Prn->Canvas->Font->Size = 20;
Prn->Canvas->TextOutA (0,0,"页首");
Prn->EndDoc();
}
俺好试了!
缺省打印机本来设在11*10inch,本程序设成10*4inch,
连打印3次,准确换页,打完后查看并没有改变打印机的原缺省纸张大小,怪。
但英寸是人工转换成mm的,这会产生小误省,有没有办法直接设成英寸?!
回复人: BCB(:)) (2001-7-23 14:14:18) 得0分
to WingSun:
咱同时试好,分照给,
但英寸是人工转换成mm的,这会产生小误差,有没有办法直接设成英寸?!
我的财务凭证纸刚好是 10*4(英寸),但1 inch=2.54cm是不完全精确的,
恐打印多了,走纸就不对了!
回复人: Wingsun(孙春阳) (2001-7-23 14:32:45) 得0分
第二种方法,经过试验也成功了:
HANDLE PrnHd;
PPrinterInfo1 PrnInfo ;
DWORD pcbNeeded ;
DWORD PDevModeBytes ;
LPDEVMODE DevMode;
HDC PrnHdc;
PDocInfo DocInfo ;
TPrinter *Prntr = Printer();
OpenPrinter(Prntr->Printers->Strings[Prntr->PrinterIndex].c_str(),&PrnHd,NULL);
PrnInfo=(PPrinterInfo1)malloc(1024);
GetPrinter(PrnHd,1,(LPBYTE)PrnInfo,1024,&pcbNeeded);
PDevModeBytes= DocumentProperties( Handle,PrnHd,PrnInfo->pDescription,NULL,NULL,0 );
DevMode=(LPDEVMODE)malloc(PDevModeBytes);
DocumentProperties( Handle,PrnHd,PrnInfo->pDescription,DevMode,NULL,DM_OUT_BUFFER );
DevMode->dmPaperSize = DMPAPER_USER;//DMPAPER_A4 ;
DevMode->dmPaperWidth =1600;
DevMode->dmPaperLength=1600;
DevMode->dmFields = DevMode->dmFields ¦ DM_PAPERSIZE;
DevMode->dmFields = DevMode->dmFields ¦ DM_PAPERLENGTH;
DevMode->dmFields = DevMode->dmFields ¦ DM_PAPERWIDTH;
DocumentProperties( Handle,PrnHd,PrnInfo->pDescription,DevMode,DevMode,DM_OUT_BUFFER ¦ DM_IN_BUFFER);
PrnHdc = CreateDC( NULL, Prntr->Printers->Strings[Prntr->PrinterIndex].c_str(),NULL,DevMode );
DocInfo=(PDocInfo)malloc(100 );
DocInfo->cbSize = sizeof(DocInfo);
DocInfo->lpszDocName = NULL;
DocInfo->lpszOutput = NULL;
DocInfo->lpszDatatype = NULL;
DocInfo->fwType = DI_APPBANDING;
StartDoc( PrnHdc, DocInfo);
StartPage(PrnHdc);
TextOut( PrnHdc, 10, 10, "Hello My Friend!",17);
EndPage(PrnHdc);
EndDoc(PrnHdc);
DeleteDC(PrnHdc);
free(DocInfo);
free(PrnInfo);
free(DevMode);
回复人: BCB(:)) (2001-7-23 14:40:16) 得0分
#include "printers.hpp"
void SetPaperSize(int w,int h) // 设置缺省打印机纸张大小 w*h(*0.1mm)
{
char Device[CCHDEVICENAME];
char Driver[MAX_PATH];
char Port[32];
THandle hDMode;
PDevMode pDMode;
TPrinter *Prn = Printer();
Prn->GetPrinter(Device,Driver,Port,hDMode);
if (hDMode!=NULL)
{
pDMode=(PDevMode)GlobalLock((HGLOBAL &)hDMode);
if (pDMode!=NULL)
{
pDMode->dmPaperSize= 256;
pDMode->dmFields=pDMode->dmFields ¦ DM_PAPERSIZE;
pDMode->dmPaperLength =h; //高 *0.1mm
pDMode->dmFields =pDMode->dmFields¦ DM_PAPERLENGTH;
pDMode->dmPaperWidth = w; //宽 *0.1mm
pDMode->dmFields =pDMode->dmFields¦ DM_PAPERWIDTH;
}
ResetDC(Prn->Handle,pDMode);
GlobalUnlock((HGLOBAL &)hDMode);
}
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
SetPaperSize(2540,1016); // 10英寸*4 英寸
TPrinter *Prn = Printer();
Prn->BeginDoc();
Prn->Canvas->Font->Name = "宋体";
Prn->Canvas->Font->Size = 20;
Prn->Canvas->TextOutA (0,0,"页首");
Prn->NewPage();
Prn->Canvas->Font->Name = "宋体";
Prn->Canvas->Font->Size = 20;
Prn->Canvas->TextOutA (0,0,"页首");
Prn->NewPage();
Prn->Canvas->Font->Name = "宋体";
Prn->Canvas->Font->Size = 20;
Prn->Canvas->TextOutA (0,0,"页首");
Prn->EndDoc();
}
已经很不错了