用程序设置打印机缺省纸张大小的问题解决了,请斑竹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();
}
已经很不错了
...全文
404 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Foreign_Devil 2002-01-15
  • 打赏
  • 举报
回复
pDev->dmFields=(pDev->dmFields)¦(DM_PAPERSIZE);
^
这是个什么?
oldsteel 2001-08-31
  • 打赏
  • 举报
回复
BCB(:)): 我表示怀疑.我照你的代码试过了,在我的机器上并不行。你把dmPaperSize 设成256,而windows SDK的说明是应设为0,难道windows SDK有错?你的测试代码并不能说明问题,Canvas.TextOut(10,10,'Hello, My Friend!');这个位置根本未超出pDMode^.dmPaperLength := 1140;
pDMode^.dmPaperWidth := 1900;
代码设置的范围。你应该试着再输出一串字符在定义的范围外,若范围外的不打印则说明成功了,或者跟踪printer.pagewidth与printer.pageheight的值,看是否与打印机设置的默认打印纸的大小一样。
我的看法是与驱动程序有关,我试过有些环境起作用,有些环境则不起作用,不知是否有一定起作用的代码?  
   
BCB 2001-08-03
  • 打赏
  • 举报
回复
| (or) 个符号 变成了 | ¦
BCB 2001-07-23
  • 打赏
  • 举报
回复
给分了
XioGua 2001-07-23
  • 打赏
  • 举报
回复
恭喜发财...

down了

G_G
BCB 2001-07-23
  • 打赏
  • 举报
回复
我已将这段代码立刻用到原先的打印程序,呵呵
wjzhuang 2001-07-23
  • 打赏
  • 举报
回复
收藏先!
Wingsun 2001-07-23
  • 打赏
  • 举报
回复
是啊!我以前写的代码也和他的差不多,但是总不成功。
BCB 2001-07-23
  • 打赏
  • 举报
回复
这原创 高手netware() 没法寻到了,也不能忘记他呀

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧