简体   繁体   English

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

[英]How to print in UWP app?

I am trying to print out something from my UWP app. 我正在尝试从我的UWP应用程序中打印出一些内容。 Basically I've used a WebViewBrush to draw some data on to some FrameworkElement 's (Windows.UI.Xaml.Shapes.Rectangle) - and I want to print one of these Rectangles on each page (one rectangle per page) 基本上我已经使用WebViewBrush将一些数据绘制到一些FrameworkElement (Windows.UI.Xaml.Shapes.Rectangle)上 - 我想在每个页面上打印其中一个矩形(每页一个矩形)

I was really hoping someone could provide a very simple example of how printing in UWP works. 我真的希望有人可以提供一个非常简单的例子,说明如何在UWP中进行打印。 I have tried it myself and I am happy to provide my code, but there are honestly thousands of lines - all of which I've taken from the Microsoft GitHub examples and tried tweaking: 我自己尝试了,我很乐意提供我的代码,但实际上有数千行 - 我从Microsoft GitHub示例中获取并尝试调整:

Honestly, those examples are too complicated I think. 老实说,我认为这些例子太复杂了。 What I want is just a really simple way to print. 我想要的只是一种非常简单的打印方式。 I can't find any tutorials on this topic either, but I figure if someone has a small code snippet that I could get working maybe I could build on it so it will work with Rectangles (rather than what I'm doing now - taking a huge example from Microsoft and trying to figure out which parts I don't need). 我也找不到关于这个主题的任何教程,但我想如果有人有一个我可以开始工作的小代码片段,也许我可以在它上面构建它所以它可以使用矩形(而不是我现在正在做的事情 - 采取微软的一个很好的例子,试图找出我不需要的部分。

Thank you. 谢谢。 I think anyone that can answer this question in a simple way will find this will become a definitive reference point in the future - because information online about this topic is so scarce. 我想任何能够以简单的方式回答这个问题的人都会发现这将成为未来的权威参考点 - 因为有关这个主题的在线信息是如此稀缺。

For how to print in UWP apps, you can follow the steps in Print from your app . 有关如何在UWP应用程序中打印 ,您可以按照应用程序中的“ 打印”中的步骤操作。 And also refer to the Printing sample on GitHub. 另请参阅GitHub上的Printing示例 Following is a simple sample demonstrates how to print a rectangle on the page. 以下是一个简单的示例演示如何在页面上打印矩形。

In XAML, add a print button and the rectangle to be printed. 在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>

And in code-behind, handle the print logic. 在代码隐藏中,处理打印逻辑。

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
}

I've been struggling with this also. 我也一直在努力。 I've gone over and over the SDK example. 我已经遍历了SDK示例。 This solution may be helpful to you. 此解决方案可能对您有所帮助。 If there is some way that you can put what you want to print into a RichTextBox, you can build the paragraphs for it programmatically. 如果有某种方法可以将要打印的内容放入RichTextBox中,则可以通过编程方式为其构建段落。 And replace the RichTextBox in the SDK example with a blank StackPanel that you have laid out the grid requirements on, and it will solve your issue. 并将SDK示例中的RichTextBox替换为您已列出网格要求的空白StackPanel,它将解决您的问题。 Mine wasn't exactly the same issue, because I have done it with Creating an even 2 columned grocery list. 我的问题并不完全相同,因为我已经完成了创建一个偶数2列的杂货清单。 The trick was to use a fixed width font, CourierNew, in my example. 诀窍是在我的例子中使用固定宽度字体CourierNew。

In your page that calls the print libraries, you need to have this in the XAML 在调用打印库的页面中,您需要在XAML中使用它

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

In the page that is substituting for PageToPrint, you can build this stuff right in the constructor. 在替换PageToPrint的页面中,您可以在构造函数中构建这些东西。 I pass a Collection into the instantiation of the page, and then calculate the layout right in the PageToPrint substitute, like this,,, 我将一个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);
        }
    }

It's not exactly what you are looking for, but I know how hard it is to find something that makes sense to answer the printing question. 这不完全是你想要的,但我知道找到一些有意义的东西来回答印刷问题是多么困难。 If you want to see the complete example it's on my GitHub.com/Gibbloggen GutenbergOne project was my prototyping that I developed this stuff. 如果你想看看我的GitHub.com/Gibbloggen上的完整例子,GutenbergOne项目就是我开发这个东西的原型。 And I also have imported into my main project EssentialGrocer, this too is open source in the same location. 而且我也导入了我的主要项目EssentialGrocer,这也是同一地点的开源。 That, just tonight, includes printing of the shopping list. 那就是今晚,包括打印购物清单。

Hope some of this helps, I've really struggled with this one also. 希望其中一些有所帮助,我也真的在努力解决这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM