Как печатать в приложении UWP?

Я пытаюсь распечатать что-то из своего приложения UWP. В основном я использовал WebViewBrush, чтобы нарисовать некоторые данные на некотором FrameworkElement (Windows.UI.Xaml.Shapes.Rectangle) - и я хочу напечатать один из этих прямоугольников на каждой странице (один прямоугольник на странице)

Я действительно надеялся, что кто-то может предоставить очень простой пример того, как работает печать в UWP. Я пробовал это сам, и я счастлив предоставить свой код, но есть честно тысячи строк - все из которых я взял из примеров Microsoft GitHub и попытался настроить:

Честно говоря, эти примеры слишком сложны, я думаю. Я хочу просто очень простой способ печати. Я тоже не могу найти учебники по этой теме, но я полагаю, что если у кого-то есть небольшой фрагмент кода, который я мог бы получить, возможно, я мог бы построить его, поэтому он будет работать с Rectangles (а не тем, что я сейчас делаю) огромный пример от Microsoft и попытка выяснить, какие части мне не нужны).

Спасибо. Я думаю, что любой, кто может ответить на этот вопрос простым способом, найдет, что это станет окончательной точкой отсчета в будущем, потому что информация в Интернете по этой теме настолько скудная.

Ответ 1

Для того, чтобы печатать в приложениях UWP, вы можете выполнить шаги в Печать из вашего приложения. А также обратитесь к Пример печати в GitHub. Ниже приведен простой пример, демонстрирующий, как печатать прямоугольник на странице.

В 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
}

Ответ 2

Я тоже борется с этим. Я перешел на пример SDK. Это решение может быть полезно для вас. Если есть способ, которым вы можете поместить то, что вы хотите распечатать, в RichTextBox, вы можете создавать абзацы для него программно. И замените RichTextBox в примере SDK пустой StackPanel, на которую вы указали требования к сетке, и это решит вашу проблему. Моя проблема была не совсем той же проблемой, потому что я сделал это с созданием 2-х столбчатых списков продуктов. Хитрость заключалась в использовании шрифта с фиксированной шириной CourierNew в моем примере.

На своей странице, которая вызывает библиотеки печати, вы должны иметь это в XAML

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

На странице, заменяющей страницу PageToPrint, вы можете построить этот материал прямо в конструкторе. Я передаю коллекцию в экземпляр страницы, а затем вычисляю макет прямо в подстановке PageToPrint, например this,,

   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, это тоже с открытым исходным кодом в том же месте. Это, только сегодня, включает печать списка покупок.

Надеюсь, что кое-что из этого помогает, я действительно боролся с этим.

Ответ 3

Интересно! А как код в VB?