zoukankan      html  css  js  c++  java
  • 使用PrintDocument定制打印格式

    虽然说使在IE上直接调用打印插件打印已经不常用,但是有时候还是会用到,这里就记录一下。

    首先我们列出来我们的打印类

      1     public class PrintService
      2     {
      3         //打印机名称
      4         private static readonly string _printerName = "";
      5         //业务名称
      6         private static string _printStr = "";
      7 
      8         /// <summary>
      9         /// 打印
     10         /// </summary>
     11         /// <param name="printStr"></param>
     12         /// <returns>0:success;1:未找到打印机;2:fail</returns>
     13         public static int PrintNo(string printStr)
     14         {
     15             try
     16             {
     17                 _printStr = printStr;
     18                 PrintDocument pd = new PrintDocument();
     19                 //取消打印弹窗(PrintDocment默认的PrintController 是PrintControllerWithStatusDialog)
     20                 pd.PrintController = new StandardPrintController();
     21                 //pd.PrinterSettings.PrinterName = "打印机的名字";
     22                 //打印机名称可以不配置,取默认打印机
     23                 pd.DocumentName = string.Format("取号{0:yyyyMMddHHmmss}", DateTime.Now);
     24                 pd.OriginAtMargins = true;
     25                 pd.DefaultPageSettings.Margins = new Margins(0, 0, 0, 20);
     26                 //打印开始前
     27                 pd.BeginPrint += new PrintEventHandler(pd_BeginPrint);
     28                 //打印输出(过程)
     29                 pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
     30                 //打印结束
     31                 pd.EndPrint += new PrintEventHandler(pd_EndPrint);
     32                 pd.Print();
     33 
     34                 return 0;
     35             }
     36             catch (Exception ex)
     37             {
     38                 NLog.Error(ex.ToString());
     39                 return 2;
     40             }
     41         }
     42 
     43         private static void pd_EndPrint(object sender, PrintEventArgs e)
     44         {
     45             //打印结束后相关操作
     46         }
     47 
     48         private static void pd_PrintPage(object sender, PrintPageEventArgs e)
     49         {
     50             try
     51             {
     52                 int pagewidth = e.MarginBounds.Width;
     53                 float y = 0;
     54                 _title = _title ?? string.Empty;
     55                 int titlerowspan = (_title.Length / 11) + 1;
     56                 y = CreateRectangleF(0, y, pagewidth, e.Graphics.MeasureString("-", new Font("微软雅黑", 14, FontStyle.Bold)).Height, "------------------------------------", new Font("微软雅黑", 14, FontStyle.Bold), e);
     57                 y = CreateRectangleF(0, y, pagewidth, e.Graphics.MeasureString("中A1", new Font("宋体", 11, FontStyle.Bold)).Height, _printStr, new Font("宋体", 11, FontStyle.Bold), e);
     58             }
     59             catch (InvalidPrinterException ex)
     60             {
     61                 return;
     62             }
     63         }
     64 
     65         private static void pd_BeginPrint(object sender, PrintEventArgs e)
     66         {
     67             //也可以把一些打印的参数放在此处设置;
     68         }
     69 
     70         /// <summary>
     71         /// 绘制一个矩形区域文本文字
     72         /// </summary>
     73         private static float CreateRectangleF(float x, float y, float width, float height, string str, Font font, PrintPageEventArgs e)
     74         {
     75             StringFormat sf = new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center };
     76             //RectangleF rect = new RectangleF(x, y, width, height);
     77             var size = MeasureStringExtend(e.Graphics, str, font, (int)width);
     78             RectangleF rect = new RectangleF(x,y,size.Width, size.Height);
     79             e.Graphics.DrawString(str, font, System.Drawing.Brushes.Black, rect, sf);
     80             return rect.Bottom;
     81         }
     82         //多行文本自动换行
     83         public static SizeF MeasureStringExtend(Graphics g, string text, Font font, int desWidth)
     84         {
     85             string tempString = text;
     86             string workString = "";//当前打印的文本
     87             int npos = 1;//文字个数
     88             int sp_pos = 0;//
     89             int line = 0;//所在行数
     90             int nWidth = 0;
     91 
     92             //获取文字的Size对象
     93             SizeF size = g.MeasureString(text, font);
     94             //多行文本:文本的宽度大于纸张的宽度
     95             if (size.Width > desWidth)
     96             {
     97                 while (tempString.Length > 0)
     98                 {
     99                     //判断最后一行
    100                     if (npos > tempString.Length)
    101                     {
    102                         line++;
    103                         break;
    104                     }
    105                     //截取npos个文字,用于检测是否超出纸张宽度
    106                     workString = tempString.Substring(0, npos);
    107                     //获取当前文本的宽度
    108                     nWidth = (int)g.MeasureString(workString, font).Width;
    109                     //仍然大于纸张宽度
    110                     if (nWidth > desWidth)
    111                     {
    112                         //最后一个空格的位置
    113                         sp_pos = workString.LastIndexOf(" ");
    114                         if (sp_pos > 0)
    115                         {
    116                             //从空格后一个字符作为起点,继续循环,可用于去除空格。这里并没有这么做。
    117                             tempString = tempString.Substring((sp_pos + 1), tempString.Length - (sp_pos + 1));
    118                             line++;
    119                             npos = 0;
    120                         }
    121                         else //没有空格
    122                         {
    123                             tempString = tempString.Substring(npos, tempString.Length - npos);
    124                             line++;
    125                             npos = 0;
    126                         }
    127                     }
    128                     npos++;
    129                 }
    130                 return new SizeF(desWidth, (line * size.Height));
    131             }
    132             else
    133                 return size;
    134 
    135         }
    136     }
    View Code

    调用的时候

    PrintSrivce.PrintNo(“这里是打印的文字内容,可以写很多,它会自动换行哦”);

    为了做成Acivex插件,所以这里我们这么做:

    1     [Guid("F83174A0-087D-4634-B6AE-0094CD392FD1")]//IE浏览器通过这个GUID可以查到打印方法,调用打印方法,打印。
    2     public class PrinterHelper:ActiveXControl
    3     {
    4         public int Printing(string printStr)
    5         {
    6             return PrintService.PrintNo(printStr);
    7         }
    8     }

    下面是打印的HTML页面

    <object id="printer-ActiveX" classid="clsid:F83174A0-087D-4634-B6AE-0094CD392FD1" codebase="Printer.CAB#version=1,0,0" style="display: none;"></object>
    1 var printerActiveX = document.getElementById('printer-ActiveX');
    2 printerActiveX.Printing('这里是打印的文字内容,可以写很多,它会自动换行哦');

    为什么这样就可以打印了呢?

    其实之前省略了如何制作Acivex的步骤,下面介绍一下:

    一、IObjectSafety接口

    为了让ActiveX控件获得客户端的信任,控件类还需要实现一个名为“IObjectSafety”的接口。先创建该接口(注意,不能修改该接口的GUID值),接口内容如下:

     1     ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
     2     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
     3     public interface IObjectSafety
     4     {
     5         [PreserveSig]
     6         int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
     7 
     8         [PreserveSig()]
     9         int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
    10     }

    二、ActiveXControl控件基类

     1     public abstract class ActiveXControl : IObjectSafety
     2     {
     3         #region IObjectSafety 成员
     4 
     5         private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
     6         private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
     7         private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
     8         private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
     9         private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";
    10 
    11         private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
    12         private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
    13         private const int S_OK = 0;
    14         private const int E_FAIL = unchecked((int)0x80004005);
    15         private const int E_NOINTERFACE = unchecked((int)0x80004002);
    16 
    17         private bool _fSafeForScripting = true;
    18         private bool _fSafeForInitializing = true;
    19 
    20 
    21         public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
    22         {
    23             int Rslt = E_FAIL;
    24 
    25             string strGUID = riid.ToString("B");
    26             pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
    27             switch (strGUID)
    28             {
    29                 case _IID_IDispatch:
    30                 case _IID_IDispatchEx:
    31                     Rslt = S_OK;
    32                     pdwEnabledOptions = 0;
    33                     if (_fSafeForScripting == true)
    34                         pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
    35                     break;
    36                 case _IID_IPersistStorage:
    37                 case _IID_IPersistStream:
    38                 case _IID_IPersistPropertyBag:
    39                     Rslt = S_OK;
    40                     pdwEnabledOptions = 0;
    41                     if (_fSafeForInitializing == true)
    42                         pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
    43                     break;
    44                 default:
    45                     Rslt = E_NOINTERFACE;
    46                     break;
    47             }
    48 
    49             return Rslt;
    50         }
    51 
    52         public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
    53         {
    54             int Rslt = E_FAIL;
    55 
    56             string strGUID = riid.ToString("B");
    57             switch (strGUID)
    58             {
    59                 case _IID_IDispatch:
    60                 case _IID_IDispatchEx:
    61                     if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) &&
    62                             (_fSafeForScripting == true))
    63                         Rslt = S_OK;
    64                     break;
    65                 case _IID_IPersistStorage:
    66                 case _IID_IPersistStream:
    67                 case _IID_IPersistPropertyBag:
    68                     if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) &&
    69                             (_fSafeForInitializing == true))
    70                         Rslt = S_OK;
    71                     break;
    72                 default:
    73                     Rslt = E_NOINTERFACE;
    74                     break;
    75             }
    76 
    77             return Rslt;
    78         }
    79 
    80         #endregion
    81     }
    View Code

     三、就是我们上面写的PrinterHelper类,并在这个类库的属性里设置“使程序集COM可见”。

    四、使用VS2012发布

    具体步骤如下:

    1、

     2、

     

     3、

     

    1)设置为简体中文,否则安装路径有中文的话就会出问题
    2)设置默认安装路径
    3)修改默认字体
    4)每次升级,重新打包,只需要点击这一行右侧的“...”按钮,就会重新生成Code,安装时就会自动覆盖老版本
    5)我们把INSTALLDIR里面改写为[ProgramFilesFolder],方便后面我们使用CAB打包
    4、

     

    5、这一步很重要,在主输出上点右键属性

    6、点击“6 Prepare for Release”下方的Release

     注意点:该解决方案需要以管理员身份运行。

    生成两个文件:

    PrinterActiveX.MSI和Data1.cab

    剩下一步就是签名了。

    makecab.exe   /f   "cab.ddf"
    signtool sign -f mantishell.pfx -p mantishell PrinterActiveX.CAB
    .OPTION   EXPLICIT
    .Set Cabinet=on
    .Set Compress=on
    .Set MaxDiskSize=CDROM
    .Set ReservePerCabinetSize=6144
    .Set DiskDirectoryTemplate="."
    .Set CompressionType=MSZIP
    .Set CompressionLevel=7
    .Set CompressionMemory=21
    .Set CabinetNameTemplate="PrinterActiveX.CAB"
    "installer.inf"
    "PrinterActiveX.MSI"
    "Data1.cab"

    1、生成公钥文件
    makecert -# 01 -r -n "CN=xxxx公司,O=xxxx,OU=xxxx,C=China,S=NanJing" -e 08/07/2019 -sky signature -sv mantishell.pvk d:mantishell.cer
    -e表示截至时间:如果去掉截至时间到2039年
    私钥密码设置为:mantishell
    2、生成证书
    pvk2pfx.exe /pvk mantishell.pvk /pi mantishell /spc mantishell.cer /pfx mantishell.pfx /f

    makecert -# 01 -r -n "CN=xxxx公司,O=xxxx公司,OU=xxxx公司,C=China,S=Nanjing" -sky signature -sv d:ActiveXCABmantishell.pvk d:ActiveXPrinterActiveXCABmantishell.cer


  • 相关阅读:
    卡特兰数
    hdu 1023 Train Problem II
    hdu 1022 Train Problem
    hdu 1021 Fibonacci Again 找规律
    java大数模板
    gcd
    object dection资源
    Rich feature hierarchies for accurate object detection and semantic segmentation(RCNN)
    softmax sigmoid
    凸优化
  • 原文地址:https://www.cnblogs.com/mantishell/p/11019725.html
Copyright © 2011-2022 走看看