生活随笔
收集整理的這篇文章主要介紹了
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打印票据 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。