当前位置 博文首页 > 畅饮无绪:Web打印插件实现思路(C#/Winform)

    畅饮无绪:Web打印插件实现思路(C#/Winform)

    作者:畅饮无绪 时间:2021-06-15 18:23

    最近,客户有个需求过来,Web端无预览打印,美其名曰:快捷打印。

    当时第一反应就是找插件,拿来主义永远不过时。找了一圈发现,免费的有限制,没限制的需要收费(LODOP真的好用)。说来就是一个简单的无预览打印,收费的诸多功能都无用武之地,总的来说性价比很低,所以就打算自己琢磨着写一个算了。刚开始总是纠结在Web端去实现直接打印,打印是实现了,结果是服务端的,客户端只能一脸懵。

    后来(准备妥协了),安装了一些收费的插件发现,都需要先安装一个客户端程序,灵光乍现,解决方案这不就出来了。

    思路:Web端调用客户端程序,让客户端程序去实现打印。

    实现:Web端通过WebSocket将Html发送给客户端,客户端(Winform)监听消息,接收处理后再打印。

    客户端(Winform)打印实现方式:

    1、Html转PDF,然后打印PDF(暂时需要用到三方包)

    2、Html转图片,然后通过PrintDocument打印图片

    3、通过WebBrowser实现打印

     

    按照上面的思路再去写代码,就会简单很多。

    Web端的代码就不多说了,一个简单的WebSocket通信。

    客户端程序(Winform)

    1、监听Web端的WebSocket消息,这里有用到三方包:Fleck,开箱即用,非常方便。

     1         /// <summary>
     2         /// ConnAndListen
     3         /// </summary>
     4         public static void ConnAndListen()
     5         { 7             // 监听本地 45000端口
     8             var server = new WebSocketServer($"ws://127.0.0.1:45000");
     9             server.Start(socket =>
    10             {
    11                 socket.OnOpen = () =>
    12                 {
    13                     // 连接成功
    14                     socket.Send("socket通讯已连接");
    15                 };
    16                 socket.OnClose = () =>
    17                 {
    18                     // 关闭连接
    19                     socket.Send("socket通讯已关闭连接");
    20                     socket.Close();
    21                 };
    22                 socket.OnMessage = message =>
    23                 {
    24                     // TODO...
    25                 };
    26             });
    27         }

    2、处理Html,将Html转换为图片:

     1         /// <summary>
     2         /// GetBitmap
     3         /// </summary>
     4         /// <returns></returns>
     5         public Bitmap GetBitmap()
     6         {
     7             WebPageBitmap Shot = new WebPageBitmap("html", "页面宽度", "页面高度");
     8             Shot.GetIt();
     9             Bitmap Pic = Shot.DrawBitmap("图片高度", "图片宽度");
    10             // 设置图片分辨率
    11             Pic.SetResolution(203.0F, 203.0F);
    12             return Pic;
    13         }   

    3、打印图片

      1     /// <summary>
      2     /// 图片打印
      3     /// </summary>
      4     public class PrintDirectClass
      5     {
      6         private PaperSize paperSize = null;
      7         // 多页打印
      8         private int printNum = 0;
      9         // 单个图片文件
     10         private string imageFile = ".....";
     11         // 多个图片文件
     12         private ArrayList imageList = new ArrayList();
     13 
     14         /// <summary>
     15         /// 打印预览
     16         /// </summary>
     17         public void PrintPreview()
     18         {
     19             // 打印机对象
     20             PrintDocument imgToPrint = new PrintDocument();
     21 
     22             #region 打印机相关设置
     23             var pageSize = imgToPrint.PrinterSettings.PaperSizes;
     24             paperSize = pageSize[pageSize.Count - 1];
     25 
     26             // 打印方向设置
     27             //imgToPrint.DefaultPageSettings.Landscape = false;
     28             // 打印纸张大小设置
     29             //imgToPrint.DefaultPageSettings.PaperSize = paperSize;
     30             // 打印分辨率设置
     31             //imgToPrint.DefaultPageSettings.PrinterResolution.Kind = PrinterResolutionKind.High;
     32             // 打印边距设置
     33             //imgToPrint.DefaultPageSettings.Margins = new Margins(40, 40, 40, 40);
     34 
     35             // 打印开始事件
     36             imgToPrint.BeginPrint += new PrintEventHandler(this.imgToPrint_BeginPrint);
     37             // 打印结束事件
     38             imgToPrint.EndPrint += new PrintEventHandler(this.imgToPrint_EndPrint);
     39             // 打印内容设置
     40             imgToPrint.PrintPage += new PrintPageEventHandler(this.imgToPrint_PrintPage);
     41             #endregion
     42 
     43             // 直接打印
     44             //imgToPrint.Print();
     45 
     46             // 打印弹框确认
     47             //PrintDialog printDialog = new PrintDialog();
     48             //printDialog.AllowSomePages = true;
     49             //printDialog.ShowHelp = true;
     50             //printDialog.Document = imgToPrint;
     51             //if (printDialog.ShowDialog() == DialogResult.OK)
     52             //{
     53             //    imgToPrint.Print();
     54             //}
     55 
     56             // 预览打印
     57             //PrintPreviewDialog pvDialog = new PrintPreviewDialog();
     58             //pvDialog.Document = imgToPrint;
     59             //pvDialog.ShowDialog();
     60         }
     61 
     62         /// <summary>
     63         /// 打印开始事件
     64         /// </summary>
     65         /// <param name="sender"></param>
     66         /// <param name="e"></param>
     67         private void imgToPrint_BeginPrint(object sender, PrintEventArgs e)
     68         {
     69             if (imageList.Count == 0)
     70                 imageList.Add(imageFile);
     71         }
     72 
     73         /// <summary>
     74         /// 打印结束事件
     75         /// </summary>
     76         /// <param name="sender"></param>
     77         /// <param name="e"></param>
     78         private void imgToPrint_EndPrint(object sender, PrintEventArgs e)
     79         {
     80 
     81         }
     82 
     83         /// <summary>
     84         /// 设置打印内容
     85         /// </summary>
     86         /// <param name="sender"></param>
     87         /// <param name="e"></param>
     88         private void imgToPrint_PrintPage(object sender, PrintPageEventArgs e)
     89         {
     90             // 图片文本质量
     91             e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
     92             // 图片插值质量
     93             e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
     94             // 图片合成质量
     95             e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
     96             // 图片抗锯齿
     97             e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
     98             // 设置缩放比例
     99             e.Graphics.PageScale = 0.3F;
    100             using (Stream fs = new FileStream(imageList[printNum].ToString().Trim(), FileMode.Open, FileAccess.Read))
    101             {
    102                 System.Drawing.Image image = System.Drawing.Image.FromStream(fs);
    103                 int w = image.Width;
    104                 int h = image.Height;
    105                 // 绘制Image
    106                 e.Graphics.DrawImage(image, 40, 40, 410, 600);
    107                 if (printNum < imageList.Count - 1)
    108                 {
    109                     printNum++;
    110                     // HasMorePages为true则再次运行PrintPage事件
    111                     e.HasMorePages = true;
    112                     return;
    113                 }
    114                 e.HasMorePages = false;
    115             }
    116             // 设置打印内容的边距
    117             //e.PageSettings.Margins = new Margins(40, 40, 40, 40);
    118             // 设置是否横向打印
    119             e.PageSettings.Landscape = false;
    120             // 设置纸张大小
    121             e.PageSettings.PaperSize = paperSize;
    122             // 设置打印分辨率
    123             e.PageSettings.PrinterResolution.Kind = PrinterResolutionKind.High;
    124         }
    125     }

    以上就是 Html转图片,然后通过PrintDocument打印图片 的实现代码了。其它两种方式大家有兴趣可以去试试。

    WebBrowser 比较简单,但是对打印机控制不是特别友好(也可能是我没有发现,研究不深)

    1             WebBrowser wb = new WebBrowser();
    2             // 直接打印