博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Win10应用开发】自定义打印选项
阅读量:6141 次
发布时间:2019-06-21

本文共 8461 字,大约阅读时间需要 28 分钟。

老周在前一篇烂文中已经给大伙伴们演示了如何打印UI元素,今天的烂文就向各位介绍一下,如何向打印对话框添加自定义选项。如果只是讲如何实现,会比较抽象,也比较枯燥,而且相当无聊,更是说不清楚,毕竟这打印API用起来要比其他API稍稍复杂了一点。所以老周就做了一个打印图片的垃圾应用,在打印对话框中,你可以选择设置要打印图片的不透明度、旋转角度(0度,90度,180度,270度)。

OK,为环保事业做贡献,老周今天也节约一点口水。下面咱们开始干活。

1、先来设计一些UI,该UI简单大方朴素美丽极致,其XAML代码如下:

按钮的作用就是打开打印对话框,Image显示要打印的图片。不过呢,为了打印过程中设置选项(就是老周上面讲的什么不透明度等)时不会干扰界面上的Image,我打算在代码中再声明一个Image对象,专门用来打印。代码是这样的:

Image copyImage = null;        public MainPage()        {            this.InitializeComponent();            copyImage = new Image();            copyImage.Source = img.Source;            copyImage.Stretch = Stretch.Uniform;            rotateTrsf = new RotateTransform() { Angle = 0d };            copyImage.RenderTransformOrigin = new Point(0.5, 0.5);            this.copyImage.RenderTransform = rotateTrsf;        }

大家会看到我弄了个RotateTransform对象,干啥用的呢?你忘了吗,我刚说了要在打印对话框中选择图片的旋转角度的,对了,就是用来让copyImage进行旋转的。

 

2、接下来实现打印,基本过程我在前一篇烂文中说过,获取PrintManager实例,处理PrintTaskRequested事件,当有新的打印任务请求时,会发生该事件。看:

private void PrintMgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)        {            PrintTask task = null;            task = args.Request.CreatePrintTask("打印图像", async printSrcrqtArgs =>            {                task.Completed += async (ps, pe) =>                {                    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>                            {                                MessageDialog msgdlg = new MessageDialog("");                                if (pe.Completion == PrintTaskCompletion.Canceled)                                {                                    msgdlg.Content = "打印被取消。";                                }                                else if (pe.Completion == PrintTaskCompletion.Abandoned)                                {                                    msgdlg.Content = "已放弃打印。";                                }                                else if (pe.Completion == PrintTaskCompletion.Submitted)                                {                                    msgdlg.Content = "已提交打印。";                                }                                await msgdlg.ShowAsync();                            });                };                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>                  {                      printSrcrqtArgs.SetSource(_printdoc?.DocumentSource);                  });            });            task.Options.Orientation = PrintOrientation.Landscape;            // 创建自定义选项            PrintTaskOptionDetails optionDetails = PrintTaskOptionDetails.GetFromPrintTaskOptions(task.Options);            // 清除所有选项            optionDetails.DisplayedOptions.Clear();            // 添加标准项:页面方向            optionDetails.DisplayedOptions.Add(StandardPrintTaskOptions.Orientation);            // 添加自定义选项            // 不透明度            PrintCustomItemListOptionDetails list = optionDetails.CreateItemListOption(OPTION_OPACITY, "不透明度");            list.AddItem(OPACITY_50PC, "50 %");            list.AddItem(OPACITY_75PC, "75 %");            list.AddItem(OPACITY_100PC, "100 %");            optionDetails.DisplayedOptions.Add(OPTION_OPACITY);            // 旋转角度            list = optionDetails.CreateItemListOption(OPTION_ANGLE, "旋转角度");            list.AddItem(ANGLE_0, "0 度");            list.AddItem(ANGLE_90, "90 度");            list.AddItem(ANGLE_180, "180 度");            list.AddItem(ANGLE_270, "270 度");            optionDetails.DisplayedOptions.Add(OPTION_ANGLE);            // 处理选项更改事件            optionDetails.OptionChanged += OptionDetails_OptionChanged;        }

为了节约代码行数,同时为了展现C#语言的风采,我这里套用了几层Lambda表达式。

请大伙注意后半段代码,前半段代码你应该在前一篇烂文中见过,但后半段代码是小鲜肉,在本文中才出现,它的作用是向打印对话框中添加标准的,以及自定义的选项。

何为标准选项?就是一般打印参数(通用级别),这些选项的ID名称都由Windows.Graphics.Printing.StandardPrintTaskOptions类的静态属性所公开。

自定义选项就咱们自己定的选项,本例中,图片透明度、旋转角度就是自定义选项。

a、PrintTaskOptionDetails.GetFromPrintTaskOptions方法获取一个PrintTaskOptionDetails对象,可用它来操作选项集合。

b、PrintTaskOptionDetails对象有个DisplayedOptions属性,它是一个字符串列表,表示要在打印对话框上显示哪些选项,就把这些选项的ID放进去。没有在这个列表中的项就只有当用户点击“更多设置”时才会显示。

c、这行代码是把标准选项中的页面方向选项加到显示列表中,因为刚才用Clear方法把DisplayedOptions清空了,所以要加入一下。

optionDetails.DisplayedOptions.Add(StandardPrintTaskOptions.Orientation);

d、调用CreateItemListOption方法可以创建一个新的自定义选项,方法有两个字符串类型的参数,第一个参数是这组选项的ID,第二个参数是显示的内容,即要显示在打印对话框上的选项标题,ID是不显示出来的。

e、用AddItem方法添加子选项时也是如此,一个ID值和一个显示值。

注意:CreateItemListOption方法创建的是整个选项组,比如“旋转方向”,而AddItem方法才是向选项组添加列表项,比如90度、180度等。

f、选项列表是添加了,但为了在打印对话框中能够实时看到预览效果,应该处理Windows.Graphics.Printing.OptionDetails.PrintTaskOptionDetails对象的OptionChanged事件,当这些选项集合中的任意一组选项发生改变时就会触发事件。

private async void OptionDetails_OptionChanged(PrintTaskOptionDetails sender, PrintTaskOptionChangedEventArgs args)        {            if (args.OptionId == null) return;            string optID = args.OptionId as string; await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>            {                _printdoc.InvalidatePreview();            });        }

事件参数中的OptionId属性就是返回被更改的选项组的ID。注意是某个组选项的ID,不是单个子项的ID。

调用PrintDocument的InvalidatePreview方法是让PrintDocument中的UI元素重新呈现,和刷新差不多。

==================================================

和上一篇烂文中的一样,需要处理PrintDocument对象的几个事件,以处理打印和预览中相关的操作。

private void _printdoc_Paginate(object sender, PaginateEventArgs e)        {            // 根据打印对话框选项的变化来修改可视化对象            PrintTaskOptionDetails optdetails = PrintTaskOptionDetails.GetFromPrintTaskOptions(e.PrintTaskOptions);            // 不透明度            IPrintOptionDetails opaOpt = optdetails.Options[OPTION_OPACITY];            string opacity = opaOpt.Value as string;            switch (opacity)            {                case OPACITY_50PC:                    copyImage.Opacity = 0.5d;                    break;                case OPACITY_75PC:                    copyImage.Opacity = 0.75d;                    break;                case OPACITY_100PC:                    copyImage.Opacity = 1d;                    break;                default:                    copyImage.Opacity = 1d;                    break;            }            // 旋转角度            IPrintOptionDetails angleOpt = optdetails.Options[OPTION_ANGLE];            string angle = angleOpt.Value as string;            switch (angle)            {                case ANGLE_0:                    rotateTrsf.Angle = 0d;                    break;                case ANGLE_90:                    rotateTrsf.Angle = 90d;                    break;                case ANGLE_180:                    rotateTrsf.Angle = 180d;                    break;                case ANGLE_270:                    rotateTrsf.Angle = 270d;                    break;                default:                    rotateTrsf.Angle = 0d;                    break;            }            // 设置预览页面数            _printdoc.SetPreviewPageCount(1, PreviewPageCountType.Final);        }        private void _printdoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e)        {            // 呈现预览            try            {                _printdoc.SetPreviewPage(e.PageNumber, copyImage);            }            catch            {                // 发生异常时忽略            }        }        private void _printdoc_AddPages(object sender, AddPagesEventArgs e)        {            // 添加要打印的页面            _printdoc.AddPage(copyImage);            // 报告添加完成            _printdoc.AddPagesComplete();        }

 在GetPreviewPage事件处理中把代码放在try...catch中,是防止发生异常。因为标准打印选项的更改本身就会引发重绘行为,但我们这里是把标准项和自定义项混在一起用,有发生异常的可能性,所以放到try中安全一些。

如果不把代码放在try块中,其实还有一种方法:就是在刚才的OptionChanged事件的处理过程中,只判断当OptionId是我们自定义的选项组时才调用PrintDocument的InvalidatePreview方法,如果是标准选项就会忽略,这样就不会发生异常。即

private async void OptionDetails_OptionChanged(PrintTaskOptionDetails sender, PrintTaskOptionChangedEventArgs args)        {            if (args.OptionId == null) return;            string optID = args.OptionId as string;            if (optID == OPTION_OPACITY || optID == OPTION_ANGLE)            {                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>                  {                       _printdoc.InvalidatePreview();                  });            }        }

=====================================================

不知不觉中,示例已经完成了,现在来运行一下。

运行后如下图:

点打印按钮,打开打印对话框。在打印对话框中,你可以进行参数设置。

 

最后看看打印结果。

 

好了,今天咱们就聊到这儿,下次有空咱们继续吹牛。

示例下载地址:http://files.cnblogs.com/files/tcjiaan/customPrintOptionSample.zip

 

转载地址:http://ktkya.baihongyu.com/

你可能感兴趣的文章
任务调度(一)——jdk自带的Timer
查看>>
UIKit框架(15)PCH头文件
查看>>
整理看到的好的文档
查看>>
Linux磁盘管理和文件系统管理
查看>>
linux运维人员的成功面试总结案例分享
查看>>
Windows DHCP Server基于MAC地址过滤客户端请求实现IP地址的分配
查看>>
命令查询每个文件文件数
查看>>
《跟阿铭学Linux》第8章 文档的压缩与打包:课后习题与答案
查看>>
RAC表决磁盘管理和维护
查看>>
Apache通过mod_php5支持PHP
查看>>
发布一个TCP 吞吐性能测试小工具
查看>>
java学习:jdbc连接示例
查看>>
PHP执行批量mysql语句
查看>>
Extjs4.1.x 框架搭建 采用Application动态按需加载MVC各模块
查看>>
Silverlight 如何手动打包xap
查看>>
建筑电气暖通给排水协作流程
查看>>
JavaScript面向对象编程深入分析(2)
查看>>
linux 编码转换
查看>>
POJ-2287 Tian Ji -- The Horse Racing 贪心规则在动态规划中的应用 Or 纯贪心
查看>>
Windows8/Silverlight/WPF/WP7/HTML5周学习导读(1月7日-1月14日)
查看>>