最近,客戶有個需求過來,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. 1 /// <summary>
  2. 2 /// ConnAndListen
  3. 3 /// </summary>
  4. 4 public static void ConnAndListen()
  5. 5 { 7 // 監聽本地 45000埠
  6. 8 var server = new WebSocketServer($"ws://127.0.0.1:45000");
  7. 9 server.Start(socket =>
  8. 10 {
  9. 11 socket.OnOpen = () =>
  10. 12 {
  11. 13 // 連線成功
  12. 14 socket.Send("socket通訊已連線");
  13. 15 };
  14. 16 socket.OnClose = () =>
  15. 17 {
  16. 18 // 關閉連線
  17. 19 socket.Send("socket通訊已關閉連線");
  18. 20 socket.Close();
  19. 21 };
  20. 22 socket.OnMessage = message =>
  21. 23 {
  22. 24 // TODO...
  23. 25 };
  24. 26 });
  25. 27 }

2、處理Html,將Html轉換為圖片:

  1. 1 /// <summary>
  2. 2 /// GetBitmap
  3. 3 /// </summary>
  4. 4 /// <returns></returns>
  5. 5 public Bitmap GetBitmap()
  6. 6 {
  7. 7 WebPageBitmap Shot = new WebPageBitmap("html", "頁面寬度", "頁面高度");
  8. 8 Shot.GetIt();
  9. 9 Bitmap Pic = Shot.DrawBitmap("圖片高度", "圖片寬度");
  10. 10 // 設定圖片解析度
  11. 11 Pic.SetResolution(203.0F, 203.0F);
  12. 12 return Pic;
  13. 13 }

3、列印圖片

  1. 1 /// <summary>
  2. 2 /// 圖片列印
  3. 3 /// </summary>
  4. 4 public class PrintDirectClass
  5. 5 {
  6. 6 private PaperSize paperSize = null;
  7. 7 // 多頁列印
  8. 8 private int printNum = 0;
  9. 9 // 單個圖片檔案
  10. 10 private string imageFile = ".....";
  11. 11 // 多個圖片檔案
  12. 12 private ArrayList imageList = new ArrayList();
  13. 13
  14. 14 /// <summary>
  15. 15 /// 列印預覽
  16. 16 /// </summary>
  17. 17 public void PrintPreview()
  18. 18 {
  19. 19 // 印表機物件
  20. 20 PrintDocument imgToPrint = new PrintDocument();
  21. 21
  22. 22 #region 印表機相關設定
  23. 23 var pageSize = imgToPrint.PrinterSettings.PaperSizes;
  24. 24 paperSize = pageSize[pageSize.Count - 1];
  25. 25
  26. 26 // 列印方向設定
  27. 27 //imgToPrint.DefaultPageSettings.Landscape = false;
  28. 28 // 列印紙張大小設定
  29. 29 //imgToPrint.DefaultPageSettings.PaperSize = paperSize;
  30. 30 // 列印解析度設定
  31. 31 //imgToPrint.DefaultPageSettings.PrinterResolution.Kind = PrinterResolutionKind.High;
  32. 32 // 列印邊距設定
  33. 33 //imgToPrint.DefaultPageSettings.Margins = new Margins(40, 40, 40, 40);
  34. 34
  35. 35 // 列印開始事件
  36. 36 imgToPrint.BeginPrint += new PrintEventHandler(this.imgToPrint_BeginPrint);
  37. 37 // 列印結束事件
  38. 38 imgToPrint.EndPrint += new PrintEventHandler(this.imgToPrint_EndPrint);
  39. 39 // 列印內容設定
  40. 40 imgToPrint.PrintPage += new PrintPageEventHandler(this.imgToPrint_PrintPage);
  41. 41 #endregion
  42. 42
  43. 43 // 直接列印
  44. 44 //imgToPrint.Print();
  45. 45
  46. 46 // 列印彈框確認
  47. 47 //PrintDialog printDialog = new PrintDialog();
  48. 48 //printDialog.AllowSomePages = true;
  49. 49 //printDialog.ShowHelp = true;
  50. 50 //printDialog.Document = imgToPrint;
  51. 51 //if (printDialog.ShowDialog() == DialogResult.OK)
  52. 52 //{
  53. 53 // imgToPrint.Print();
  54. 54 //}
  55. 55
  56. 56 // 預覽列印
  57. 57 //PrintPreviewDialog pvDialog = new PrintPreviewDialog();
  58. 58 //pvDialog.Document = imgToPrint;
  59. 59 //pvDialog.ShowDialog();
  60. 60 }
  61. 61
  62. 62 /// <summary>
  63. 63 /// 列印開始事件
  64. 64 /// </summary>
  65. 65 /// <param name="sender"></param>
  66. 66 /// <param name="e"></param>
  67. 67 private void imgToPrint_BeginPrint(object sender, PrintEventArgs e)
  68. 68 {
  69. 69 if (imageList.Count == 0)
  70. 70 imageList.Add(imageFile);
  71. 71 }
  72. 72
  73. 73 /// <summary>
  74. 74 /// 列印結束事件
  75. 75 /// </summary>
  76. 76 /// <param name="sender"></param>
  77. 77 /// <param name="e"></param>
  78. 78 private void imgToPrint_EndPrint(object sender, PrintEventArgs e)
  79. 79 {
  80. 80
  81. 81 }
  82. 82
  83. 83 /// <summary>
  84. 84 /// 設定列印內容
  85. 85 /// </summary>
  86. 86 /// <param name="sender"></param>
  87. 87 /// <param name="e"></param>
  88. 88 private void imgToPrint_PrintPage(object sender, PrintPageEventArgs e)
  89. 89 {
  90. 90 // 圖片文字質量
  91. 91 e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
  92. 92 // 圖片插值質量
  93. 93 e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
  94. 94 // 圖片合成質量
  95. 95 e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
  96. 96 // 圖片抗鋸齒
  97. 97 e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
  98. 98 // 設定縮放比例
  99. 99 e.Graphics.PageScale = 0.3F;
  100. 100 using (Stream fs = new FileStream(imageList[printNum].ToString().Trim(), FileMode.Open, FileAccess.Read))
  101. 101 {
  102. 102 System.Drawing.Image image = System.Drawing.Image.FromStream(fs);
  103. 103 int w = image.Width;
  104. 104 int h = image.Height;
  105. 105 // 繪製Image
  106. 106 e.Graphics.DrawImage(image, 40, 40, 410, 600);
  107. 107 if (printNum < imageList.Count - 1)
  108. 108 {
  109. 109 printNum++;
  110. 110 // HasMorePages為true則再次執行PrintPage事件
  111. 111 e.HasMorePages = true;
  112. 112 return;
  113. 113 }
  114. 114 e.HasMorePages = false;
  115. 115 }
  116. 116 // 設定列印內容的邊距
  117. 117 //e.PageSettings.Margins = new Margins(40, 40, 40, 40);
  118. 118 // 設定是否橫向列印
  119. 119 e.PageSettings.Landscape = false;
  120. 120 // 設定紙張大小
  121. 121 e.PageSettings.PaperSize = paperSize;
  122. 122 // 設定列印解析度
  123. 123 e.PageSettings.PrinterResolution.Kind = PrinterResolutionKind.High;
  124. 124 }
  125. 125 }

以上就是 Html轉圖片,然後通過PrintDocument列印圖片 的實現程式碼了。其它兩種方式大家有興趣可以去試試。

WebBrowser 比較簡單,但是對印表機控制不是特別友好(也可能是我沒有發現,研究不深)

  1. 1 WebBrowser wb = new WebBrowser();
  2. 2 // 直接列印
  3. 3 wb.Print();
  4. 4 // 確認列印
  5. 5 wb.ShowPrintDialog();
  6. 6 // 預覽列印
  7. 7 wb.ShowPrintPreviewDialog();

Html轉PDF,然後列印PDF原理於Html轉圖片,然後通過PrintDocument列印圖片一樣,不同的是轉PDF可能需要用到第三方的包,目前這方便的包還是比較齊全的,NUGET搜尋pdf幾乎全是。

需求總是來得特別突然,下次再有新特別需求時再來和大家分享。

以上就是這篇文章的全部內容了,有幫助的點個贊,有錯誤的歡迎大家指出來,有更好的解決方案也希望大家不吝賜教。