如何在UWP应用程序中打印?

问题描述 投票:7回答:2

我正在尝试从我的UWP应用程序中打印出一些内容。基本上我用WebViewBrush将一些数据绘制到一些FrameworkElement(Windows.UI.Xaml.Shapes.Rectangle) - 我想在每个页面上打印其中一个矩形(每页一个矩形)

我真的希望有人可以提供一个非常简单的例子,说明如何在UWP中进行打印。我自己尝试了,我很乐意提供我的代码,但实际上有数千行 - 我从Microsoft GitHub示例中获取并尝试调整:

老实说,我认为这些例子太复杂了。我想要的只是一种非常简单的打印方式。我也找不到关于这个主题的任何教程,但我想如果有人有一个我可以开始工作的小代码片段,也许我可以在它上面构建它所以它可以使用矩形(而不是我现在正在做的事情 - 采取微软的一个很好的例子,试图找出我不需要的部分。

谢谢。我想任何能够以简单的方式回答这个问题的人都会发现这将成为未来的权威参考点 - 因为有关这个主题的在线信息是如此稀缺。

c# printing uwp windows-10-universal
2个回答
17
投票

有关如何在UWP应用程序中打印,您可以按照Print from your app中的步骤操作。并且还可以参考GitHub上的Printing sample。以下是一个简单的示例演示如何在页面上打印矩形。

在XAML中,添加打印按钮和要打印的矩形。

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Button HorizontalAlignment="Center" Click="PrintButtonClick">Print</Button>
    <Rectangle x:Name="RectangleToPrint"
               Grid.Row="1"
               Width="500"
               Height="500">
        <Rectangle.Fill>
            <ImageBrush ImageSource="Assets/img.jpg" />
        </Rectangle.Fill>
    </Rectangle>
</Grid>

在代码隐藏中,处理打印逻辑。

public sealed partial class MainPage : Page
{
    private PrintManager printMan;
    private PrintDocument printDoc;
    private IPrintDocumentSource printDocSource;

    public MainPage()
    {
        this.InitializeComponent();
    }

    #region Register for printing

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        // Register for PrintTaskRequested event
        printMan = PrintManager.GetForCurrentView();
        printMan.PrintTaskRequested += PrintTaskRequested;

        // Build a PrintDocument and register for callbacks
        printDoc = new PrintDocument();
        printDocSource = printDoc.DocumentSource;
        printDoc.Paginate += Paginate;
        printDoc.GetPreviewPage += GetPreviewPage;
        printDoc.AddPages += AddPages;
    }

    #endregion

    #region Showing the print dialog

    private async void PrintButtonClick(object sender, RoutedEventArgs e)
    {
        if (PrintManager.IsSupported())
        {
            try
            {
                // Show print UI
                await PrintManager.ShowPrintUIAsync();
            }
            catch
            {
                // Printing cannot proceed at this time
                ContentDialog noPrintingDialog = new ContentDialog()
                {
                    Title = "Printing error",
                    Content = "\nSorry, printing can' t proceed at this time.",
                    PrimaryButtonText = "OK"
                };
                await noPrintingDialog.ShowAsync();
            }
        }
        else
        {
            // Printing is not supported on this device
            ContentDialog noPrintingDialog = new ContentDialog()
            {
                Title = "Printing not supported",
                Content = "\nSorry, printing is not supported on this device.",
                PrimaryButtonText = "OK"
            };
            await noPrintingDialog.ShowAsync();
        }
    }

    private void PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
    {
        // Create the PrintTask.
        // Defines the title and delegate for PrintTaskSourceRequested
        var printTask = args.Request.CreatePrintTask("Print", PrintTaskSourceRequrested);

        // Handle PrintTask.Completed to catch failed print jobs
        printTask.Completed += PrintTaskCompleted;
    }

    private void PrintTaskSourceRequrested(PrintTaskSourceRequestedArgs args)
    {
        // Set the document source.
        args.SetSource(printDocSource);
    }

    #endregion

    #region Print preview

    private void Paginate(object sender, PaginateEventArgs e)
    {
        // As I only want to print one Rectangle, so I set the count to 1
        printDoc.SetPreviewPageCount(1, PreviewPageCountType.Final);
    }

    private void GetPreviewPage(object sender, GetPreviewPageEventArgs e)
    {
        // Provide a UIElement as the print preview.
        printDoc.SetPreviewPage(e.PageNumber, this.RectangleToPrint);
    }

    #endregion

    #region Add pages to send to the printer

    private void AddPages(object sender, AddPagesEventArgs e)
    {
        printDoc.AddPage(this.RectangleToPrint);

        // Indicate that all of the print pages have been provided
        printDoc.AddPagesComplete();
    }

    #endregion

    #region Print task completed

    private async void PrintTaskCompleted(PrintTask sender, PrintTaskCompletedEventArgs args)
    {
        // Notify the user when the print operation fails.
        if (args.Completion == PrintTaskCompletion.Failed)
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            {
                ContentDialog noPrintingDialog = new ContentDialog()
                {
                    Title = "Printing error",
                    Content = "\nSorry, failed to print.",
                    PrimaryButtonText = "OK"
                };
                await noPrintingDialog.ShowAsync();
            });
        }
    }

    #endregion
}

1
投票

我也一直在努力。我已经遍历了SDK示例。此解决方案可能对您有所帮助。如果有某种方法可以将要打印的内容放入RichTextBox中,则可以通过编程方式为其构建段落。并将SDK示例中的RichTextBox替换为您已列出网格要求的空白StackPanel,它将解决您的问题。我的问题并不完全相同,因为我已经完成了创建一个偶数2列的杂货清单。诀窍是在我的例子中使用固定宽度字体CourierNew。

在调用打印库的页面中,您需要在XAML中使用它

<Canvas x:Name="PrintCanvas" Opacity="0"/>

在替换PageToPrint的页面中,您可以在构造函数中构建这些东西。我将一个Collection传递给页面的实例化,然后在PageToPrint替换中直接计算布局,就像这样,

   private void MakeThePrintOut()
    {


        RichTextBlock gutOne = initBlock();
        PopulateBlock(gutOne);
        ContentStack.Children.Add(gutOne);


    }
    private RichTextBlock initBlock()
    {

        RichTextBlock gutInitBlock = new RichTextBlock();
        gutInitBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.Black);
        gutInitBlock.FontSize = 18;
        gutInitBlock.OverflowContentTarget = FirstLinkedContainer;
        gutInitBlock.FontFamily = new FontFamily("Courier New");
        gutInitBlock.VerticalAlignment = VerticalAlignment.Top;
        gutInitBlock.HorizontalAlignment = HorizontalAlignment.Left;
        return gutInitBlock;

    }
    private void PopulateBlock( RichTextBlock Blocker)
    {


        bool firstItem = true;
        int firstLength = 0;
        Paragraph paraItem = null;
        Run itemRun = null;

        string CurrentIsle = "None";

        foreach( Grocery j in Grocs)
        {
            if (j.Isle != CurrentIsle)
            {
                if ((CurrentIsle != "None") && (!firstItem))
                {
                    paraItem.Inlines.Add(itemRun);
                    Blocker.Blocks.Add(paraItem);

                }
                CurrentIsle = j.Isle;
                firstItem = true;
                Paragraph paraIsle = new Paragraph();
                Run paraRan = new Run();
                paraRan.Text = "     " + j.Isle;
                paraIsle.Inlines.Add(paraRan);
                Blocker.Blocks.Add(paraIsle);


            }
           if (firstItem)
            {
                paraItem = new Paragraph();
                itemRun = new Run();
                itemRun.Text = "        [] " + j.Item;
                firstLength = j.Item.Length;
                firstItem = false;
            } else
            {
                firstItem = true;
                string s = new string(' ', 30 - firstLength);
                itemRun.Text += s + "[] " +  j.Item;
                paraItem.Inlines.Add(itemRun);
                Blocker.Blocks.Add(paraItem);

            }





            }
        if (!firstItem)
        {
            paraItem.Inlines.Add(itemRun);
            Blocker.Blocks.Add(paraItem);
        }
    }

这不完全是你想要的,但我知道找到一些有意义的东西来回答印刷问题是多么困难。如果你想看看我的GitHub.com/Gibbloggen上的完整例子,GutenbergOne项目就是我开发这个东西的原型。而且我也导入了我的主要项目EssentialGrocer,这也是同一地点的开源。那就是今晚,包括打印购物清单。

希望其中一些有所帮助,我也真的在努力解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.