(转)打印机设置一等分、二等分、三等分打印尺寸使用教程 您所在的位置:网站首页 打印机a4尺寸怎么设置方法 (转)打印机设置一等分、二等分、三等分打印尺寸使用教程

(转)打印机设置一等分、二等分、三等分打印尺寸使用教程

2024-02-21 18:30| 来源: 网络整理| 查看: 265

前端实现打印预览功能以及page-break-inside属性解决打印换行问题(打印预览表格或文字被分割开)

崽崽的谷雨

于 2021-05-18 09:48:59 发布

2827 收藏 3分类专栏: 前端 js 文章标签: javascript版权

前端同时被 2 个专栏收录12 篇文章0 订阅订阅专栏

js45 篇文章0 订阅订阅专栏前言: 做项目的时候可能会遇到打印,不管是调用系统的(Ctrl+shift+p)或者浏览器里window.print();

打印实现方案:1.调用系统的(Ctrl+shift+p);

2.调用浏览器里window.print(); window.print() api

window.print():默认打印当前页面body里的所有内容。当然也可以打印局部。思路就是把要打印的临时赋值给body然后再重新赋值会原来的。

function doPrint2(){ //根据div标签ID拿到div中的局部内容 bdhtml=window.document.body.innerHTML; var jubuData = document.getElementById("printcontent").innerHTML; //把获取的 局部div内容赋给body标签, 相当于重置了 body里的内容 window.document.body.innerHTML= jubuData; //调用打印功能 window.print(); window.document.body.innerHTML=bdhtml;//重新给页面内容赋值; return false;}参考:window.print实现局部打印

window.onbeforeprint()--打印之前做的事 onbeforeprint api

window.onafterprint()--打印之后做的事 nafterprint api

3.实际上转换成图片再打印也行或者截图打印(当然效果不太好,对于海报之类的可能会好些可以用)这个也是一个思路建议用上面的。

例如:html2Canvas html2Cavas遇到的问题及解决方案 html2Cavas官网 api

定义和用法onbeforeprint 事件在页面即将打印时触发 (在打印窗口出现前)。

提示: onbeforeprint 事件的相反事件为 onafterprint 。

遇到的问题:打印预览的时候表格被分割了,就是一共两页而其中一行显示在不同的两个页面(而不想让tr被隔开,很难看)。如下图:

 

代码如下:

Document

tr { width: 500px; height: 500px; } table { /* width: 200px; */ border-top: 1px solid #999; border-left: 1px solid #999;

border-spacing: 0; /*去掉单元格间隙*/ }

printthis page nmae age 33 33 33 33 33 33 function func() { window.print(); }

解决方案:给tr加上age-break-inside: avoid;

tr { width: 500px; height: 500px; page-break-inside: avoid; /* page-break-before: avoid; page-break-after: avoid; */

}加上之后效果图

 

浏览器支持表格中的数字注明了完全支持该属性的首个浏览器版本。

属性 Chrome IE Firefox Safari Operapage-break-inside 1.0 8.0 19.0 1.3 7.0一、定义和用法 (page-break-inside)page-break-inside 属性设置元素内部的 page-breaking 行为。

尽管可以用 always 强制放上分页符,但是无法保证避免分页符的插入,创作人员最多只能要求用户代理尽可能避免插入分页。

应用于:position 值为 relative 或 static 的非浮动块级元素。

注释:请尽可能少地使用分页属性,并且避免在表格、浮动元素、带有边框的块元素中使用分页属性。

默认值: auto继承性: no版本: CSS2JavaScript 语法: object.style.pageBreakInside="avoid"可能的值值 描述auto 默认。如果必要则在元素内部插入分页符。avoid 避免在元素内部插入分页符。inherit 规定应该从父元素继承 page-break-inside 属性的设置。参考: w3c page-break-inside api

二、定义和用法(page-break-before)page-break-before 属性设置元素前的 page-breaking 行为。

尽管可以用 always 强制放上分页符,但是无法保证避免分页符的插入,创作人员最多只能要求用户代理尽可能避免插入分页。

应用于:position 值为 relative 或 static 的非浮动块级元素。

注释:请尽可能少地使用分页属性,并且避免在表格、浮动元素、带有边框的块元素中使用分页属性。

可能的值值 描述auto 默认值。如果必要则在元素前插入分页符。always 在元素前插入分页符。avoid 避免在元素前插入分页符。left 在元素之前足够的分页符,一直到一张空白的左页为止。right 在元素之前足够的分页符,一直到一张空白的右页为止。inherit 规定应该从父元素继承 page-break-before 属性的设置。参考: w3c page-break-before api

三、定义和用法(page-break-after)page-break-after 属性设置元素后的 page-breaking 行为。

尽管可以用 always 强制放上分页符,但是无法保证避免分页符的插入,创作人员最多只能要求用户代理尽可能避免插入分页。

应用于:position 值为 relative 或 static 的非浮动块级元素。

可能的值值 描述auto 默认。如果必要则在元素后插入分页符。always 在元素后插入分页符。avoid 避免在元素后插入分页符。left 在元素之后足够的分页符,一直到一张空白的左页为止。right 在元素之后足够的分页符,一直到一张空白的右页为止。inherit 规定应该从父元素继承 page-break-after 属性的设置。注释:请尽可能少地使用分页属性,并且避免在表格、浮动元素、带有边框的块元素中使用分页属性。

参考:w3c page-break-after api

其他用法: 这个只是其中一种用法,可以搭配另外两个属性组合成各种效果(根据自己的效果搭配)。

一、page-break-before

想要实现让h1独占一页

代码如下:

任何属性都没加

Document

h1{ text-align: center; }

printthis page ttttt

5555555555555555555

function func() { window.print(); }

解决方案:

(1)给h1加page-break-after: right;

h1{ text-align: center; page-break-after: right; }

(2)给p加 page-break-before: right;

h1{ text-align: center; /* page-break-after: right; */ } p{ page-break-before: right; }

本文部分参api考于:css-page-break 属性

vue和react中的插件vue: vue-printjs

vue-printjshttps://codechina.csdn.net/mirrors/xyl66/vueplugs_printjs?utm_source=csdn_github_accelerator vue-print.js api地址当然github上也有只是,访问很慢 github print.js api

react:react-to-print

https://codechina.csdn.net/mirrors/gregnb/react-to-print?utm_source=csdn_github_accelerator react-to-print 地址 当然github上也有只是,访问很慢github react-to-print api

当然vue,react或者其他框架里也可以事用上面的浏览器自带的方案也行 ,请根据自己的需求择优选择。这些插件都事基于window.print封装的,有些api还是很方便的。

动态调整打印机纸张大小

江苏省昆山市地方税务局

  信息管理系统中经常要提供各种打印功能,例如报表打印、凭证打印以及发票打印。在这些打印过程中所需要纸张的大小往往是不一致的,例如,打印报表有可能使用A4 纸或A3 纸,打印凭证或发票可能需要将打印纸张设置成自定义大小。如果在同一台打印机上打印这些内容,那么就应该针对不同的打印内容设置不同的纸张尺寸。显然如果用手动的方法来设置打印机的纸张尺寸是件很麻烦的事,最好的方法是让程序动态地修改打印机的纸张尺寸。

  解决问题的思路

  通过查阅API 函数技术文档可知,每个打印机都拥有唯一的一个叫做DevMode 的结构,与打印机相关的各项参数被存放在这个结构中。通过对DevMode 结构的分析,发现与设置打印机纸张大小有关的结构成员有四项:dmFields、dmPaperSize、dmPaperLength 以及dmPaperWidth。dmFields 是DevMode 的标志位初始化部分,如果要修改结构中的某些成员,那么dmFields 中相应位应被置位。dmPaperSize 表示打印机当前默认的打印纸张的大小,若要设置自定义纸张该项应为0(注,上述解释是根据微软提供的技术文档,但是在Delphi 中应将该成员设置成$100 即256)。dmPaperLength 和dmPaperWidth 只是在设置自定义大小纸张时使用,分别表示纸张的长度和宽度。如何对打印机的DevMode 结构进行修改呢?无非采用两种方法,一种是利用Delphi 提供的TPrinter 类中的某些方法,还有一种是调用与打印有关的API 函数。下面就以Delphi 为开发工具,以Epson 1600K 为默认打印机,用两种不同的方法来实现这一功能。

方法一:利用Delphi 的TPrinter 类

  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;// 如果要将当前打印机纸张变为自定义dmPaperSize 必须设置成256   pDMode^.dmPaperLength := 1140;   pDMode^.dmPaperWidth := 1900;   pDMode^.dmFields := pDMode^.dmFields orDM_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;

方法二:利用有关打印的Windows API 函数

  解决问题的思路和第一种方法类似,首先要获取当前打印机的DevMode 结构的指针,然后再对该结构进行修改,从而修改打印机纸张大小。要完成上述功能,就得调用DocumentProperties 函数。利用该函数程序就可以获取并修改与当前打印机相关的DevMode 结构中的成员。DocumentProperties 函数申明如下:

LONG DocumentProperties(  HWND    hWnd,  HANDLE   hPrinter,     LPTSTR   pDeviceName,   PDEVMODE pDevModeOutput,   PDEVMODE pDevModeInput,   DWORD   fMode);  六个参数中只有pDevModeOutput 是输出变量,其余五个参数必须由程序给出具体值。其中,hWnd 表征当前窗口的句柄值;hPrinter 表示当前打印机的句柄;pDeviceName 是对打印机设备的描述;pDevModeOutput 是指向句柄值为hPrinter 的打印机DevMode 结构的指针;pDevModeInput 是指向一个修改后的DevMode 结构的指针,该结构有待于被句柄值为hPrinter 的打印机接受;fMode 定义了该函数的具体功能,如果取值DM_IN_BUFFER 那么表示打印机接受由参数pDevModeInput 表示的由程序修改了的DevMode 值,如果取值DM_OUT_BUFFER 那么程序可以通过参数pDevModeOutput 来获取打印机的DevMode 值,如果fMode 为零,则函数返回的值表示结构DevMode 所需的字节数。承接上述例子,现在将190 *114 大小的纸张设成A4 纸。再往Form1 上放置按钮Button2,增加OnClick 事件,在Use 子句后面添加WinSpool。代码如下:

Procedure TForm1.Button2Click(Sender: TObject);var  PrnHd : THandle;  PrnInfo : PPrinterInfo1;  pcbNeeded : DWORD;  PDevModeBytes : DWORD;  DevMode: PDeviceMode;  PrnHdc : HDC;  DocInfo : PDocInfo;begin  OpenPrinter('Epson LQ -1600K',PrnHd,nil);  // 获得打印机句柄PrnHd  GetMem(PrnInfo,1024);  GetPrinter(PrnHd,1,PrnInfo,1024,@pcbNeeded);  PDevModeBytes:= DocumentProperties( Handle,PrnHd,prninfo^. pDescription,DevMode^,DevMode^,0 );{ 获取DevMode 结构所需的字节数}  GetMem(DevMode,PDevModeBytes);// 给结构DevMode 分配空间  DocumentProperties( Handle,PrnHd,PrnInfo^.p Description,DevMode^,DevMode^,DM_OUT_BUFFER );// 获取打印机的DevMode 结构  With DevMode^ do begin   dmPaperSize := DMPAPER_A4   ;// 将纸张设置成A4 纸   dmFields := dmFields or DM_PAPERSIZE;  end;  DocumentProperties( Handle,PrnHd,PrnInfo^.pDescription,DevMode^,DevMode^,DM_OUT_BUFFER or DM_IN_BUFFER);// 修改DevMode 结构。 { 下面的代码是为了测试打印机  是否按A4 纸大小来打印 }  PrnHdc := CreateDC( nil, 'Epson LQ -1600K',nil,DevMode );  GetMem( DocInfo, 100 );  With DocInfo^ do begin   cbSize := sizeof(DocInfo);   lpszDocName := nil;   lpszOutput := nil;   lpszDatatype := nil;   fwType := DI_APPBANDING;  end;  StartDoc( PrnHdc, DocInfo^);  StartPage(PrnHdc);  TextOut( PrnHdc, 10, 10, 'Hello My Friend!',17);  EndPage(PrnHdc);  EndDoc(PrnHdc);  DeleteDC(PrnHdc);  FreeMem(DocInfo);  FreeMem(PrnInfo);  FreeMem(DevMode);end;  至此,程序实现了本文开头所提出的要求。需要指出的是,上述代码是在程序运行时,动态地改变打印机纸张大小,而不改变打印机默认纸张大小。也就是说当打印程序运行结束后,打印机还是会按照默认打印纸张大小来打印、走纸。动态调整打印机纸张尺寸也是因打印机而异,某些打印机基本不支持自定义纸张,例如惠普的HP DeskJet 1120C 喷墨打印机以及众多激光打印机。因此在这些打印机上,不能实现按任意纸张大小打印。对于一些针式打印机则没有上述问题。

  上述程序是在Windows 95 环境下,用Delphi 4.0 为开发工具调试通过。 

 

 

打印自定义纸张大小 长江支流说的办法保留太多了,结果不行,很多类都是他在程序集里自定义的,源码又没公开 不过还是要感谢他的提示 今天和小陈搞了一天,他在国外的论坛上看到了一篇文章得到了启示,最后我们在凌晨3点终于把自定义纸张的代码给写出来了,看来必须用API,微软的.NET对打印的支持太菜了 现公开我们工作室实现此功能的部分代码 using System; using System.Text; using System.Runtime.InteropServices; using System.Security; using System.ComponentModel; using System.Drawing.Printing; namespace MCCustomPrintForm { /// /// 成都微创工作室(电子科技大学微创工作室) /// Tell 028-82853098 /// Email [email protected] , [email protected] /// 打印机纸张的真正自定义部分代码 /// 2006-1-2 /// public class MCCustomPrintForm { // Make a static class private MCCustomPrintForm() { } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] internal struct structPrinterDefaults { [MarshalAs(UnmanagedType.LPTStr)] public String pDatatype; public IntPtr pDevMode; [MarshalAs(UnmanagedType.I4)] public int DesiredAccess; }; [DllImport("winspool.Drv", EntryPoint="OpenPrinter", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=false,CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()] internal static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPTStr)] string printerName, out IntPtr phPrinter, ref structPrinterDefaults pd); [DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=false, CallingConvention=CallingConvention.StdCall),SuppressUnmanagedCodeSecurityAttribute()] internal static extern bool ClosePrinter(IntPtr phPrinter); [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] internal struct structSize { public Int32 width; public Int32 height; } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] internal struct structRect { public Int32 left; public Int32 top; public Int32 right; public Int32 bottom; } [StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)] internal struct FormInfo1 { [FieldOffset(0), MarshalAs(UnmanagedType.I4)] public uint Flags; [FieldOffset(4), MarshalAs(UnmanagedType.LPWStr)] public String pName; [FieldOffset(8)] public structSize Size; [FieldOffset(16)] public structRect ImageableArea; }; [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi/* changed from CharSet=CharSet.Auto */)] internal struct structDevMode { [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public String dmDeviceName; [MarshalAs(UnmanagedType.U2)] public short dmSpecVersion; [MarshalAs(UnmanagedType.U2)] public short dmDriverVersion; [MarshalAs(UnmanagedType.U2)] public short dmSize; [MarshalAs(UnmanagedType.U2)] public short dmDriverExtra; [MarshalAs(UnmanagedType.U4)] public int dmFields; [MarshalAs(UnmanagedType.I2)] public short dmOrientation; [MarshalAs(UnmanagedType.I2)] public short dmPaperSize; [MarshalAs(UnmanagedType.I2)] public short dmPaperLength; [MarshalAs(UnmanagedType.I2)] public short dmPaperWidth; [MarshalAs(UnmanagedType.I2)] public short dmScale; [MarshalAs(UnmanagedType.I2)] public short dmCopies; [MarshalAs(UnmanagedType.I2)] public short dmDefaultSource; [MarshalAs(UnmanagedType.I2)] public short dmPrintQuality; [MarshalAs(UnmanagedType.I2)] public short dmColor; [MarshalAs(UnmanagedType.I2)] public short dmDuplex; [MarshalAs(UnmanagedType.I2)] public short dmYResolution; [MarshalAs(UnmanagedType.I2)] public short dmTTOption; [MarshalAs(UnmanagedType.I2)] public short dmCollate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public String dmFormName; [MarshalAs(UnmanagedType.U2)] public short dmLogPixels; [MarshalAs(UnmanagedType.U4)] public int dmBitsPerPel; [MarshalAs(UnmanagedType.U4)] public int dmPelsWidth; [MarshalAs(UnmanagedType.U4)] public int dmPelsHeight; [MarshalAs(UnmanagedType.U4)] public int dmNup; [MarshalAs(UnmanagedType.U4)] public int dmDisplayFrequency; [MarshalAs(UnmanagedType.U4)] public int dmICMMethod; [MarshalAs(UnmanagedType.U4)] public int dmICMIntent; [MarshalAs(UnmanagedType.U4)] public int dmMediaType; [MarshalAs(UnmanagedType.U4)] public int dmDitherType; [MarshalAs(UnmanagedType.U4)] public int dmReserved1; [MarshalAs(UnmanagedType.U4)] public int dmReserved2; } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] internal struct PRINTER_INFO_9 { public IntPtr pDevMode; } [DllImport("winspool.Drv", EntryPoint="AddFormW", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()] internal static extern bool AddForm( IntPtr phPrinter, [MarshalAs(UnmanagedType.I4)] int level, ref FormInfo1 form); /* This method is not used [DllImport("winspool.Drv", EntryPoint="SetForm", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=false, CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()] internal static extern bool SetForm(IntPtr phPrinter, string paperName, [MarshalAs(UnmanagedType.I4)] int level, ref FormInfo1 form); */ [DllImport("winspool.Drv", EntryPoint="DeleteForm", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=false,CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()] internal static extern bool DeleteForm( IntPtr phPrinter, [MarshalAs(UnmanagedType.LPTStr)] string pName); [DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false, ExactSpelling=true, CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()] internal static extern Int32 GetLastError(); [DllImport("GDI32.dll", EntryPoint="CreateDC", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=false, CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()] internal static extern IntPtr CreateDC([MarshalAs(UnmanagedType.LPTStr)] string pDrive, [MarshalAs(UnmanagedType.LPTStr)] string pName, [MarshalAs(UnmanagedType.LPTStr)] string pOutput, ref structDevMode pDevMode); [DllImport("GDI32.dll", EntryPoint="ResetDC", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=false, CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()] internal static extern IntPtr ResetDC( IntPtr hDC, ref structDevMode pDevMode); [DllImport("GDI32.dll", EntryPoint="DeleteDC", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=false, CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()] internal static extern bool DeleteDC(IntPtr hDC); [DllImport("winspool.Drv", EntryPoint="SetPrinterA", SetLastError=true, CharSet=CharSet.Auto, ExactSpelling=true, CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()] internal static extern bool SetPrinter( IntPtr hPrinter, [MarshalAs(UnmanagedType.I4)] int level, IntPtr pPrinter, [MarshalAs(UnmanagedType.I4)] int command); /* LONG DocumentProperties( HWND hWnd, // handle to parent window HANDLE hPrinter, // handle to printer object LPTSTR pDeviceName, // device name PDEVMODE pDevModeOutput, // modified device mode PDEVMODE pDevModeInput, // original device mode DWORD fMode // mode options ); */ [DllImport("winspool.Drv", EntryPoint="DocumentPropertiesA", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)] public static extern int DocumentProperties( IntPtr hwnd, IntPtr hPrinter, [MarshalAs(UnmanagedType.LPStr)] string pDeviceName /* changed from String to string */, IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode ); [DllImport("winspool.Drv", EntryPoint="GetPrinterA", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)] public static extern bool GetPrinter( IntPtr hPrinter, int dwLevel /* changed type from Int32 */, IntPtr pPrinter, int dwBuf /* chagned from Int32*/, out int dwNeeded /* changed from Int32*/ ); // SendMessageTimeout tools [Flags] public enum SendMessageTimeoutFlags : uint { SMTO_NORMAL = 0x0000, SMTO_BLOCK = 0x0001, SMTO_ABORTIFHUNG = 0x0002, SMTO_NOTIMEOUTIFNOTHUNG = 0x0008 } const int WM_SETTINGCHANGE = 0x001A; const int HWND_BROADCAST = 0xffff; [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern IntPtr SendMessageTimeout( IntPtr windowHandle, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags flags, uint timeout, out IntPtr result ); //打印纸张长宽设置 public static void AddMC80MmPaperSizeToDefaultPrinter() { AddCustomPaperSizeToDefaultPrinter("MC 80mm * Receipt Length", 80.1f, 4003.9f); } public static void AddMC104MmPaperSizeToDefaultPrinter() { AddCustomPaperSizeToDefaultPrinter("MC 104mm * Receipt Length", 104.1f, 4003.9f); } /// /// Adds the printer form to the default printer /// /// Name of the printer form /// Width given in millimeters /// Height given in millimeters public static void AddCustomPaperSizeToDefaultPrinter(string paperName, float widthMm, float heightMm) { PrintDocument pd = new PrintDocument(); string sPrinterName = pd.PrinterSettings.PrinterName; AddCustomPaperSize(sPrinterName, paperName, widthMm, heightMm); } /// /// Add the printer form to a printer /// /// The printer name /// Name of the printer form /// Width given in millimeters /// Height given in millimeters public static void AddCustomPaperSize(string printerName, string paperName, float widthMm, float heightMm) { if (PlatformID.Win32NT == Environment.OSVersion.Platform) { // The code to add a custom paper size is different for Windows NT then it is // for previous versions of windows const int PRINTER_ACCESS_USE = 0x00000008; const int PRINTER_ACCESS_ADMINISTER = 0x00000004; const int FORM_PRINTER = 0x00000002; structPrinterDefaults defaults = new structPrinterDefaults(); defaults.pDatatype = null; defaults.pDevMode = IntPtr.Zero; defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE; IntPtr hPrinter = IntPtr.Zero; // Open the printer. if (OpenPrinter(printerName, out hPrinter, ref defaults)) { try { // delete the form incase it already exists DeleteForm(hPrinter, paperName); // create and initialize the FORM_INFO_1 structure FormInfo1 formInfo = new FormInfo1(); formInfo.Flags = 0; formInfo.pName = paperName; // all sizes in 1000ths of millimeters formInfo.Size.width = (int)(widthMm * 1000.0); formInfo.Size.height = (int)(heightMm * 1000.0); formInfo.ImageableArea.left = 0; formInfo.ImageableArea.right = formInfo.Size.width; formInfo.ImageableArea.top = 0; formInfo.ImageableArea.bottom = formInfo.Size.height; if (!AddForm(hPrinter, 1, ref formInfo)) { StringBuilder strBuilder = new StringBuilder(); strBuilder.AppendFormat("Failed to add the custom paper size {0} to the printer {1}, System error number: {2}", paperName, printerName, GetLastError()); throw new ApplicationException(strBuilder.ToString()); } // INIT const int DM_OUT_BUFFER = 2; const int DM_IN_BUFFER = 8; structDevMode devMode = new structDevMode(); IntPtr hPrinterInfo, hDummy; PRINTER_INFO_9 printerInfo; printerInfo.pDevMode = IntPtr.Zero; int iPrinterInfoSize, iDummyInt; // GET THE SIZE OF THE DEV_MODE BUFFER int iDevModeSize = DocumentProperties(IntPtr.Zero, hPrinter, printerName, IntPtr.Zero, IntPtr.Zero, 0); if(iDevModeSize < 0) throw new ApplicationException("Cannot get the size of the DEVMODE structure."); // ALLOCATE THE BUFFER IntPtr hDevMode = Marshal.AllocCoTaskMem(iDevModeSize + 100); // GET A POINTER TO THE DEV_MODE BUFFER int iRet = DocumentProperties(IntPtr.Zero, hPrinter, printerName, hDevMode, IntPtr.Zero, DM_OUT_BUFFER); if(iRet < 0) throw new ApplicationException("Cannot get the DEVMODE structure."); // FILL THE DEV_MODE STRUCTURE devMode = (structDevMode)Marshal.PtrToStructure(hDevMode, devMode.GetType()); // SET THE FORM NAME FIELDS TO INDICATE THAT THIS FIELD WILL BE MODIFIED devMode.dmFields = 0x10000; // DM_FORMNAME // SET THE FORM NAME devMode.dmFormName = paperName; // PUT THE DEV_MODE STRUCTURE BACK INTO THE POINTER Marshal.StructureToPtr(devMode, hDevMode, true); // MERGE THE NEW CHAGES WITH THE OLD iRet = DocumentProperties(IntPtr.Zero, hPrinter, printerName, printerInfo.pDevMode, printerInfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER); if(iRet < 0) throw new ApplicationException("Unable to set the orientation setting for this printer."); // GET THE PRINTER INFO SIZE GetPrinter(hPrinter, 9, IntPtr.Zero, 0, out iPrinterInfoSize); if(iPrinterInfoSize == 0) throw new ApplicationException("GetPrinter failed. Couldn't get the # bytes needed for shared PRINTER_INFO_9 structure"); // ALLOCATE THE BUFFER hPrinterInfo = Marshal.AllocCoTaskMem(iPrinterInfoSize + 100); // GET A POINTER TO THE PRINTER INFO BUFFER bool bSuccess = GetPrinter(hPrinter, 9, hPrinterInfo, iPrinterInfoSize, out iDummyInt); if(!bSuccess) throw new ApplicationException("GetPrinter failed. Couldn't get the shared PRINTER_INFO_9 structure"); // FILL THE PRINTER INFO STRUCTURE printerInfo = (PRINTER_INFO_9)Marshal.PtrToStructure(hPrinterInfo, printerInfo.GetType()); printerInfo.pDevMode = hDevMode; // GET A POINTER TO THE PRINTER INFO STRUCTURE Marshal.StructureToPtr(printerInfo, hPrinterInfo, true); // SET THE PRINTER SETTINGS bSuccess = SetPrinter(hPrinter, 9, hPrinterInfo, 0); if(!bSuccess) throw new Win32Exception(Marshal.GetLastWin32Error(), "SetPrinter() failed. Couldn't set the printer settings"); // Tell all open programs that this change occurred. SendMessageTimeout( new IntPtr(HWND_BROADCAST), WM_SETTINGCHANGE, IntPtr.Zero, IntPtr.Zero, MCCustomPrintForm.SendMessageTimeoutFlags.SMTO_NORMAL, 1000, out hDummy); } finally { ClosePrinter(hPrinter); } } else { StringBuilder strBuilder = new StringBuilder(); strBuilder.AppendFormat("Failed to open the {0} printer, System error number: {1}", printerName, GetLastError()); throw new ApplicationException(strBuilder.ToString()); } } else { structDevMode pDevMode = new structDevMode(); IntPtr hDC = CreateDC(null, printerName, null, ref pDevMode); if (hDC != IntPtr.Zero) { const long DM_PAPERSIZE = 0x00000002L; const long DM_PAPERLENGTH = 0x00000004L; const long DM_PAPERWIDTH = 0x00000008L; pDevMode.dmFields = (int)(DM_PAPERSIZE | DM_PAPERWIDTH | DM_PAPERLENGTH); pDevMode.dmPaperSize = 256; pDevMode.dmPaperWidth = (short)(widthMm * 1000.0); pDevMode.dmPaperLength = (short)(heightMm * 1000.0); ResetDC(hDC, ref pDevMode); DeleteDC(hDC); } } } } }

 

C# PrintDocument打印 多页 打印预览  

PrintDocument实例所有的订阅事件如下:

1.创建一个PrintDocument的实例.如下:System.Drawing.Printing.PrintDocument docToPrint =   new System.Drawing.Printing.PrintDocument();2.设置打印机开始打印的事件处理函数.函数原形如下:void docToPrint_PrintPage(object sender,   System.Drawing.Printing.PrintPageEventArgs e)3.将事件处理函数添加到PrintDocument的PrintPage事件中。docToPrint.PrintPage+=new PrintPageEventHandler(docToPrint_PrintPage);4.设置PrintDocument的相关属性,如:PrintDialog1.AllowSomePages = true;PrintDialog1.ShowHelp = true;5.把PrintDialog的Document属性设为上面配置好的PrintDocument的实例:PrintDialog1.Document = docToPrint;6.调用PrintDialog的ShowDialog函数显示打印对话框:DialogResult result = PrintDialog1.ShowDialog();7.根据用户的选择,开始打印:if (result==DialogResult.OK)   {    docToPrint.Print();   }8.打印预览控件PrintPreviewDialog例子如下:

使用时先创建PrintService类的实例,然后调用void StartPrint(Stream streamToPrint,string streamType)函数开始打印。其中streamToPrint是要打印的内容(字节流),streamType是流的类型(txt表示普通文本,image表示图像);

 

public partial class PrintTxt 

 

{

 

      private   PrintPreviewDialog PrintPreview = new PrintPreviewDialog();

 

      private   string    StreamType;

 

      private   Image image = null;

 

      private   Stream StreamToPrint = null;

 

      Font mainFont = new Font("宋体", 12);//打印的字体

 

      public string Filename =null;

 

        

 

        

 

    //1、实例化打印文档

 

    PrintDocument pdDocument = new PrintDocument();

 

    private string[] lines;

 

    private int linesPrinted;

 

 

 

 

 

    public PrintTxt(string filepath,string filetype)

 

    {

 

          

 

 

 

         Filename = Path.GetFileNameWithoutExtension(filepath);

 

 

 

        //订阅BeginPrint事件

 

        pdDocument.BeginPrint += new PrintEventHandler(pdDocument_BeginPrint);

 

        //訂閱EndPrint事件,释放资源

 

       

 

          

 

        pdDocument.PrintPage += new PrintPageEventHandler(OnPrintPage);

 

 

 

 

 

        //订阅Print打印事件,该方法必须放在订阅打印事件的最后

 

        FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);

 

        StartPrint(fs, filetype);

 

 

 

 

 

        //打印结束

 

        pdDocument.EndPrint += new PrintEventHandler(pdDocument_EndPrint);

 

 

 

 

 

 

 

    } //2、启动Print打印方法     public   void StartPrint(Stream streamToPrint, string streamType)     {           //返回值的PageSettings A4\A5         PageSettings ps = new PageSettings();          //显示设置打印页对话框      PageSetupDialog Psdl = new PageSetupDialog();           //打印多份设置,注意,该方法需放在printpage方法后面。      PrintDialog pt = new PrintDialog();         pt.AllowCurrentPage = true;         pt.AllowSomePages = true;         pt.AllowPrintToFile = true;            StreamToPrint = streamToPrint;//打印的字节流      StreamType = streamType; //打印的类型      pdDocument.DocumentName = Filename; //打印的文件名        Psdl.Document = pdDocument;         PrintPreview.Document = pdDocument;         pt.Document = pdDocument;           Psdl.PageSettings = pdDocument.DefaultPageSettings;         try         {             //显示对话框               if (Psdl.ShowDialog() == DialogResult.OK)             {                 ps = Psdl.PageSettings;                 pdDocument.DefaultPageSettings = Psdl.PageSettings;             }               if (pt.ShowDialog() == DialogResult.OK)             {                 pdDocument.PrinterSettings.Copies = pt.PrinterSettings.Copies;                 pdDocument.Print();             }            if(PrintPreview.ShowDialog()==DialogResult.OK )             //调用打印               pdDocument.Print();                               * PrintDocument对象的Print()方法在PrintController类中执行PrintPage事件。              */         }         catch (InvalidPrinterException ex)         {             MessageBox.Show(ex.Message, "Simple Editor", MessageBoxButtons.OK, MessageBoxIcon.Error);             throw;         }     }   ///     /// 3、得到打印內容     /// 每个打印任务只调用OnBeginPrint()一次。     ///     ///     ///     void pdDocument_BeginPrint(object sender, PrintEventArgs e)     {         char[] param = { '\n' };         char[] trimParam = { '\r' };//回车           switch (StreamType)         {             case "txt":                 StringBuilder text = new StringBuilder();                 System.IO.StreamReader streamReader = new StreamReader(StreamToPrint, Encoding.Default);                 while (streamReader.Peek() >= 0)                 {                     lines = streamReader.ReadToEnd().Split(param);                     for (int i = 0; i < lines.Length; i++)                     {                         lines[i] = lines[i].TrimEnd(trimParam);                     }                 }                   break;             case "image":                 image = System.Drawing.Image.FromStream(StreamToPrint);                 break;             default:                 break;         }       }           ///     /// 4、绘制多个打印界面     /// printDocument的PrintPage事件     ///     ///     ///     private void OnPrintPage(object sender, PrintPageEventArgs e)     {         int leftMargin = Convert.ToInt32((e.MarginBounds.Left) * 3 / 4);  //左边距         int topMargin = Convert.ToInt32(e.MarginBounds.Top * 2 / 3);    //顶边距         switch (StreamType)         {             case "txt":                 while (linesPrinted < lines.Length)                 {                     //向画布中填写内容                     e.Graphics.DrawString(lines[linesPrinted++], new Font("Arial", 10), Brushes.Black, leftMargin, topMargin, new StringFormat());                       topMargin += 55;//行高为55,可调整                       //走纸换页                     if (topMargin >= e.PageBounds.Height - 60)//页面累加的高度大于页面高度。根据自己需要,可以适当调整                     {                         //如果大于设定的高                         e.HasMorePages = true;                            /*                          * PrintPageEventArgs类的HaeMorePages属性为True时,通知控件器,必须再次調用OnPrintPage()方法,打印一个页面。                          * PrintLoopI()有一个用於每个要打印的页面的序例。如果HasMorePages是False,PrintLoop()就会停止。                          */                         return;                     }                 }                   break;             case "image"://一下涉及剪切图片,                 int width = image.Width;                 int height = image.Height;                 if ((width / e.MarginBounds.Width) > (height / e.MarginBounds.Height))                 {                     width = e.MarginBounds.Width;                     height = image.Height * e.MarginBounds.Width / image.Width;                 }                 else                 {                     height = e.MarginBounds.Height;                     width = image.Width * e.MarginBounds.Height / image.Height;                 }                                    System.Drawing.Rectangle destRect = new System.Drawing.Rectangle(topMargin, leftMargin, width, height);                 //向画布写入图片                 for (int i = 0; i < Convert.ToInt32(Math.Floor((double)image.Height/ 820)) + 1; i++)                 {                                           e.Graphics.DrawImage(image, destRect, i*820,i*1170 , image.Width, image.Height, System.Drawing.GraphicsUnit.Pixel);                     //走纸换页                     if (i * 1170 >= e.PageBounds.Height - 60)//页面累加的高度大于页面高度。根据自己需要,可以适当调整                     {                         //如果大于设定的高                         e.HasMorePages = true;                           /*                         * PrintPageEventArgs类的HaeMorePages属性为True时,通知控件器,必须再次調用OnPrintPage()方法,打印一个页面。                         * PrintLoopI()有一个用於每个要打印的页面的序例。如果HasMorePages是False,PrintLoop()就会停止。                         */                         return;                     }                 }                                break;         }           //打印完毕后,画线条,且注明打印日期         e.Graphics.DrawLine(new Pen(Color.Black), leftMargin, topMargin, e.MarginBounds.Right, topMargin);            string strdatetime = DateTime.Now.ToLongDateString() + DateTime.Now.ToLongTimeString();         e.Graphics.DrawString(string.Format("打印时间:{0}", strdatetime), mainFont, Brushes.Black, e.MarginBounds.Right-240, topMargin+40, new StringFormat());         linesPrinted = 0;         //绘制完成后,关闭多页打印功能         e.HasMorePages = false;       } ///        ///5、EndPrint事件,释放资源     ///     ///     ///     void pdDocument_EndPrint(object sender, PrintEventArgs e)     {           //变量Lines占用和引用的字符串数组,现在释放         lines = null;     }       } //PrintTxt simple = new PrintTxt("D:\\Mainsoft\\12.txt", "txt");

C#学习笔记之PrintDocument打印

秋忆夏伤

于 2016-05-30 15:26:56 发布

8703 收藏 18分类专栏: C#学习笔记版权

C#学习笔记专栏收录该内容54 篇文章0 订阅订阅专栏using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Drawing.Printing;using System.Linq;using System.Management;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;

namespace PrintDocument控件{ public partial class Form1 : Form { public Form1() { InitializeComponent(); }

/// /// PrintDocument:用于打印最重要的类,几乎所有的打印类都与这个类有关系。 ///

// 1、打印页面设置 private void btnSetting_Click(object sender, EventArgs e) { // 打印页面设置对话框 PageSetupDialog page = new PageSetupDialog();

page.Document = printDocument1; page.AllowMargins = true; page.AllowOrientation = true; page.AllowPaper = true; page.AllowPrinter = true; page.ShowHelp = true; if (page.ShowDialog() == DialogResult.OK) { // 将设置好的打印页 用作 PrintDocument进行打印。 printDocument1.DefaultPageSettings = page.PageSettings; } }

// 2、打印机设置 private void btnPrint_Click(object sender, EventArgs e) { // 打印机设置对话框 PrintDialog print = new PrintDialog();

print.Document = printDocument1; print.AllowCurrentPage = true; print.AllowPrintToFile = true; print.AllowSelection = true; print.AllowSomePages = true; print.ShowHelp = true; if (print.ShowDialog() == DialogResult.OK) { // 将设置好的打印机 用作 PrinDocument进行打印。 printDocument1.PrinterSettings = print.PrinterSettings; } }

// 3、打印预览 private void btnPreview_Click(object sender, EventArgs e) { if (MessageBox.Show("是否要预览打印文件?", "打印预览", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK) { // 设置要预览的文档 printPreviewDialog1.Document = printDocument1; // 开启操作系统的抗锯齿功能 printPreviewDialog1.UseAntiAlias = true;

// 打开预览窗口 if (printPreviewDialog1.ShowDialog() == DialogResult.OK) { // 如果选择的是系统默认打印机,点击“打印”按钮之后,会跳出“文件另存为”窗口; // 如果选择别的打印机,点击“打印”之后,会直接打印,不会返回“OK”。 MessageBox.Show("开始打印"); } else { MessageBox.Show("关闭预览"); } } }

// 4、开始打印 private void btnStart_Click(object sender, EventArgs e) { // PrintController:控制一个PrintDocument是如何打印的。 PrintController printController = new StandardPrintController(); printDocument1.PrintController = printController; printDocument1.DocumentName = "社保样卡"; printDocument1.PrinterSettings.PrinterName = "XID8600 U1"; printDocument1.Print(); // 触发Print_Page事件。 }

// PrintDocument 三个事件中的第二个参数 e 有如下属性: // e.Cancel:设置为true,将取消这次打印作业。 // e.Griphics:所使用打印机的设备环境。 // e.HasMorePages:PrintPage事件打印一页后,如果仍有数据未打印,退出事件前设置 // HasMorePages=true;退出事件之后将再次出发PrintPage事件,打印下一页。 // e.MarginBounds:打印区域的大小,是Rectangle结构,元素包括左上角坐标(Left和Top), // 宽和高(Width和Height),单位为1/100英寸。 // e.PageSettings:PageSettings类对象,包含用对话框PageSetupDialog设置的页面打印方式的 // 全部信息,

// 在调用 Print 方法后,在打印文档的第一页之前发生。 private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e) { }

// 需要打印新的一页时发生,负责打印一页所需要的数据 // 打印预览会调用该事件,预览的内容就是此处设置好的内容。 private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { Image iamge = Image.FromFile(@"D:\photo\test.jpg");

e.Graphics.DrawString("社保卡样卡", new Font("黑体", 35), Brushes.Black, new Point(400, 120));

e.Graphics.DrawString("姓名 张三", new Font("黑体", 25), Brushes.Black, new Point(480, 270)); e.Graphics.DrawString("社会保障号码 32032032302030230", new Font("黑体", 25), Brushes.Black, new Point(480, 360)); e.Graphics.DrawString("社会保障卡号 JS2018098", new Font("黑体", 25), Brushes.Black, new Point(480, 450)); e.Graphics.DrawString("制卡日期 2016年5月", new Font("黑体", 25), Brushes.Black, new Point(480, 540)); e.Graphics.DrawImage(iamge, new Point(100, 240)); }

// 在打印完最后一页文档时发生。 private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e) { }

/// /// 打印机状态值 /// public enum PrinterStatus { 其他状态 = 1, 未知, 空闲, 正在打印, 预热, 停止打印, 打印中, 离线 }

// 获取指定打印机的状态 private void btnState_Click(object sender, EventArgs e) { string strPrinter = "win32_printer.DeviceId='XID8300 U1'";

// 用指定的打印机实例化一个打印机对象。 ManagementObject printer = new ManagementObject(strPrinter);

// 获取打印机信息。 printer.Get();

// 获取打印机状态属性 string str = printer.Properties["PrinterStatus"].Value.ToString(); textBox1.Text = str; }

// 获取本地所有打印机信息 private void button1_Click(object sender, EventArgs e) { string strPrinter = "win32_printer";

// 获取本地所有打印机 ManagementClass mc = new ManagementClass(strPrinter);

// 获取所有打印机实例的集合 ManagementObjectCollection moc = mc.GetInstances();

// 遍历本地所有打印机 foreach (ManagementObject printer in moc) { // 打印机名字 string strName = printer.Properties["DeviceId"].Value.ToString(); // 打印机状态 string strState = printer.Properties["PrinterStatus"].Value.ToString(); comboBox1.Items.Add(strName); } } }}

秋忆夏伤关注

————————————————版权声明:本文为CSDN博主「秋忆夏伤」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_29331365/article/details/51538369



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有