Partager via


Imprimer à partir de votre application

Cette rubrique explique comment imprimer à partir d’une application Windows.

Pour obtenir des fonctionnalités plus avancées, consultez Personnaliser l’interface utilisateur d’aperçu avant impression.

S’inscrire à l’impression

La première étape pour ajouter l’impression à votre application consiste à s’inscrire à l’impression en obtenant l’objet PrintManager pour la fenêtre active. La classe PrintManager est chargée d’orchestrer le flux d’impression pour votre application. Pour utiliser cette classe, vous devez d’abord appeler la méthode qui retourne l’objet PrintManager spécifique à la fenêtre active actuelle.

Votre application doit effectuer cette opération sur chaque écran à partir duquel vous souhaitez que votre utilisateur puisse imprimer. Seul l’écran affiché à l’utilisateur peut être inscrit pour l’impression. Si un écran de votre application est inscrit pour l’impression, il doit annuler l’inscription pour l’impression lors de sa sortie. S’il est remplacé par un autre écran, l’écran suivant doit s’inscrire à l’impression lorsqu’il s’ouvre.

Conseil

 Si vous devez prendre en charge l’impression à partir de plusieurs pages de votre application, vous pouvez placer ce code d’impression dans une classe d’assistance commune et faire en sorte que vos pages d’application la réutilisent. Pour obtenir un exemple de procédure, consultez la PrintHelper classe dans l’exemple d’impression UWP.

Une fois qu’un utilisateur a lancé l’impression, vous utilisez un PrintDocument pour préparer les pages à envoyer à l’imprimante. Le PrintDocument type se trouve dans l’espace de noms Microsoft.UI.Xaml.Printing , ainsi que d’autres types qui prennent en charge la préparation du contenu XAML pour l’impression.

La classe PrintDocument est utilisée pour gérer une grande partie de l’interaction entre l’application et PrintManager, mais elle expose plusieurs rappels de ses propres. Lors de l’inscription, créez des PrintDocument instances et PrintManager inscrivez des gestionnaires pour leurs événements d’impression.

Dans cet exemple, l’inscription est effectuée dans la RegisterForPrinting méthode, qui est appelée à partir du gestionnaire d’événements Loaded de la page.

using Microsoft.UI.Xaml.Printing;
using Windows.Graphics.Printing;

PrintDocument printDocument = null;
IPrintDocumentSource printDocumentSource = null;
List<UIElement> printPreviewPages = new List<UIElement>();

private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    RegisterForPrinting();
}

private void RegisterForPrinting()
{
    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
    PrintManager printManager = PrintManagerInterop.GetForWindow(hWnd);
    printManager.PrintTaskRequested += PrintTask_Requested;

    printDocument = new PrintDocument();
    printDocumentSource = printDocument.DocumentSource;
    printDocument.Paginate += PrintDocument_Paginate;
    printDocument.GetPreviewPage += PrintDocument_GetPreviewPage;
    printDocument.AddPages += PrintDocument_AddPages;
}

Avertissement

Dans les exemples d’impression UWP, il est recommandé de s’inscrire à l’impression à partir de la substitution de méthode OnNavigatedTo. Dans les applications non UWP, vous devez utiliser le handle de fenêtre dans l’appel PrintManagerInterop.GetForWindow. Vous devez donc utiliser l’événement Loaded pour vous assurer que le handle de fenêtre n’est pas null, ce qui peut être le cas dans OnNavigatedTo.

Ici, les gestionnaires d’événements ne sont pas inscrits dans la UnregisterForPrinting méthode, qui est appelée à partir de la méthode OnNavigatedFrom .

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    base.OnNavigatedFrom(e);
    UnregisterForPrinting();
}


private void UnregisterForPrinting()
{
    if (printDocument == null)
    {
        return;
    }

    printDocument.Paginate -= PrintDocument_Paginate;
    printDocument.GetPreviewPage -= PrintDocument_GetPreviewPage;
    printDocument.AddPages -= PrintDocument_AddPages;

    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
    PrintManager printManager = PrintManagerInterop.GetForWindow(hWnd);
    printManager.PrintTaskRequested -= PrintTask_Requested;
}

Remarque

Si vous avez une application à plusieurs pages et que vous ne déconnectez pas l’impression, une exception est levée lorsque l’utilisateur quitte la page, puis retourne à celle-ci.

Créer un bouton Imprimer

Ajoutez un bouton d’impression à l’écran de votre application dans lequel vous souhaitez qu’elle apparaisse. Assurez-vous qu’il n’interfère pas avec le contenu que vous souhaitez imprimer.

<Button x:Name="InvokePrintingButton"
        Content="Print"
        Click="InvokePrintingButton_Click"/>

Dans le gestionnaire d’événements Click du bouton, affichez l’interface utilisateur d’impression Windows à l’utilisateur.

var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
await PrintManagerInterop.ShowPrintUIForWindowAsync(hWnd);

Cette méthode est une méthode asynchrone qui affiche la fenêtre d’impression appropriée. Vous devez donc ajouter le mot clé asynchrone au gestionnaire Click. Nous vous recommandons d’appeler d’abord la méthode IsSupported pour vérifier que l’application est en cours d’exécution sur un appareil prenant en charge l’impression (et de gérer le cas dans lequel elle n’est pas). Si l’impression ne peut pas être effectuée à ce moment-là pour une autre raison, la méthode lève une exception. Nous vous recommandons d’intercepter ces exceptions et d’informer l’utilisateur lorsque l’impression ne peut pas continuer.

Dans cet exemple, une fenêtre d’impression s’affiche dans le gestionnaire d’événements pour un clic sur un bouton. Si la méthode lève une exception (car l’impression ne peut pas être effectuée à ce moment-là), un contrôle ContentDialog informe l’utilisateur de la situation.

private async void InvokePrintingButton_Click(object sender, RoutedEventArgs e)
{
    if (PrintManager.IsSupported())
    {
        try
        {
            // Show system print UI.
            var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
            await Windows.Graphics.Printing.PrintManagerInterop.ShowPrintUIForWindowAsync(hWnd);
        }
        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();
    }
}

Mettre en forme le contenu de votre application

Quand ShowPrintUIForWindowAsync il est appelé, l’événement PrintTaskRequested est déclenché. Dans le PrintTaskRequested gestionnaire d’événements, vous créez un PrintTask en appelant la méthode PrintTaskRequest.CreatePrintTask . Transmettez le titre de la page d’impression et le nom d’un délégué PrintTaskSourceRequestedHandler . Le titre est affiché dans l’interface utilisateur d’aperçu avant impression. PrintTask Liens PrintTaskSourceRequestedHandler avec le PrintDocument contenu qui fournira le contenu.

Dans cet exemple, un gestionnaire d’achèvement est également défini pour intercepter les erreurs. Il est judicieux de gérer les événements d’achèvement, car votre application peut indiquer à l’utilisateur si une erreur s’est produite et fournir des solutions possibles. De même, votre application peut utiliser l’événement d’achèvement pour indiquer les étapes suivantes pour que l’utilisateur prenne une fois la tâche d’impression réussie.

private void PrintTask_Requested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
    // Create the PrintTask.
    // Defines the title and delegate for PrintTaskSourceRequested.
    PrintTask printTask = args.Request.CreatePrintTask("WinUI 3 Printing example", PrintTaskSourceRequested);

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

    DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () =>
    {
        InvokePrintingButton.IsEnabled = false;
    });
}

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

private void PrintTask_Completed(PrintTask sender, PrintTaskCompletedEventArgs args)
{
    string StatusBlockText = string.Empty;

    // Notify the user if the print operation fails.
    if (args.Completion == PrintTaskCompletion.Failed)
    {
        StatusBlockText = "Failed to print.";
    }
    else if (args.Completion == PrintTaskCompletion.Canceled)
    {
        StatusBlockText = "Printing canceled.";
    }
    else
    {
        StatusBlockText = "Printing completed.";
    }


    DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () =>
    {
        StatusBlock.Text = StatusBlockText;
        InvokePrintingButton.IsEnabled = true;
    });
}

Une fois la tâche d’impression créée, PrintManager demande une collection de pages d’impression à afficher dans l’interface utilisateur d’aperçu avant impression en générant l’événement Paginate. (Cela correspond à la Paginate méthode de l’interface IPrintPreviewPageCollection .) Le gestionnaire d’événements que vous avez créé lors de l’inscription est appelé pour l’instant.

Important

 Si l’utilisateur modifie les paramètres d’impression, le gestionnaire d’événements paginé est appelé à nouveau pour vous permettre de reflower le contenu. Pour une expérience utilisateur optimale, nous vous recommandons de vérifier les paramètres avant de reflower le contenu et d’éviter de réinitialiser le contenu paginé lorsqu’il n’est pas nécessaire.

Dans le gestionnaire d’événements Paginate, créez les pages à afficher dans l’interface utilisateur d’aperçu avant impression et envoyez-les à l’imprimante. Le code que vous utilisez pour préparer le contenu de votre application pour l’impression est spécifique à votre application et le contenu que vous imprimez.

Cet exemple montre les étapes de base pour créer une page d’impression unique qui imprime une image et une légende à partir de la page affichée à l’écran.

  • Créez une liste pour contenir les éléments de l’interface utilisateur (pages) à imprimer.
  • Effacez la liste des pages d’aperçu afin que les pages ne soient pas dupliquées chaque fois que la pagination se produit.
  • Utilisez printPageDescription pour obtenir la taille de la page d’imprimante.
  • Mettez en forme votre contenu XAML pour qu’il corresponde à la page de l’imprimante. Chaque page à imprimer est un élément d’interface utilisateur XAML (généralement un élément conteneur qui contient d’autres contenus). Dans cet exemple, les éléments sont créés dans le code et utilisent les mêmes données que les éléments affichés à l’écran.
  • Circulez le contenu sur des pages supplémentaires si nécessaire. Plusieurs pages ne sont pas affichées dans cet exemple de base, mais la division du contenu en pages est une partie importante de l’événement Paginate.
  • Ajoutez chaque page à la liste des pages à imprimer.
  • Définissez le nombre de pages d’aperçu dans PrintDocument.
List<UIElement> printPreviewPages = new List<UIElement>();

private void PrintDocument_Paginate(object sender, PaginateEventArgs e)
{
    // Clear the cache of preview pages.
    printPreviewPages.Clear();

    // Get the PrintTaskOptions.
    PrintTaskOptions printingOptions = ((PrintTaskOptions)e.PrintTaskOptions);
    // Get the page description to determine the size of the print page.
    PrintPageDescription pageDescription = printingOptions.GetPageDescription(0);

    // Create the print layout.
    StackPanel printLayout = new StackPanel();
    printLayout.Width = pageDescription.PageSize.Width;
    printLayout.Height = pageDescription.PageSize.Height;
    printLayout.BorderBrush = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.Black);
    printLayout.BorderThickness = new Thickness(48);

    Image printImage = new Image();
    printImage.Source = printContent.Source;

    printImage.Width = pageDescription.PageSize.Width / 2;
    printImage.Height = pageDescription.PageSize.Height / 2;

    TextBlock imageDescriptionText = new TextBlock();
    imageDescriptionText.Text = imageDescription.Text;
    imageDescriptionText.FontSize = 24;
    imageDescriptionText.HorizontalAlignment = HorizontalAlignment.Center;
    imageDescriptionText.Width = pageDescription.PageSize.Width / 2;
    imageDescriptionText.TextWrapping = TextWrapping.WrapWholeWords;

    printLayout.Children.Add(printImage);
    printLayout.Children.Add(imageDescriptionText);

    // Add the print layout to the list of preview pages.
    printPreviewPages.Add(printLayout);

    // Report the number of preview pages created.
    PrintDocument printDocument = (PrintDocument)sender;
    printDocument.SetPreviewPageCount(printPreviewPages.Count,
                                          PreviewPageCountType.Intermediate);
}

Voici une capture d’écran de l’interface utilisateur de l’application et de la façon dont le contenu apparaît dans l’interface utilisateur d’aperçu avant impression.

Capture d’écran d’une interface utilisateur d’application en regard de l’interface utilisateur d’aperçu avant impression système, montrant une image et une légende à imprimer.

Lorsqu’une page particulière doit être affichée dans la fenêtre d’aperçu avant impression, PrintManager déclenche l’événement GetPreviewPage. Cela correspond à la MakePage méthode de l’interface IPrintPreviewPageCollection . Le gestionnaire d’événements que vous avez créé lors de l’inscription est appelé pour l’instant.

Dans le gestionnaire d’événements GetPreviewPage , définissez la page appropriée sur le document d’impression.

private void PrintDocument_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
{
    PrintDocument printDocument = (PrintDocument)sender;
    printDocument.SetPreviewPage(e.PageNumber, printPreviewPages[e.PageNumber - 1]);
}

Enfin, une fois que l’utilisateur clique sur le bouton Imprimer, printManager demande la collection finale de pages à envoyer à l’imprimante en appelant la MakeDocument méthode de l’interfaceIDocumentPageSource. En XAML, cela déclenche l’événement AddPages . Le gestionnaire d’événements que vous avez créé lors de l’inscription est appelé pour l’instant.

Dans le gestionnaire d’événements AddPages , ajoutez des pages de la collection de pages à l’objet PrintDocument à envoyer à l’imprimante. Si un utilisateur spécifie des pages particulières ou une plage de pages à imprimer, vous utilisez ces informations ici pour ajouter uniquement les pages qui seront réellement envoyées à l’imprimante.

private void PrintDocument_AddPages(object sender, AddPagesEventArgs e)
{
    PrintDocument printDocument = (PrintDocument)sender;

    // Loop over all of the preview pages and add each one to be printed.
    for (int i = 0; i < printPreviewPages.Count; i++)
    {
        printDocument.AddPage(printPreviewPages[i]);
    }

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