自定义一个控制打印机的单元

    技术2022-05-11  142

    自定义一个控制打印机的单元unit My_Print;interfaceuses  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;implementationconstructor 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;  


    最新回复(0)