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打印票据的更多相关文章
- 洗衣店专用手持智能POS PDA手持设备 上门收衣 现场刷卡 打印票据 开单系统
手持上门收衣设备通过wifi或者3G手机卡等进行联网,功能便捷强大,多功能一体同步使用,通过手持机上门收.取衣物,快速开单收衣消费.取货.新建会员.现场办理会员发卡.手持机读发会员卡和会员用卡消费等. ...
- WPF 打印实例
原文:WPF 打印实例 在WPF 中可以通过PrintDialog 类方便的实现应用程序打印功能,本文将使用一个简单实例进行演示.首先在VS中编辑一个图形(如下图所示). 将需要打 ...
- WPF打印原理,自定义打印
一.基础知识 1.System.Printing命名空间 我们可以先看一下System.Printing命名空间,东西其实很多,功能也非常强大,可以说能够控制打印的每一个细节,曾经对PrintDial ...
- WPF 打印控件 无弹框打印。
WPF中打印用到了 PrintDialog类. 其中设置打印属性的是PrintTicket,管理打印机的是PrintQueue. 实例如下: public class PrintDialogHelpe ...
- C# WPF打印报表
前天我的一个同学由于打印报表而苦恼,所以就介绍了一下WPF的打印报表,希望能帮助到大家. 展示报表 1. 首先新建项“报表”,选定项目,右击,点击“添加”->“新建项”->“报表”
- wpf打印控件 实现分页打印控件功能
因为 要实现打印 wpf listbox控件 数据特别多 要打印在 几张纸上 找了几天 都没有找到相关的例子 现在 解决了 在这里和大家分享一下 public void print(Fram ...
- [WPF打印]WPF 文档元素(Run TextBlock Paragraph)的文字对齐方式
最近开发WPF程序,需要打印,用到了FlowDocument(这相当于有了打印模版,而且可以随时修改,真的是挺方便的).可是在输出表格形数据(这种情况恐怕是大多数~)时遇到了点儿麻烦. 由于Table ...
- WPF打印控件内容
当我们想打印控件内容时,如一个Grid中的内容,可以用WPF中PrintDialog类的PrintVisual()方法来实现 界面如下: XAML代码如下 <Grid> <Grid. ...
- WPF 打印
1. System.Windows.Controls.PrintDialog printDialog = new System.Windows.Controls.PrintDialog(); if ( ...
随机推荐
- Dynamic CRM 2013学习笔记(三十八)流程1 - 操作(action)开发与配置详解
CRM 2013 里流程有4个类别:操作(action).业务流程(business process flow).对话(dialog)和工作流(workflow).它们都是从 setting –> ...
- Dynamic CRM 2015学习笔记 系列汇总
这里列出所有 Dynamic CRM 2015学习笔记 系列文章,方便大家查阅.有任何建议.意见.需要,欢迎大家提交评论一起讨论. 本文原文地址:Dynamic CRM 2015学习笔记 系列汇总 一 ...
- solr与.net系列课程(一)solr的安装与配置
不久之前开发了一个项目,需要用到solr,因为所以在开始再网上查找资料,但是发现大部分的资料都是很片面的,要么就是只讲解solr如何安装的,要么就是只讲解solr的某一个部分的,而且很多都是资料都是一 ...
- [JS3] 立即执行JS
<html> <head> <title>立即执行</title> <SCRIPT TYPE="text/JavaScript" ...
- 深入浅出OOP(三): 多态和继承(动态绑定/运行时多态)
在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 运行时多态或迟绑定.动态绑定 在C#语音中,运行时 ...
- Oracle dmp文件导入(还原)到不同的表空间和不同的用户下
------------------------------------- 从生产环境拷贝一个dmp备份文件,在另外一台电脑上搭建测试环境,用imp命令导入dmp文件时提示如下错误: 问题描述: IM ...
- 在SecureCRT标签显示IP标题(转)
- HTML5播放器FlowPlayer的极简风格效果
在线演示 本地下载 使用Flowplayer生成的极简风格的播放器效果.
- js图片时间翻转
带素材 代码一: <!-- Author: XiaoWen Create a file: 2016-12-12 10:08:02 Last modified: 2016-12-12 11:30: ...
- iOS开发之静态库(五)—— 图片、界面xib等资源文件封装到静态框架framework
编译环境:Macbook Air + OS X 10.9.2 + XCode5.1 + iPhone5s(iOS7.0.3) 一.首先将资源文件打包成bundle 由于bundle是静态的,所以可以将 ...