Lazarus中文社区

 找回密码
 立即注册(注册审核可向QQ群索取)

QQ登录

只需一步,快速开始

Lazarus IDE and 组件 下载地址版权申明
查看: 2486|回复: 3

求助:代码创建打印机纸张

[复制链接]

该用户从未签到

发表于 2012-8-15 15:35:23 | 显示全部楼层 |阅读模式
最近几天尝试用代码创建打印机纸张,参考DELPHI的代码,一直未果.水平有限,特来求助.
获取打印机的代码可以了,附问题程序.


谢谢

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册(注册审核可向QQ群索取)

x
回复

使用道具 举报

该用户从未签到

 楼主| 发表于 2012-8-19 13:56:39 | 显示全部楼层
试了N次还是不行啊,继续求助
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2012-9-2 14:44:52 | 显示全部楼层
顶顶!!!!!!!!!!!!!!!!!!!!!!!
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2012-9-3 13:48:07 | 显示全部楼层
以下是从网络中找到的,但在lazarus中通不过,唉,总也改不好.烦请大家给看看,多谢了

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

在 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, &#39rinter test!');

Printer.EndDoc;

end;

在Delphi帮助中,AddForm定义如下:

BOOL AddForm(

HANDLE hPrinter, // handle to printer object

DWORD Level, // data-structure level

LPBYTE pForm // pointer to form info. data structure

);

下面是我在Delphi中定义的自定义函数AddPaper():

function AddPaper(PaperName: PChar;fPaperWidth,fPaperHeigth: Double): String;

var

PrintDevice, PrintDriver, PrintPort : array[0..255] of Char;

hDMode : THandle;

hPrinter: THandle;

FormInfo: TForminfo1;

PaperSize: TSize;

PaperRect: TRect;

PaperWidth,PaperHeigth: Integer;

function Zlxs(S: String;nWs: Integer): String; //整理小数位,并转化成厘米

begin

Try

Result:=FloatToStr(StrToFloat(S));

If pos('.',Result)>0 then

Result:=Copy(Result,1,pos('.',Result)+2);

Result:=FloatToStr(StrToFloat(Result)*10000);

Except

Result:='0';

end;

end;

begin

PaperWidth:=StrToInt(Zlxs(FloatToStr(fPaperWidth),3));

Paperheigth:=StrToInt(Zlxs(FloatToStr(fPaperheigth),3));

//判断是否安装打印机,并得到默认打印机的句柄

Printer.GetPrinter(PrintDevice, PrintDriver, PrintPort, hDMode);

OpenPrinter(PrintDevice, hPrinter, nil);

if hPrinter=0 then

begin

Result:='没有安装打印机!';

Exit;

end;

//定义结构

FormInfo.Flags:=FORM_USER;

FormInfo.pName:=PChar(PaperName);

PaperSize.cx:=PaperWidth;

PaperSize.cy:=PaperHeigth;

PaperRect.Left:=0;

PaperRect.Top:=0;

PaperRect.Right:=PaperSize.cx;

PaperRect.Bottom:=PaperSize.cy;

FormInfo.Size:=PaperSize;

FormInfo.ImageableArea:=PaperRect;

AddForm(hPrinter,1,@FormInfo); //添加纸张

ClosePrinter(hPrinter);

end;

3个参数:PaperName:你给纸张命的名(操作系统中叫描述格式),fPaperWidth:纸张宽度,fPaperHeigth:纸张高度。如果没有安装打印机,返回提示信息。如果已经有同样名称的纸张,函数不起作用,建议大家最好在名称中加入“_”,因为很少有这样命名的纸张,你的程序用你的专用纸张也不为过吧(谁叫Windows不提供,而我们偏偏又要用呢)?里面还有一个函数:Zlxs,这是用来整理小数的,经过试验,加入的纸张采用的单位是厘米时宽度用10000时只有1厘米,大家输入的往往是以厘米为单位的,且带小数,所以得用一个函数来将浮点数转换成整数。当然首先还得在uses段中加入Printers,winspool引用。以上代码在D5,D6+ Win 2000中运行通过。将这个函数加入管理系统中,在打印之前调用生成专用纸张,省时又省力。
回复 支持 反对

使用道具 举报

*滑块验证:

本版积分规则

QQ|手机版|小黑屋|Lazarus中国|Lazarus中文社区 ( 鄂ICP备16006501号-1 )

GMT+8, 2025-5-2 23:01 , Processed in 0.027775 second(s), 10 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表