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à)比很低,所以就打算自己琢磨著寫一個(gè)算了。剛開始總是糾結(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)打印
按照上面的思路再去寫代碼,就會(huì)簡(jiǎn)單很多。
Web端的代碼就不多說(shuō)了,一個(gè)簡(jiǎn)單的WebSocket通信。
客戶端程序(Winform)
1、監(jiān)聽(tīng)Web端的WebSocket消息,這里有用到三方包:Fleck,開箱即用,非常方便。
/// <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);
// 打印開始事件
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>
/// 打印開始事件
/// </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)文章
c#學(xué)習(xí)之30分鐘學(xué)會(huì)XAML
一個(gè)界面程序的核心,無(wú)疑就是界面和后臺(tái)代碼,而xaml就是微軟為構(gòu)建應(yīng)用程序界面而創(chuàng)建的一種描述性語(yǔ)言,也就是說(shuō),這東西是搞界面的2016-11-11
C#制作多線程處理強(qiáng)化版網(wǎng)絡(luò)爬蟲
這篇文章主要介紹了C#制作多線程處理強(qiáng)化版網(wǎng)絡(luò)爬蟲的相關(guān)代碼,有想學(xué)習(xí)C#多線程編程的小伙伴可以參考下2016-09-09
在Form_Load里面調(diào)用Focus無(wú)效的解決方法
在調(diào)用Form_Load的時(shí)候,F(xiàn)orm其實(shí)還沒(méi)有進(jìn)入展示階段,自然Focus()調(diào)用也就沒(méi)效果了。2013-02-02
C# 使用WPF 用MediaElement控件實(shí)現(xiàn)視頻循環(huán)播放
在WPF里用MediaElement控件,實(shí)現(xiàn)一個(gè)循環(huán)播放單一視頻的程序,同時(shí)可以控制視頻的播放、暫停、停止。這篇文章給大家介紹了C# 使用WPF 用MediaElement控件實(shí)現(xiàn)視頻循環(huán)播放,需要的朋友參考下吧2018-04-04
C#實(shí)現(xiàn)Excel導(dǎo)入sqlite的方法
這篇文章主要介紹了C#實(shí)現(xiàn)Excel導(dǎo)入sqlite的方法,是C#程序設(shè)計(jì)中非常重要的一個(gè)實(shí)用技巧,需要的朋友可以參考下2014-09-09
C#如何實(shí)現(xiàn)子進(jìn)程跟隨主進(jìn)程關(guān)閉
多進(jìn)程開發(fā)經(jīng)常會(huì)遇到主進(jìn)程關(guān)閉,子進(jìn)程需要跟隨主進(jìn)程一同關(guān)閉,比如調(diào)ffmpeg命令行實(shí)現(xiàn)的錄屏程序等,下面我們就來(lái)看看C#是如何實(shí)現(xiàn)子進(jìn)程跟隨主進(jìn)程關(guān)閉的吧2024-04-04
HTML文本框的值改變后觸發(fā)后臺(tái)代碼的方法
asp.net用日期插件,當(dāng)選中一個(gè)日期時(shí)觸發(fā)一個(gè)事件,以查詢當(dāng)前日期的數(shù)據(jù)。這是要跟數(shù)據(jù)庫(kù)交互的。先貼出控件代碼:2013-04-04
C#實(shí)現(xiàn)掃描局域網(wǎng)內(nèi)的所有IP和端口
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)掃描局域網(wǎng)內(nèi)的所有IP和端口的功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12

