c# 如何實(shí)現(xiàn)web打印插件
最近,客戶有個(gè)需求過(guò)來(lái),Web端無(wú)預(yù)覽打印,美其名曰:快捷打印。
當(dāng)時(shí)第一反應(yīng)就是找插件,拿來(lái)主義永遠(yuǎn)不過(guò)時(shí)。找了一圈發(fā)現(xiàn),免費(fèi)的有限制,沒(méi)限制的需要收費(fèi)(LODOP真的好用)。說(shuō)來(lái)就是一個(gè)簡(jiǎn)單的無(wú)預(yù)覽打印,收費(fèi)的諸多功能都無(wú)用武之地,總的來(lái)說(shuō)性價(jià)比很低,所以就打算自己琢磨著寫(xiě)一個(gè)算了。剛開(kāi)始總是糾結(jié)在Web端去實(shí)現(xiàn)直接打印,打印是實(shí)現(xiàn)了,結(jié)果是服務(wù)端的,客戶端只能一臉懵。
后來(lái)(準(zhǔn)備妥協(xié)了),安裝了一些收費(fèi)的插件發(fā)現(xiàn),都需要先安裝一個(gè)客戶端程序,靈光乍現(xiàn),解決方案這不就出來(lái)了。
思路:Web端調(diào)用客戶端程序,讓客戶端程序去實(shí)現(xiàn)打印。
實(shí)現(xiàn):Web端通過(guò)WebSocket將Html發(fā)送給客戶端,客戶端(Winform)監(jiān)聽(tīng)消息,接收處理后再打印。
客戶端(Winform)打印實(shí)現(xiàn)方式:
1、Html轉(zhuǎn)PDF,然后打印PDF(暫時(shí)需要用到三方包)
2、Html轉(zhuǎn)圖片,然后通過(guò)PrintDocument打印圖片
3、通過(guò)WebBrowser實(shí)現(xiàn)打印
按照上面的思路再去寫(xiě)代碼,就會(huì)簡(jiǎn)單很多。
Web端的代碼就不多說(shuō)了,一個(gè)簡(jiǎn)單的WebSocket通信。
客戶端程序(Winform)
1、監(jiān)聽(tīng)Web端的WebSocket消息,這里有用到三方包:Fleck,開(kāi)箱即用,非常方便。
/// <summary> /// ConnAndListen /// </summary> public static void ConnAndListen() { // 監(jiān)聽(tīng)本地 45000端口 var server = new WebSocketServer($"ws://127.0.0.1:45000"); server.Start(socket => { socket.OnOpen = () => { // 連接成功 socket.Send("socket通訊已連接"); }; socket.OnClose = () => { // 關(guān)閉連接 socket.Send("socket通訊已關(guān)閉連接"); socket.Close(); }; socket.OnMessage = message => { // TODO... }; }); }
2、處理Html,將Html轉(zhuǎn)換為圖片:
/// <summary> /// GetBitmap /// </summary> /// <returns></returns> public Bitmap GetBitmap() { WebPageBitmap Shot = new WebPageBitmap("html", "頁(yè)面寬度", "頁(yè)面高度"); Shot.GetIt(); Bitmap Pic = Shot.DrawBitmap("圖片高度", "圖片寬度"); // 設(shè)置圖片分辨率 Pic.SetResolution(203.0F, 203.0F); return Pic; }
3、打印圖片
/// <summary> /// 圖片打印 /// </summary> public class PrintDirectClass { private PaperSize paperSize = null; // 多頁(yè)打印 private int printNum = 0; // 單個(gè)圖片文件 private string imageFile = "....."; // 多個(gè)圖片文件 private ArrayList imageList = new ArrayList(); /// <summary> /// 打印預(yù)覽 /// </summary> public void PrintPreview() { // 打印機(jī)對(duì)象 PrintDocument imgToPrint = new PrintDocument(); #region 打印機(jī)相關(guān)設(shè)置 var pageSize = imgToPrint.PrinterSettings.PaperSizes; paperSize = pageSize[pageSize.Count - 1]; // 打印方向設(shè)置 //imgToPrint.DefaultPageSettings.Landscape = false; // 打印紙張大小設(shè)置 //imgToPrint.DefaultPageSettings.PaperSize = paperSize; // 打印分辨率設(shè)置 //imgToPrint.DefaultPageSettings.PrinterResolution.Kind = PrinterResolutionKind.High; // 打印邊距設(shè)置 //imgToPrint.DefaultPageSettings.Margins = new Margins(40, 40, 40, 40); // 打印開(kāi)始事件 imgToPrint.BeginPrint += new PrintEventHandler(this.imgToPrint_BeginPrint); // 打印結(jié)束事件 imgToPrint.EndPrint += new PrintEventHandler(this.imgToPrint_EndPrint); // 打印內(nèi)容設(shè)置 imgToPrint.PrintPage += new PrintPageEventHandler(this.imgToPrint_PrintPage); #endregion // 直接打印 //imgToPrint.Print(); // 打印彈框確認(rèn) //PrintDialog printDialog = new PrintDialog(); //printDialog.AllowSomePages = true; //printDialog.ShowHelp = true; //printDialog.Document = imgToPrint; //if (printDialog.ShowDialog() == DialogResult.OK) //{ // imgToPrint.Print(); //} // 預(yù)覽打印 //PrintPreviewDialog pvDialog = new PrintPreviewDialog(); //pvDialog.Document = imgToPrint; //pvDialog.ShowDialog(); } /// <summary> /// 打印開(kāi)始事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void imgToPrint_BeginPrint(object sender, PrintEventArgs e) { if (imageList.Count == 0) imageList.Add(imageFile); } /// <summary> /// 打印結(jié)束事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void imgToPrint_EndPrint(object sender, PrintEventArgs e) { } /// <summary> /// 設(shè)置打印內(nèi)容 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void imgToPrint_PrintPage(object sender, PrintPageEventArgs e) { // 圖片文本質(zhì)量 e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; // 圖片插值質(zhì)量 e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; // 圖片合成質(zhì)量 e.Graphics.CompositingQuality = CompositingQuality.HighQuality; // 圖片抗鋸齒 e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; // 設(shè)置縮放比例 e.Graphics.PageScale = 0.3F; using (Stream fs = new FileStream(imageList[printNum].ToString().Trim(), FileMode.Open, FileAccess.Read)) { System.Drawing.Image image = System.Drawing.Image.FromStream(fs); int w = image.Width; int h = image.Height; // 繪制Image e.Graphics.DrawImage(image, 40, 40, 410, 600); if (printNum < imageList.Count - 1) { printNum++; // HasMorePages為true則再次運(yùn)行PrintPage事件 e.HasMorePages = true; return; } e.HasMorePages = false; } // 設(shè)置打印內(nèi)容的邊距 //e.PageSettings.Margins = new Margins(40, 40, 40, 40); // 設(shè)置是否橫向打印 e.PageSettings.Landscape = false; // 設(shè)置紙張大小 e.PageSettings.PaperSize = paperSize; // 設(shè)置打印分辨率 e.PageSettings.PrinterResolution.Kind = PrinterResolutionKind.High; } }
以上就是 Html轉(zhuǎn)圖片,然后通過(guò)PrintDocument打印圖片 的實(shí)現(xiàn)代碼了。其它兩種方式大家有興趣可以去試試。
WebBrowser 比較簡(jiǎn)單,但是對(duì)打印機(jī)控制不是特別友好(也可能是我沒(méi)有發(fā)現(xiàn),研究不深)
WebBrowser wb = new WebBrowser(); // 直接打印 wb.Print(); // 確認(rèn)打印 wb.ShowPrintDialog(); // 預(yù)覽打印 wb.ShowPrintPreviewDialog();
Html轉(zhuǎn)PDF,然后打印PDF原理于Html轉(zhuǎn)圖片,然后通過(guò)PrintDocument打印圖片一樣,不同的是轉(zhuǎn)PDF可能需要用到第三方的包,目前這方便的包還是比較齊全的,NUGET搜索pdf幾乎全是。
需求總是來(lái)得特別突然,下次再有新特別需求時(shí)再來(lái)和大家分享。
其他的實(shí)現(xiàn)思路
第一種
安裝一個(gè)打印客戶端 用grid++實(shí)現(xiàn)打印模板
本地起一個(gè) WebSocketServer 客戶端接收信息然后 組裝模板打印即可。
第二種
通過(guò)webBrowser實(shí)現(xiàn)打印功能,只適用于文本
//轉(zhuǎn)到某個(gè)網(wǎng)址 webBrowser.Navigate(""); //直接打印 webBrowser.Print(); //預(yù)覽 webBrowser.ShowPrintPreviewDialog(); //打印 webBrowser.ShowPrintDialog();
以上就是c# 如何實(shí)現(xiàn)web打印插件的詳細(xì)內(nèi)容,更多關(guān)于c# 實(shí)現(xiàn)web打印插件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Unity的IPreprocessBuildWithReport實(shí)用案例深入解析
這篇文章主要為大家介紹了Unity的IPreprocessBuildWithReport實(shí)用案例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05c# 判斷指定文件是否存在的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了c# 判斷指定文件是否存在的簡(jiǎn)單實(shí)現(xiàn),需要的朋友可以參考下2014-02-02C#中的矩形數(shù)組(多維數(shù)組)和鋸齒數(shù)組的實(shí)現(xiàn)
本文主要介紹了C#中的矩形數(shù)組(多維數(shù)組)和鋸齒數(shù)組的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04C#中實(shí)現(xiàn)可變參數(shù)實(shí)例
這篇文章主要介紹了C#中實(shí)現(xiàn)可變參數(shù)實(shí)例,本文演示使用params 實(shí)現(xiàn)可變數(shù)量的參數(shù),并且這些參數(shù)的類型可以不同,需要的朋友可以參考下2015-01-01DevExpress實(shí)現(xiàn)GridView當(dāng)無(wú)數(shù)據(jù)行時(shí)提示消息
這篇文章主要介紹了DevExpress實(shí)現(xiàn)GridView當(dāng)無(wú)數(shù)據(jù)行時(shí)提示消息,需要的朋友可以參考下2014-08-08C#導(dǎo)入導(dǎo)出Excel數(shù)據(jù)的兩種方法
這篇文章主要為大家詳細(xì)介紹了C#導(dǎo)入導(dǎo)出Excel數(shù)據(jù)的兩種方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03基于C#的圖表控件庫(kù) ScottPlot編譯visual studio 2022
基于 C# 的 圖表控件庫(kù) ScottPlot,開(kāi)源免費(fèi),可以用于開(kāi)發(fā)一些上位機(jī)軟件,如電壓、電流波形的顯示,開(kāi)發(fā)【示波器】圖形界面,可以顯示一些圖表、波形,總之功能比較的強(qiáng)大,本文介紹了基于C#的圖表控件庫(kù) ScottPlot編譯visual studio 2022,需要的朋友可以參考下2022-06-06C#實(shí)現(xiàn)判斷當(dāng)前操作用戶管理角色的方法
這篇文章主要介紹了C#實(shí)現(xiàn)判斷當(dāng)前操作用戶管理角色的方法,涉及C#針對(duì)系統(tǒng)用戶判斷的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08