码迷,mamicode.com
首页 > Windows程序 > 详细

【Win10应用开发】自定义打印选项

时间:2015-08-08 10:27:47      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:

原文:【Win10应用开发】自定义打印选项

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

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

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

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Button Content="打印" Click="OnClick"/>

            <Image Grid.Row="1" Width="300" Height="200" VerticalAlignment="Center" HorizontalAlignment="Center" Name="img"  Source="Assets/03.jpg"/>
        </Grid>

按钮的作用就是打开打印对话框,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

 

【Win10应用开发】自定义打印选项

标签:

原文地址:http://www.cnblogs.com/lonelyxmas/p/4712562.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!