Imprimir de seu app
Este tópico descreve como imprimir de um aplicativo do Windows.
Para obter recursos mais avançados, consulte Personalizar a interface do usuário de visualização de impressão.
- APIs importantes: namespace Windows.Graphics.Printing, classe PrintManager, PrintTask, namespace Microsoft.UI.Xaml.Printing, classe PrintDocument
Registre-se para impressão
A primeira etapa para adicionar impressão ao seu aplicativo é registrar-se para impressão obtendo o objeto PrintManager para a janela atual. A classe PrintManager é responsável por orquestrar o fluxo de impressão do seu aplicativo. Para usar essa classe, você deve primeiro chamar o método que retorna o objeto PrintManager específico da janela ativa atual.
- Em um aplicativo não UWP, use o método PrintManagerInterop.GetForWindow .
- Em um aplicativo UWP, use o método PrintManager.GetForCurrentView .
Seu aplicativo deve fazer isso em todas as telas das quais você deseja que o usuário possa imprimir. Somente a tela exibida para o usuário pode ser registrada para impressão. Se uma tela do seu aplicativo tiver sido registrada para impressão, ela deverá cancelar o registro para impressão quando for encerrada. Se for substituído por outra tela, a próxima tela deverá ser registrada para impressão quando for aberta.
Dica
Se você precisar dar suporte à impressão de mais de uma página em seu aplicativo, poderá colocar esse código de impressão em uma classe auxiliar comum e fazer com que as páginas do aplicativo o reutilizem. Para obter um exemplo de como fazer isso, consulte a PrintHelper
classe no exemplo de impressão UWP.
Depois que um usuário inicia a impressão, você usa um PrintDocument para preparar as páginas a serem enviadas para a impressora. O PrintDocument
tipo está no namespace Microsoft.UI.Xaml.Printing junto com outros tipos que dão suporte à preparação de conteúdo XAML para impressão.
A classe PrintDocument é usada para lidar com grande parte da interação entre o aplicativo e o PrintManager, mas expõe vários retornos de chamada próprios. Durante o registro, crie instâncias de PrintManager
e PrintDocument
e registre manipuladores para seus eventos de impressão.
Neste exemplo, o RegisterForPrinting
registro é executado no método, que é chamado do manipulador de eventos Loaded da página.
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;
}
Aviso
Em exemplos de impressão UWP, é recomendável se registrar para impressão da substituição do método OnNavigatedTo. Em aplicativos não UWP, você precisa usar o identificador de janela na chamada PrintManagerInterop.GetForWindow, portanto, você deve usar o evento Loaded para garantir que o identificador de janela não null
seja , o que pode ser o caso em OnNavigatedTo.
Aqui, os manipuladores de eventos não são registrados no UnregisterForPrinting
método, que é chamado do método 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;
}
Observação
Se você tiver um aplicativo de várias páginas e não desconectar a impressão, uma exceção será gerada quando o usuário sair da página e retornar a ela.
Criar um botão de impressão
Adicione um botão de impressão à tela do seu aplicativo onde você gostaria que ele aparecesse. Certifique-se de que não interfere com o conteúdo que pretende imprimir.
<Button x:Name="InvokePrintingButton"
Content="Print"
Click="InvokePrintingButton_Click"/>
No manipulador de eventos Click do Button, mostre a interface do usuário de impressão do Windows para o usuário.
- Em um aplicativo não UWP, use o método PrintManagerInterop.ShowPrintUIForWindowAsync .
- Em um aplicativo UWP, use o método PrintManager.ShowPrintUIAsync .
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
await PrintManagerInterop.ShowPrintUIForWindowAsync(hWnd);
Esse método é um método assíncrono que exibe a janela de impressão apropriada, portanto, você precisará adicionar a palavra-chave assíncrona ao manipulador de cliques. É recomendável chamar o método IsSupported primeiro para verificar se o aplicativo está sendo executado em um dispositivo que dá suporte à impressão (e lidar com o caso em que não está). Se a impressão não puder ser executada naquele momento por qualquer outro motivo, o método gerará uma exceção. Recomendamos capturar essas exceções e informar ao usuário quando a impressão não puder continuar.
Neste exemplo, uma janela de impressão é exibida no manipulador de eventos para um clique de botão. Se o método gerar uma exceção (porque a impressão não pode ser executada naquele momento), um controle ContentDialog informará o usuário sobre a situação.
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();
}
}
Formatar o conteúdo do seu aplicativo
Quando ShowPrintUIForWindowAsync
é chamado, o evento PrintTaskRequested é gerado. No manipulador de PrintTaskRequested
eventos, você cria um PrintTask chamando o método PrintTaskRequest.CreatePrintTask . Passe o título da página de impressão e o nome de um representante PrintTaskSourceRequestedHandler . O título é mostrado na interface do usuário de visualização de impressão. Os PrintTaskSourceRequestedHandler
links com PrintTask
o PrintDocument
que fornecerá o conteúdo.
Neste exemplo, um manipulador de conclusão também é definido para capturar erros. É uma boa ideia lidar com eventos de conclusão porque seu aplicativo pode informar ao usuário se ocorreu um erro e fornecer possíveis soluções. Da mesma forma, seu aplicativo pode usar o evento completion para indicar as etapas subsequentes a serem executadas pelo usuário após o trabalho de impressão ser bem-sucedido.
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;
});
}
Depois que a tarefa de impressão é criada, o PrintManager solicita uma coleção de páginas de impressão para mostrar na interface do usuário de visualização de impressão gerando o evento Paginate. (Isso corresponde ao Paginate
IPrintPreviewPageCollection
método da interface.) O manipulador de eventos que você criou durante o registro é chamado neste momento.
Importante
Se o usuário alterar as configurações de impressão, o manipulador de eventos paginate será chamado novamente para permitir que você reflua o conteúdo. Para obter a melhor experiência do usuário, recomendamos verificar as configurações antes de refluir o conteúdo e evitar reinicializar o conteúdo paginado quando não for necessário.
No manipulador de eventos Paginate , crie as páginas a serem mostradas na interface do usuário de visualização de impressão e enviadas para a impressora. O código usado para preparar o conteúdo do aplicativo para impressão é específico do aplicativo e do conteúdo impresso.
Este exemplo mostra as etapas básicas para criar uma única página de impressão que imprime uma imagem e uma legenda da página mostrada na tela.
- Crie uma lista para conter os elementos da interface do usuário (páginas) a serem impressos.
- Limpe a lista de páginas de visualização para que as páginas não sejam duplicadas sempre que ocorrer a paginação.
- Use o PrintPageDescription para obter o tamanho da página da impressora.
- Formate o conteúdo XAML para caber na página da impressora. Cada página a ser impressa é um elemento de interface do usuário XAML (normalmente um elemento de contêiner que contém outro conteúdo). Neste exemplo, os elementos são criados no código e usam os mesmos dados que os elementos mostrados na tela.
- Flua o conteúdo para páginas adicionais conforme necessário. Várias páginas não são mostradas neste exemplo básico, mas dividir o conteúdo em páginas é uma parte importante do evento Paginate.
- Adicione cada página à lista de páginas a serem impressas.
- Defina a contagem de páginas de visualização no 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);
}
Aqui está uma captura de tela da interface do usuário do aplicativo e como o conteúdo aparece na interface do usuário de visualização de impressão.
Quando uma página específica deve ser mostrada na janela de visualização de impressão, o PrintManager gera o evento GetPreviewPage . Isso corresponde ao MakePage
método da IPrintPreviewPageCollection
interface. O manipulador de eventos que você criou durante o registro é chamado neste momento.
No manipulador de eventos GetPreviewPage , defina a página apropriada no documento de impressão.
private void PrintDocument_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
{
PrintDocument printDocument = (PrintDocument)sender;
printDocument.SetPreviewPage(e.PageNumber, printPreviewPages[e.PageNumber - 1]);
}
Por fim, quando o usuário clica no botão de impressão, o PrintManager solicita a coleção final de páginas a serem enviadas à impressora chamando o MakeDocument
método da IDocumentPageSource
interface. Em XAML, isso gera o evento AddPages . O manipulador de eventos que você criou durante o registro é chamado neste momento.
No manipulador de eventos AddPages, adicione páginas da coleção de páginas ao objeto PrintDocument a ser enviado para a impressora. Se um usuário especificar páginas específicas ou um intervalo de páginas para imprimir, use essas informações aqui para adicionar apenas as páginas que serão realmente enviadas para a impressora.
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();
}
Tópicos relacionados
Windows developer