镀锌六角带帽螺栓:自定义一个控制打印机的单元

来源:百度文库 编辑:九乡新闻网 时间:2024/04/30 11:02:54

unit My_Print;

interface

uses
   Printers, Types, Windows, Messages, SysUtils, Variants, Graphics,Dialogs,
   Inifiles, Forms;

type
   TCustomPrinter=class(TObject)
   private
     FiOffsetX: Integer; //水平方向偏移量:.1毫米
     FiOffsetY: Integer; //垂直方向偏移量:.1毫米

    //取得字符的高度
     function CharHeight: Word;
     //取得字符的平均宽度
     function AvgCharWidth: Word;
     //取得纸张的物理尺寸---单位:点
     function GetPhicalPaper: TPoint;
     //得到打印机默认的页边距
     function GetPrintStartPos:TPoint;
     //取得纸张的逻辑宽度--可打印区域,纸张的逻辑尺寸
     function PaperLogicSize: TPoint;
     //纸张水平对垂直方向的纵横比例
     function HVLogincRatio: Extended;
     //取得纸张的横向偏移量-单位:点
     function GetOffSetX: Integer;
     //取得纸张的纵向偏移量-单位:点
     function GetOffSetY: Integer;
     //毫米单位转换为英寸单位
     function MmToInch(Length: Extended): Extended;
     //英寸单位转换为毫米单位
     function InchToMm(Length: Extended): Extended;
     //取得水平方向每英寸打印机的点数
     function HPointsPerInch: Integer;
     //取得纵向方向每英寸打印机的光栅数
     function VPointsPerInch: Integer;
     //横向点单位转换为毫米单位
     function XPointToMm(Pos: Integer): Extended;
     //纵向点单位转换为毫米单位
     function YPointToMm(Pos: Integer): Extended;
     //设置纸张尺寸:纸张宽度和纸张高度-单位:mm
     procedure SetPagerSize(const ASize: Integer; AWidth,AHeight: Double);
   protected

  public
     constructor Create;
     {********************************************************************
      函数名称:       InitPrinter
      函数功能:  初始化打印机,包括打印机名称、纸张大小等等
      输入参数:      ConfigIni: string    --打印配置文件:*.ini
      输出参数:       None      --参数的用途
      *********************************************************************}
     procedure InitPrinter(PRatio: Integer=1;APWidth: Double=171;
         APHeight: Double=78;APsize: Integer=256;ADeviceName:string='';
         Adefault:string='YES';AOffsetX:Integer=0;AOffsetY:Integer=0); overload;
     procedure InitPrinter(ConfigIni: string;PRatio: Integer=1); overload;
     {********************************************************************
      函数名称:       PrintText
      函数功能:  在 (Xmm, Ymm)处按指定配置文件信息和字体输出字符串
      输入参数:      X, Y: Extended; -- 打印起始点,单位为毫米
      输入参数:      LineHeight, TextWidth: Extended;  --行高,待打印矩形宽度
      输入参数:      Txt: string;    -- 待打印的文本
      输入参数:      FontSize: Integer=12    --字体为'宋体',缺省大小为12,
      输入参数:      TextAlignment: Integer=DT_LEFT  --文本对齐方式,缺省为'左对齐'
      输入参数:      AllowNewLine:Boolean=False  --是否允许换行
      输出参数:       换了几行则返回几,默认为1,未换行      --参数的用途
      *********************************************************************}
     function PrintText(Xmm, Ymm, LineHeight, TextWidth: Extended;
         Txt: string; FontSize: Integer=10; TextAlignment: Integer=DT_LEFT;
         AllowNewLine:Boolean=False):Integer; overload;
     function PrintText(Xmm, Ymm: Extended; Txt: string;FontSize: Integer=10;
         AllowNewLine:Boolean=False):Integer; overload;
     procedure PrintChar(s: PChar);
     procedure PrintEllipse(Xmm1, Ymm1, Xmm2, Ymm2: DOUBLE;APenWidth: Integer=2);
     procedure PrintLine(Xmm1, Ymm1, Xmm2, Ymm2: DOUBLE; ACanvas: TCanvas; APenWidth: Integer=5);
     procedure PrintTableLine(ACanvas: TCanvas; APenWidth: Integer=5);
   end;
     procedure My_InitPrinter(ConfigIni :string);
     function  My_PrintText(Xmm, Ymm: Extended; Txt: string;FontSize: Integer=10):Integer;
implementation


constructor TCustomPrinter.Create;
begin
   FiOffsetX:=0;
   FiOffsetY:=0;
end;

function TCustomPrinter.CharHeight: Word;
{取得字符的高度}
var
   Metrics: TTextMetric;
begin
   GetTextMetrics(Printer.Canvas.Handle, Metrics);
   Result := Metrics.tmHeight;
end;

//取得字符的平均宽度
function TCustomPrinter.AvgCharWidth: Word;
var
   Metrics: TTextMetric;
begin
   GetTextMetrics(Printer.Canvas.Handle, Metrics);
   Result := Metrics.tmAveCharWidth;
end;

//取得纸张的物理尺寸---单位:点
function TCustomPrinter.GetPhicalPaper: TPoint;
var
   PageSize : TPoint;
begin
   //PageSize.X; 纸张物理宽度-单位:点
   //PageSize.Y; 纸张物理高度-单位:点
   Escape(Printer.Handle, GETPHYSPAGESIZE, 0,nil,@PageSize);
   Result := PageSize;
end;

//打印机的坐标原点总是在纸张的左上角,不管纸张从那个方向进入打印机。
//得到打印机默认的页边距
function TCustomPrinter.GetPrintStartPos:TPoint;
var
   pageMargin:TPoint;
   myEscape:integer;
begin
   pageMargin.x:=0;
   pageMargin.y:=0;
   myEscape:=GETPRINTINGOFFSET;
   if Escape(Printer.Handle,QUERYESCSUPPORT,sizeof(myEscape),@myEscape,nil) >0 then
   begin
     if Escape(printer.Handle,GETPRINTINGOFFSET,0,nil,@pageMargin) <=0 then
     begin
       pageMargin.x:=0;
       pageMargin.y:=0;
     end;
   end;
   result:=pageMargin;
end;

 //2.取得纸张的逻辑宽度--可打印区域
  //取得纸张的逻辑尺寸
function TCustomPrinter.PaperLogicSize: TPoint;
var
   APoint: TPoint;
begin
   APoint.X := Printer.PageWidth;
   APoint.Y := Printer.PageHeight;
   Result := APoint;
end;

//纸张水平对垂直方向的纵横比例
function TCustomPrinter.HVLogincRatio: Extended;
var
   AP: TPoint;
begin
   Ap := PaperLogicSize;
   Result := Ap.y/Ap.X;
end;

//取得纸张的横向偏移量-单位:点 --打印机的每英寸为多少像素
function TCustomPrinter.GetOffSetX: Integer;
begin
   Result := GetDeviceCaps(Printer.Handle, PhysicalOffSetX);
end;

//取得纸张的纵向偏移量-单位:点 --打印机的每英寸为多少像素
function TCustomPrinter.GetOffSetY: Integer;
begin
   Result := GetDeviceCaps(Printer.Handle, PhysicalOffSetY);
end;

//毫米单位转换为英寸单位
function TCustomPrinter.MmToInch(Length: Extended): Extended;
begin
   Result := round(Length/25.4); //每毫米水平方向象素
end;

//英寸单位转换为毫米单位
function TCustomPrinter.InchToMm(Length: Extended): Extended;
begin
   Result := round(Length*25.4);//每毫米水平方向象素
end;

//取得水平方向每英寸打印机的点数
function TCustomPrinter.HPointsPerInch: Integer;
begin
   Result := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
end;

//取得纵向方向每英寸打印机的光栅数
function TCustomPrinter.VPointsPerInch: Integer;
begin
   Result := GetDeviceCaps(Printer.Handle, LOGPIXELSY)
end;

//横向点单位转换为毫米单位
function TCustomPrinter.XPointToMm(Pos: Integer): Extended;
begin
   Result := Pos*25.4/HPointsPerInch;
end;

//纵向点单位转换为毫米单位
function TCustomPrinter.YPointToMm(Pos: Integer): Extended;
begin
   Result := Pos*25.4/VPointsPerInch;
end;

procedure TCustomPrinter.SetPagerSize(const ASize: Integer; AWidth,
   AHeight: Double);
var
   Device : array[0..255] of char;
   Driver : array[0..255] of char;
   Port : array[0..255] of char;
   hDMode : THandle;
   PDMode : PDEVMODE;
   paperOrientation: Integer;
begin
   //自定义纸张最小高度70mm
   if AHeight  < 70 then AHeight := 70;
   //自定义纸张最大高度432mm
   if AHeight  > 500 then AHeight := 500;
    //自定义纸张最小宽度76mm
   if AWidth  < 76 then AWidth := 76;
    //自定义纸张最大宽度216mm
   if AWidth  > 300 then AWidth := 300;
   paperOrientation:=1;
   {AWidth := 171;
   AHeight := 78;}
   Printer.PrinterIndex := Printer.PrinterIndex;
   Printer.GetPrinter(Device, Driver, Port, hDMode);
   if hDMode  <> 0 then
   begin
     pDMode := GlobalLock(hDMode);
     if pDMode  <> nil then
     begin
       {设定打印的方向为纵向或横向
       if PaperOrientation <>0 then
         pDMode^.dmOrientation:=DMORIENT_LANDSCAPE
       else pDMode^.dmOrientation:=DMORIENT_PORTRAIT;
         //设置拷贝份数为1份.
       pDMode^.dmCopies:=1;}

      //自定义纸张
       pDMode^.dmPaperSize := DMPAPER_USER;
       {pDMode^.dmPaperSize:=256;}
        //将毫米单位转换为0.1mm单位

      pDMode^.dmPaperWidth := round(AWidth * 10);
       pDMode^.dmPaperLength := round(Aheight * 10);
       pDMode^.dmFields := pDMode^.dmFields or DM_PAPERSIZE or
                           DM_PAPERWIDTH;
       pDMode^.dmFields := pDMode^.dmFields or DM_PAPERLENGTH;
       //pDMode^.dmFields := pDMode^.dmFields or DMBIN_MANUAL;
       {pDMode^.dmFields:=pDMode^.dmFields or DM_PAPERSIZE;
       pDMode^.dmFields:=pDMode^.dmFields or DM_PAPERWIDTH;
       pDMode^.dmFields:=pDMode^.dmFields or DM_PAPERLENGTH;}
       //pDMode^.dmDefaultSource := DMBIN_MANUAL;

      GlobalUnlock(hDMode);
     end;
   end;
   Printer.PrinterIndex := Printer.PrinterIndex;

end;

procedure TCustomPrinter.InitPrinter(PRatio: Integer=1;APWidth: Double=171;
     APHeight: Double=78;APsize: Integer=256;ADeviceName:string='';
     Adefault:string='YES';AOffsetX:Integer=0;AOffsetY:Integer=0);
{在 (Xmm, Ymm)处按指定配置文件信息和字体输出字符串}
var
   dName: string;
   bDefault:string;//是否使用缺省打印机
   offSetX, offSetY: Integer;
   pSize: Integer;
   pWidth,pHeight: Double;
begin
   bDefault:=Adefault;
   dName:=ADeviceName;
   pSize:=APsize;
   pWidth:=APWidth;
   pHeight:=APHeight;
   offSetX:=AOffsetX;
   offSetY:=AOffsetY;
   pHeight:=pHeight*PRatio;
   FiOffsetX:=offSetX;
   FiOffsetY:=offSetY;
   if CompareText(UpperCase(bDefault),'YES')=0 then //是否使用缺省打印机
     Printer.PrinterIndex:=-1
   else if dName <>'' then
     Printer.PrinterIndex:= Printer.Printers.IndexOf(dName);
   SetPagerSize(pSize,pWidth,pHeight);
end;

procedure TCustomPrinter.InitPrinter(ConfigIni: string;PRatio: Integer=1);
{在 (Xmm, Ymm)处按指定配置文件信息和字体输出字符串}
var
   fN: string;
   inif: TIniFile;
   dName: string;
   bDefault:string;//是否使用缺省打印机
   offSetX, offSetY: Integer;
   pSize: Integer;
   pWidth,pHeight: Double;
begin
   pSize:=256;
   pWidth:=239;
   pHeight:=139.7;
   offSetX:=0;
   offSetY:=0;
   fN :=  ConfigIni;            // ExtractFilePath(Application.ExeName)+'\'+
   if FileExists(fN) then
   begin
     inif:= TIniFile.Create(fN);
     try
       try
         dName:=inif.ReadString('Printer','DeviceName','error');
         bDefault:=inif.ReadString('Printer','IsUseDefault','Yes');
         pSize:=StrToInt(inif.ReadString('Printer','PaperSize','256'));
         pWidth:=StrToFloat(inif.ReadString('Printer','PageWidth','20'));
         pHeight:=StrToFloat(inif.ReadString('Printer','PageHeight','20'));
         offSetX:= 0;
         //StrToInt(inif.ReadString('Printer','OffsetX','0'));
         offSetY:= 0;
         //StrToInt(inif.ReadString('Printer','OffsetY','0'));
       except
         bDefault:='Yes';
         pSize:=256;
         pWidth:=239;
         pHeight:=139.7;
         offSetX:=0;
         offSetY:=0;
       end;
     finally
       inif.Free;
     end;
   end;
   pHeight:=pHeight*PRatio;
   FiOffsetX:=offSetX;
   FiOffsetY:=offSetY;
   if CompareText(bDefault,'Yes')=0 then //是否使用缺省打印机
     Printer.PrinterIndex:=-1
   else
     Printer.PrinterIndex:= Printer.Printers.IndexOf(dName);
   SetPagerSize(pSize,pWidth,pHeight);
end;

//在 (Xmm, Ymm)处按指定配置文件信息和字体输出字符串
function TCustomPrinter.PrintText(Xmm, Ymm, LineHeight, TextWidth: Extended;
    Txt: string; FontSize: Integer=10; TextAlignment: Integer=DT_LEFT;
    AllowNewLine:Boolean=False): Integer;
var
   PrintRect: TRect;
   Px,Py: Integer;
   lh,tw: Extended;
   tmpTxt,prnTxt: string;
begin
   Result:=1;
   Xmm := Xmm + FiOffSetX/10;
   Ymm := Ymm + FiOffSetY/10;
   Px := Round(Round(Xmm * HPointsPerInch * 10000/25.4) / 10000);
   Py := Round(Round(Ymm * VPointsPerInch * 10000/25.4) / 10000);
   Py := Py - GetOffSetY;  //因为是绝对坐标, 因此, 不用换算成相对于Y轴坐标
   Px := Px + 2 * AvgCharWidth;
   tw:= Round(Round(textwidth * HPointsPerInch * 10000/25.4) / 10000);
   lh:= Round(Round(LineHeight * VPointsPerInch * 10000/25.4) / 10000);
   Printer.Canvas.Font.Name :='宋体'; //  Arial'
   Printer.Canvas.Font.Size := FontSize;
    //Printer.Canvas.Font.Color := clGreen;
   PrintRect.Left := Round(px);
   PrintRect.Top := Round(py);
   PrintRect.Bottom := Round(PrintRect.Top + Lh);
   PrintRect.Right := Round(PrintRect.Left +tw);
   if (Length(txt)*AvgCharWidth >tw) and AllowNewLine then
   begin
     tmpTxt:=Txt;
     while Length(tmpTxt)*AvgCharWidth >tw do
     begin
       prnTxt:=string(Copy(WideString(tmpTxt),1,Length(WideString(Copy(tmpTxt,1,Trunc(tw/AvgCharWidth))))-1));
       if not Printer.Aborted then
         DrawText(Printer.Canvas.Handle,PChar(prnTxt),Length(prnTxt),PrintRect,TextAlignment);
       tmpTxt:=' '+Copy(tmpTxt,Length(prnTxt)+1,Length(tmpTxt)-Length(prnTxt));
       Py:=PrintRect.Bottom-PrintRect.Top;
       PrintRect.Top:= PrintRect.Bottom;
       PrintRect.Bottom:= PrintRect.Bottom+py;
       Inc(Result);
     end;
     if not Printer.Aborted then
       DrawText(Printer.Canvas.Handle,PChar(tmpTxt),Length(tmpTxt),PrintRect,TextAlignment);
   end
   else if not Printer.Aborted then
     DrawText(Printer.Canvas.Handle,PChar(Txt),Length(Txt),PrintRect,TextAlignment);
end;

function TCustomPrinter.PrintText(Xmm, Ymm: Extended; Txt: string;
      FontSize: Integer=10;AllowNewLine:Boolean=False):Integer;
var
   Px, Py: Integer;
begin
   Result:=1;
   Xmm := Xmm + FiOffSetX/10;
   Ymm := Ymm + FiOffSetY/10;
   Px := Round(Round(Xmm * HPointsPerInch * 10000/25.4) / 10000);
   Py := Round(Round(Ymm * VPointsPerInch * 10000/25.4) / 10000);
   Py := Py - GetOffSetY;  //因为是绝对坐标, 因此, 不用换算成相对于Y轴坐标
   Px := Px + 2 * AvgCharWidth;
   Printer.Canvas.Font.Name := '宋体';
   Printer.Canvas.Font.Size := FontSize;
    //Printer.Canvas.Font.Color := clGreen;
   if not Printer.Aborted then
     Printer.Canvas.TextOut(Px, Py, Txt);
end;

Procedure TCustomPrinter.PrintChar(s: PChar);
var 
   tf: TextFile;
begin 
   AssignFile(tF, 'LPT1');
   Rewrite(tF);
   Write(tF,s);
   CloseFile(tF);
end;

procedure TCustomPrinter.PrintEllipse(Xmm1, Ymm1, Xmm2, Ymm2: DOUBLE;APenWidth: Integer=2);
var
   oldPen: TPen;
   Px1, Py1, Px2, Py2 : Integer;
begin
   oldPen:=TPen.Create;
   OldPen.Assign(Printer.Canvas.Pen);
   Xmm1 := Xmm1 + FiOffSetX/10;
   Ymm1 := Ymm1 + FiOffSetY/10;
   Xmm2 := Xmm2 + FiOffSetX/10;
   Ymm2 := Ymm2 + FiOffSetY/10;
   Px1 := Round(Round(Xmm1 * HPointsPerInch * 10000/25.4) / 10000);
   Py1 := Round(Round(Ymm1 * VPointsPerInch * 10000/25.4) / 10000);
   Py1 := Py1 - GetOffSetY;  //因为是绝对坐标, 因此, 不用换算成相对于Y轴坐标
   Px1 := Px1 + 2 * AvgCharWidth;
   Px2 := Round(Round(Xmm2 * HPointsPerInch * 10000/25.4) / 10000);
   Py2 := Round(Round(Ymm2 * VPointsPerInch * 10000/25.4) / 10000);
   Py2 := Py2 - GetOffSetY;  //因为是绝对坐标, 因此, 不用换算成相对于Y轴坐标
   Px2 := Px2 + 2 * AvgCharWidth;
   //  Printer.Canvas.Font.Name := '宋体';
   //  Printer.Canvas.Font.Size := 10;   // FontSize
   Printer.Canvas.Pen.Style := psSolid;
   Printer.Canvas.Pen.Width := APenWidth;
   if not Printer.Aborted then
     Printer.Canvas.Ellipse(Px1,Py1,Px2,Py2);
   Printer.Canvas.Pen.Assign(OldPen);
   OldPen.Free;
end;

procedure TCustomPrinter.PrintLine(Xmm1, Ymm1, Xmm2, Ymm2: DOUBLE;
      ACanvas: TCanvas; APenWidth: Integer=5);
var
   oldPen: TPen;
   Px1, Py1, Px2, Py2 : Integer;
begin
   oldPen:=TPen.Create;
   OldPen.Assign(ACanvas.Pen);
   Xmm1 := Xmm1 + FiOffSetX/10;
   Ymm1 := Ymm1 + FiOffSetY/10;
   Xmm2 := Xmm2 + FiOffSetX/10;
   Ymm2 := Ymm2 + FiOffSetY/10;
   Px1 := Round(Round(Xmm1 * HPointsPerInch * 10000/25.4) / 10000);
   Py1 := Round(Round(Ymm1 * VPointsPerInch * 10000/25.4) / 10000);
   Py1 := Py1 - GetOffSetY;  //因为是绝对坐标, 因此, 不用换算成相对于Y轴坐标
   Px1 := Px1 + 2 * AvgCharWidth;
   Px2 := Round(Round(Xmm2 * HPointsPerInch * 10000/25.4) / 10000);
   Py2 := Round(Round(Ymm2 * VPointsPerInch * 10000/25.4) / 10000);
   Py2 := Py2 - GetOffSetY;  //因为是绝对坐标, 因此, 不用换算成相对于Y轴坐标
   Px2 := Px2 + 2 * AvgCharWidth;
   with ACanvas do
   begin
     //Printer.Canvas.Font.Name := '宋体';
     //Printer.Canvas.Font.Size := 10;   // FontSize
     Pen.Style:= psSolid;
     Pen.Width:= APenWidth;     // APenWidth
     if not Printer.Aborted then
     begin
       MoveTo(px1,py1);
       LineTo(px2,py2);
     end;
     Pen.Assign(OldPen);
   end;
   OldPen.Free;
end;

procedure TCustomPrinter.PrintTableLine(ACanvas: TCanvas;
   APenWidth: Integer=5);
var
   cv:TCanvas;
begin
   cv:=ACanvas;
   PrintLine(0,32,170,32,cv,APenWidth); //行
   PrintLine(0,40,170,40,cv,APenWidth);
   PrintLine(0,72,170,72,cv,APenWidth);
   PrintLine(0,79,170,79,cv,APenWidth);
   PrintLine(0,32,0,79,cv,APenWidth);   //列
   PrintLine(68,32,68,72,cv,APenWidth);
   PrintLine(80,32,80,72,cv,APenWidth);
   PrintLine(102,32,102,72,cv,APenWidth);
   //PrintLine(111,32,111,72,cv,APenWidth);
   //PrintLine(122,32,122,72,cv,APenWidth);
   PrintLine(127,32,127,79,cv,APenWidth);
   PrintLine(157,32,158,79,cv,APenWidth);
   PrintLine(170,32,170,79,cv,APenWidth);
end;

procedure My_InitPrinter(ConfigIni :string);
var printer1 : TCustomPrinter;
begin
   printer1 := TCustomPrinter.Create;
   printer1.InitPrinter(ConfigIni,1);
end;
function My_PrintText(Xmm, Ymm: Extended; Txt: string;FontSize: Integer=10):Integer;
var printer1 : TCustomPrinter;
begin
   printer1 := TCustomPrinter.Create;
   result := printer1.PrintText(Xmm, Ymm, Txt,FontSize,false);
end;
end.

应用如下:
   //初始化打印机 
   My_InitPrinter(strFileName);
   //开始打印
   Printer.BeginDoc;
   //把要打印的信息放到文档中
   My_PrintText(t_X[0] ,t_Y[0] ,strDate,10);
   //结束打印
   Printer.EndDoc;