最近,客戶有個需求過來,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 // 直接打印 3 wb.Print(); 4 // 確認打印 5 wb.ShowPrintDialog(); 6 // 預覽打印 7 wb.ShowPrintPreviewDialog();
Html轉PDF,然后打印PDF原理於Html轉圖片,然后通過PrintDocument打印圖片一樣,不同的是轉PDF可能需要用到第三方的包,目前這方便的包還是比較齊全的,NUGET搜索pdf幾乎全是。
需求總是來得特別突然,下次再有新特別需求時再來和大家分享。
以上就是這篇文章的全部內容了,有幫助的點個贊,有錯誤的歡迎大家指出來,有更好的解決方案也希望大家不吝賜教。