日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

WPF打印票据

發布時間:2023/12/31 asp.net 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WPF打印票据 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文:WPF打印票據

最近工作的內容是有關于WPF的,整體開發沒有什么難度,主要是在打印上因為沒有任何經驗,犯了一些難,不過還好,解決起來也不是很費勁。

WPF打印票據或者是打印普通紙張區別不大,只是說打印票據要把需要打的內容擺放好位置,搞定縮放比例,就可以放入票據直接打印了。
那么關鍵點就是3個:
1、使用WPF提供的什么類、什么方法來執行打印
2、如何擺放位置
3、如何搞定縮放比例

1、使用WPF提供的什么類、什么方法來執行打印

這個問題很容易解決,搜索下WPF打印或WPF Print,就能找到示例代碼。
那么我用的是PrintDialog的PrintVisual方法。PrintDialog從名字中可以看出是個對話框,讓用戶手動選擇打印機。如果不想彈出對話框和選擇打印機,則可以讀取默認打印機或者在配置文件里配置打印機名稱,然后找到它。這就需要用到另外的兩個類:PrintQueue和LocalPrintServer。
使用PrintDialog打印:

var printDialog = new PrintDialog(); printDialog.PrintQueue = GetPrinter(); printDialog.PrintVisual(visual, visual.Name);

獲取打印機任務隊列:

public static PrintQueue GetPrinter(string printerName = null) {try{PrintQueue selectedPrinter = null;if (!string.IsNullOrEmpty(printerName)){var printers = new LocalPrintServer().GetPrintQueues();selectedPrinter = printers.FirstOrDefault(p => p.Name == printerName);}else{selectedPrinter = LocalPrintServer.GetDefaultPrintQueue();}return selectedPrinter;}catch{return null;} }

2、如何擺放位置

注意到我們上面的打印代碼是使用的PrintVisual,參數是Visual,那么這個Visual是什么?
我舉個WPF Grid類的繼承關系:Grid : Panel : FrameworkElement : UIElement : Visual,所以WPF的控件都是繼承自UIElement的,也是繼承Visual的。
那么我們把Grid看作是一張票據或一張紙,在這張紙上布置好需要打印的內容,不就OK了嗎。
你可以創建一個用戶控件來鼠標拖拽擺放,傳入實體對象綁定值,也可以動態生成一個Grid。

3、如何搞定縮放比例

僅僅擺放好,打印出來未必是我們想要的結果。因為票據的大小不同,特別是銀行那種身份證或金額的小格子,打歪了只能說明技術不到家啊。
所以擺放是要有依據的,依據就是掃描票據,然后在掃描的底圖上擺放,樣位置就不會錯位。然后縮放就是DPI(DPI是Dots Per Inch(每英寸所打印的點數)的縮寫)的概念。我們掃描的圖是像素的,而實際的紙張不能用像素這個單位。這個之間的換算需要依賴DPI。
具體縮放的方法:

//注意,我這里DPI寫死的是150,實際中你的DPI是多少要看掃描件怎么掃的。 var settings = new PrintSettings { Width = visual.Width, Height = visual.Height, DPI = 150 }; var renderTarget = new RenderTargetBitmap((int)settings.Width, (int)settings.Height, settings.DPI, settings.DPI, PixelFormats.Default); printDialog.PrintTicket = new PrintTicket(); printDialog.PrintTicket.PageMediaSize = new PageMediaSize(renderTarget.Width, renderTarget.Height); var capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket); var scale = Math.Max(capabilities.PageImageableArea.ExtentWidth / visual.Width, capabilities.PageImageableArea.ExtentHeight / visual.Height); visual.LayoutTransform = new ScaleTransform(scale, scale); var sz = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight); visual.Measure(sz); visual.Arrange(new Rect(new Point(0, 0), sz));

?

這樣我們就達到了縮放的目的,你可以查看MSDN看看具體的類和方法的含義。

其他的需求:

1、豎打

有些單據比較窄,但是寬度還可以,所以希望可以豎著打印,滿足這個需求也是一句話的事情。
在visual.Measure(sz);語句之前增加下面兩行代碼即可。

printDialog.PrintTicket.PageOrientation = PageOrientation.Landscape; printDialog.PrintTicket.PageMediaSize = new PageMediaSize(renderTarget.Height, renderTarget.Width);

2、退紙(針式打印機)

退紙并不是常用的功能,但是放錯了紙張想拿出來也要費一番力氣,所以想讓打印機自動吐出紙來。我也搜索了很多問答和文章,也沒試出來一個成功的,可能是方法不正確。最終采用了一個比較雞賊的辦法,就是打印一個空白頁,然后自動退紙。每種針式打印機可能不同,所以退紙的空白頁的大小要調整好。

var printer = GetPrinter(); var visual = new Grid() { Width = 1000, Height = 1500, VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left }; PrintVisual(printer, visual);

?3、監控打印任務狀態

打印的時候肯定想知道任務有沒有被打印,提醒用戶放入紙張,打印完畢后提醒用戶打印完成。我這里寫了一個PrintJobChecker類,Start后就會根據timer的間隔時間檢查任務隊列,和打印時間。
但是.NET提供的方法并不能很好的做到理想的效果,只能獲取到任務還有沒有,這是很郁悶的事情。一旦打印機開始打印(注意還沒完成),job就是null了。這無法判斷紙張是不是還在打印中。如果有朋友知道怎么處理還望評論告知。

public class PrintJobChecker {private DispatcherTimer _timer;private PrintQueue _printer;private Action<string> _checkingAction;public DateTime? StartPrintTime { get; set; }private int _interval = 100;public int TimerInterval{get { return _interval; }set{_interval = value;_timer.Interval = TimeSpan.FromMilliseconds(value);}}public PrintJobChecker(PrintQueue printer, Action<string> checkingAction){if (printer == null || checkingAction == null){return;}_printer = printer;_checkingAction = checkingAction;_timer = new DispatcherTimer{Interval = TimeSpan.FromMilliseconds(TimerInterval),};_timer.Tick += CheckJobStatus;PrintingStatus = "正在打印";PrintErrorStatus = "打印出錯";PrintOfflineStatus = "請連接打印機";PrintWaittingStatus = "請放入相應的表單至打印機";PrintUnknownStatus = "未知錯誤";}public void Start(){_timer.Start();}public void Stop(){_timer.Stop();}private void CheckJobStatus(object sender, EventArgs e){if (_printer == null){return;}var job = _printer.GetLastJob();if (job == null){if (!StartPrintTime.HasValue){StartPrintTime = DateTime.Now;}_checkingAction(PrintingStatus);}else{var statusText = GetJobStatus(job);_checkingAction(statusText);}}public string PrintingStatus { get; set; }public string PrintErrorStatus { get; set; }public string PrintOfflineStatus { get; set; }public string PrintWaittingStatus { get; set; }public string PrintUnknownStatus { get; set; }private string GetJobStatus(PrintSystemJobInfo job){if (job == null) return null;if (((job.JobStatus & PrintJobStatus.Completed) == PrintJobStatus.Completed)||((job.JobStatus & PrintJobStatus.Printed) == PrintJobStatus.Printed)){StartPrintTime = DateTime.Now;return PrintingStatus;}if ((job.JobStatus & PrintJobStatus.Error) == PrintJobStatus.Error){_timer.Stop();return PrintErrorStatus;}if ((job.JobStatus & PrintJobStatus.Offline) == PrintJobStatus.Offline||job.JobStatus == PrintJobStatus.None){return PrintOfflineStatus;}if ((job.JobStatus & PrintJobStatus.Printing) == PrintJobStatus.Printing){if (job.TimeSinceStartedPrinting > 0){return PrintingStatus;}else{return PrintWaittingStatus;}}return PrintUnknownStatus;} }

  

總結

以上是生活随笔為你收集整理的WPF打印票据的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。