使用Delphi实现票据精确打印
一、概述
在银行,税务,邮政等行业的实际工作中,经常涉及到在印刷好具有固定格式的汇款单,储蓄凭证,
税票等单据上的确定位置打印输出相关的信息。在此类需求中,精确地定位单据并打印相关信息,
是解决问题的关键。一般情况下,开发者都是通过在打印机上通过重复的测试来达到实际需求。
那么,有没有简单有效而又灵活的方法实现上述功能呢?
二、基本思路
分析上述单据的特征,可以发现:此类打印输出的信息一般比较简短,不涉及到文字过长的折行处理,
另外,其打印输出的位置相对固定。因此,我们可以通过用尺子以毫米为单位,测量好每个输出信息位置
的横向和纵向坐标,作为信息输出的位置。但由于不同打印机在实际输出效果上,总是存在理论和实际位置
的偏差,因此,要求程序具有一定的灵活性,供最终用户根据需要,进行必要的位置调整。因此,可设置
一打印配置文件,用于存储横坐标和纵坐标的偏移量,用于用户进行位置校正,从而提供了一定的灵活性。
三、精确打印输出的程序实现
1. 在Delphi中新建一个名为mprint.pas的单元文件并编写如下程序,单元引用中加入Printers略:
//取得字符的高度
function CharHeight: Word;
var
Metrics: TTextMetric;
begin
GetTextMetrics(Printer.Canvas.Handle, Metrics);
Result := Metrics.tmHeight;
end;
file://取得字符的平均宽度
function AvgCharWidth: Word;
var
Metrics: TTextMetric;
begin
GetTextMetrics(Printer.Canvas.Handle, Metrics);
Result := Metrics.tmAveCharWidth;
end;
file://取得纸张的物理尺寸---单位:点
function GetPhicalPaper: TPoint;
var
PageSize : TPoint;
begin
file://PageSize.X; 纸张物理宽度-单位:点
file://PageSize.Y; 纸张物理高度-单位:点
Escape(Printer.Handle, GETPHYSPAGESIZE, 0,nil,@PageSize);
Result := PageSize;
end;
file://2.取得纸张的逻辑宽度--可打印区域
file://取得纸张的逻辑尺寸
function PaperLogicSize: TPoint;
var
APoint: TPoint;
begin
APoint.X := Printer.PageWidth;
APoint.Y := Printer.PageHeight;
Result := APoint;
end;
file://纸张水平对垂直方向的纵横比例
function HVLogincRatio: Extended;
var
AP: TPoint;
begin
Ap := PaperLogicSize;
Result := Ap.y/Ap.X;
end;
file://取得纸张的横向偏移量-单位:点
function GetOffSetX: Integer;
begin
Result := GetDeviceCaps(Printer.Handle, PhysicalOffSetX);
end;
file://取得纸张的纵向偏移量-单位:点
function GetOffSetY: Integer;
begin
Result := GetDeviceCaps(Printer.Handle, PhysicalOffSetY);
end;
file://毫米单位转换为英寸单位
function MmToInch(Length: Extended): Extended;
begin
Result := Length/25.4;
end;
file://英寸单位转换为毫米单位
function InchToMm(Length: Extended): Extended;
begin
Result := Length*25.4;
end;
file://取得水平方向每英寸打印机的点数
function HPointsPerInch: Integer;
begin
Result := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
end;
file://取得纵向方向每英寸打印机的光栅数
function VPointsPerInch: Integer;
begin
Result := GetDeviceCaps(Printer.Handle, LOGPIXELSY)
end;
file://横向点单位转换为毫米单位
function XPointToMm(Pos: Integer): Extended;
begin
Result := Pos*25.4/HPointsPerInch;
end;
file://纵向点单位转换为毫米单位
function YPointToMm(Pos: Integer): Extended;
begin
Result := Pos*25.4/VPointsPerInch;
end;
file://设置纸张高度-单位:mm
procedure SetPaperHeight(Value:integer);
var
Device : array[0..255] of char;
Driver : array[0..255] of char;
Port : array[0..255] of char;
hDMode : THandle;
PDMode : PDEVMODE;
begin
file://自定义纸张最小高度127mm
if Value < 127 then Value := 127;
file://自定义纸张最大高度432mm
if Value > 432 then Value := 432;
Printer.PrinterIndex := Printer.PrinterIndex;
Printer.GetPrinter(Device, Driver, Port, hDMode);
if hDMode <> 0 then
begin
pDMode := GlobalLock(hDMode);
if pDMode <> nil then
begin
pDMode^.dmFields := pDMode^.dmFields or DM_PAPERSIZE or
DM_PAPERLENGTH;
pDMode^.dmPaperSize := DMPAPER_USER;
pDMode^.dmPaperLength := Value * 10;
pDMode^.dmFields := pDMode^.dmFields or DMBIN_MANUAL;
pDMode^.dmDefaultSource := DMBIN_MANUAL;
GlobalUnlock(hDMode);
end;
end;
Printer.PrinterIndex := Printer.PrinterIndex;
end;
file://设置纸张宽度:单位--mm
Procedure SetPaperWidth(Value:integer);
var
Device : array[0..255] of char;
Driver : array[0..255] of char;
Port : array[0..255] of char;
hDMode : THandle;
PDMode : PDEVMODE;
begin
file://自定义纸张最小宽度76mm
if Value < 76 then Value := 76;
file://自定义纸张最大宽度216mm
if Value > 216 then Value := 216;
Printer.PrinterIndex := Printer.PrinterIndex;
Printer.GetPrinter(Device, Driver, Port, hDMode);
if hDMode <> 0 then
begin
pDMode := GlobalLock(hDMode);
if pDMode <> nil then
begin
pDMode^.dmFields := pDMode^.dmFields or DM_PAPERSIZE or
DM_PAPERWIDTH;
pDMode^.dmPaperSize := DMPAPER_USER;
file://将毫米单位转换为0.1mm单位
pDMode^.dmPaperWidth := Value * 10;
pDMode^.dmFields := pDMode^.dmFields or DMBIN_MANUAL;
pDMode^.dmDefaultSource := DMBIN_MANUAL;
GlobalUnlock(hDMode);
end;
end;
Printer.PrinterIndex := Printer.PrinterIndex;
end;
file://在 (Xmm, Ymm)处按指定配置文件信息和字体输出字符串
procedure PrintText(X, Y: Extended; Txt: string; ConfigFileName: string; FontSize: Integer=12);
var
OrX, OrY: Extended;
Px, Py: Integer;
AP: TPoint;
Fn: TStrings;
FileName: string;
OffSetX, OffSetY: Integer;
begin
file://打开配置文件,读出横向和纵向偏移量
try
Fn := TStringList.Create;
FileName := ExtractFilePath(Application.ExeName) + ConfigFileName;
if FileExists(FileName) then
begin
Fn.LoadFromFile(FileName);
file://横向偏移量
OffSetX := StrToInt(Fn.Values['X']);
file://纵向偏移量
OffSetY := StrToInt(Fn.Values['Y']);
end
else
begin
file://如果没有配置文件,则生成
Fn.Values['X'] := '0';
Fn.Values['Y'] := '0';
Fn.SaveToFile(FileName);
end;
finally
Fn.Free;
end;
X := X + OffSetX;
Y := Y + OffSetY;
Px := Round(Round(X * HPointsPerInch * 10000/25.4) / 10000);
Py := Round(Round(Y * VPointsPerInch * 10000/25.4) / 10000);
Py := Py - GetOffSetY; file://因为是绝对坐标, 因此, 不用换算成相对于Y轴坐标
Px := Px + 2 * AvgCharWidth;
Printer.Canvas.Font.Name := '宋体';
Printer.Canvas.Font.Size := FontSize;
file://Printer.Canvas.Font.Color := clGreen;
Printer.Canvas.TextOut(Px, Py, Txt);
end;
2. 使用举例
在主窗体中加入对mprint单元的引用,在一命令钮的OnClick
事件中书写如下代码(用于在邮政汇款单上的相应方框内打印邮政编码843300):
Printer.BeginDoc;
PrintText(16, 14, '8', 'config.txt');
PrintText(26, 14, '4', 'config.txt');
PrintText(36, 14, '3', 'config.txt');
PrintText(46, 14, '3', 'config.txt');
PrintText(56, 14, '0', 'config.txt');
PrintText(66, 14, '0', 'config.txt');
Printer.EndDoc;
观察结果,用尺子测量偏移量,在config.txt文件中修改X,Y的值即可。
其它,设置打印机和纸张类型从略。
四、结束语
使用Delphi实现票据精确打印的更多相关文章
- Delphi 10 Seattle 小票打印控件TQ_Printer
TQ_Printrer控件,是一个为方便需要控制打印命令而设计的跨平台专用控件,已包含标准ESC/POS打印控制的基本指令在内(这些基本指令已能很好的满足多数项目使用). TQ_Printrer控件让 ...
- Delphi水晶横向竖向打印
最近做一个打印项目,本来报表已经设为横向打印了,可是运行程序,打印出来的是竖向的,非要在打印机里再设定为横向,郁闷了很久,看看UCrpe32的源码之后,由于我重新封装了TCrpe,在TCrpe的派生类 ...
- [2014.01.27]wfPrintOcx 票据打印控件 v5.3
支持选择打印机,并自动记忆选择的打印机. 适合打印各类票据格式. 支持画正方形.长方形.圆形.椭圆.横线.竖线.HTTP图片. 支持数字金额转换成中文大写金额. 可以设置固定宽度的文字自动换行. 组件 ...
- Web打印组件jatoolsPrinter
应用web化,不论对开发商,还是对用户来说,实在是一种很经济的选择,因为基于web的应用,客户端的规则很简单,容易学习,容易维护,容易发布.但对程序员来说,因为浏览器的局限性,却要面对很多挑战.怎么样 ...
- 2013第39周一Web打印
2013第39周一Web打印 项目中遇到了Java Web打印问题,简单调用IE浏览器的打印不能完全满足要求,于是就搜集了Web打印相关的主题,简单汇总一下.web打印难点在分页.页面纸张设置,页眉页 ...
- Web打印组件jatoolsPrinter(转载)
应用web化,不论对开发商,还是对用户来说,实在是一种很经济的选择,因为基于web的应用,客户端的规则很简单,容易学习,容易维护,容易发布.但对程序员来说,因为浏览器的局限性,却要面对很多挑战.怎么样 ...
- WEB打印的几种方案
-------------------------------------------一 基于Web的打印方案比较分析-------------------------------- 基于web的套 ...
- Web系统页面打印技术实现与分析
1 Web页面打印概述应用WEB化,不论对开发商,还是对用户来说,实在是一种很经济的选择,因为基于WEB的应用,客户端的规则很简单,容易学习,容易维护,容易发布.在WEB系统中,打印的确是个烦人的问题 ...
- lodop 控件实现web打印功能
WEB套打可选方案不多,理想的更少,利用免费控件Lodop+JavaScript实现精确套打,算是较为经典的选择.这种方案其实比较简单,利用一个htm文件就可以实现模板设计过程,几乎是“空手套”式的开 ...
随机推荐
- [Algorithm] How many meeting rooms needed?
Give you set of meetings start time and end time, count how many meeting rooms needed. For example: ...
- mysql中ibdata1过大的问题
ibdata1文件是什么? 答: ibdata1是一个用来构建innodb系统表空间的文件,这个文件包含了innodb表的元数据.撤销记录.修改buffer和双写buffer.如果file-per-t ...
- JavaScript如何根据当天算出前三天和后三天
经杨秀徐批准 中央军委颁发意见建设新型司令机关news 杨秀徐会见到北京述职的香港特首梁振英news 海军372潜艇官兵先进事迹报告会举行 杨秀徐作指示news 中央农村工作会议在京召开 李克强作重要 ...
- Maven的JAR包仓库,不用再百度搜JAR包了!
http://search.maven.org/ 今天初学Maven,发现Maven的中央仓库里差点儿什么jar都有...........还有各种版本号... 你值得拥有!
- webapck 打包体积优化策略
一.概述 1.Tree-shaking 2.公共资源分离 3.图片压缩 二.Tree-shaking Tree-shaking:1个模块可能有多个方法,只要其中的某个方法使用到了,则整个文件都会被打到 ...
- npm 主要命令
本文主要参考自:http://www.runoob.com/nodejs/nodejs-npm.html 1.使用 npm 命令安装模块 $ npm install express var expre ...
- Spring学习笔记三:Bean管理
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6775827.html 一:如何使用Spring获取对象 1:定义bean类:要按照注入方式来定义对应的bea ...
- 腾讯云ubuntu搭建jdk
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6377878.html 在购买了腾讯云ubuntu主机后,需要手动搭建java环境.安装tomcat等.ubun ...
- Java关闭Socket来终止线程
Java代码: package Threads; import java.io.BufferedReader; import java.io.IOException; import java.io.I ...
- 检测动态生成的单选按钮和jQuery的变化
我试图发现变化动态生成的单选按钮.我有一个生成的单选按钮的表单,他们根据自己的ID保存在数据库.所以这是什么 <input type="radio" name="d ...