Compartilhar via


Como gerenciar trabalhos de impressão em um aplicativo de dispositivo UWP

No Windows 8.1, os aplicativos de dispositivo UWP para impressoras podem gerenciar trabalhos de impressão. Este tópico usa a versão de C# do exemplo Gerenciamento de trabalho de impressão e manutenção de impressora para demonstrar como criar uma exibição de trabalhos de impressão, monitorar esses trabalhos e, se necessário, cancelar um trabalho. Para saber mais sobre aplicativos de dispositivo UWP em geral, consulte Conhecer os aplicativos de dispositivo UWP.

A versão de C# do exemplo Gerenciamento de trabalho de impressão e manutenção de impressora demonstra a manutenção da impressora com o arquivo DeviceMaintenance.xaml.cs no projeto DeviceAppForPrinters2. Para trabalhar com Bidi, o exemplo usa a biblioteca de extensão de impressora no projeto PrinterExtensionLibrary. A biblioteca de extensão de impressora fornece uma maneira conveniente de acessar as interfaces de extensão de impressora do driver de impressão v4. Para obter mais informações, consulte Visão geral da biblioteca de extensões de impressora.

Os exemplos de código mostrados neste tópico são baseados na versão de C# do exemplo Gerenciamento de trabalho de impressão e manutenção de impressora. Este exemplo também está disponível em JavaScript e C++. Como o C++ pode acessar o COM diretamente, a versão de C++ do exemplo não inclui projetos de biblioteca de códigos. Baixe os exemplos para ver as versões mais recentes do código.

Gerenciando trabalhos de impressão

O Windows 8.1 apresenta novas interfaces de extensão de impressora no driver de impressora v4 que você pode usar para gerenciar trabalhos de impressão: IPrinterQueue2, IPrinterQueueView, IPrinterQueueViewEvent, IPrintJob e IPrintJobCollection. Essas interfaces permitem monitorar e cancelar trabalhos de impressão. Para obter mais informações, consulte Gerenciamento de trabalho de impressão (driver de impressora v4).

Os aplicativos C# e JavaScript não podem funcionar diretamente com APIs COM. Se você estiver escrevendo um aplicativo de dispositivo UWP C# ou JavaScript, use a biblioteca de extensões de impressora para acessar essas interfaces (conforme mostrado neste tópico).

Pré-requisitos

Antes de começar:

  1. Verifique se a impressora está instalada usando um driver de impressão v4. Para obter mais informações, consulte Desenvolvendo drivers de impressão v4.

  2. Obtenha a configuração de seu computador de desenvolvimento. Consulte Introdução para obter informações sobre como baixar as ferramentas e criar uma conta de desenvolvedor.

  3. Associar seu aplicativo à loja. Consulte Criar um aplicativo de dispositivo UWP para obter informações sobre isso.

  4. Crie metadados de dispositivo para sua impressora que os associem ao seu aplicativo. Consulte Criar metadados do dispositivo para saber mais sobre isso.

  5. Crie a interface do usuário para a página principal do seu aplicativo. Todos os aplicativos de dispositivo UWP podem ser iniciados pelo menu Início, em que serão exibidos em tela inteira. Use a experiência de Início para destacar seu produto ou serviços de uma maneira que corresponda à identidade visual e aos recursos específicos de seus dispositivos. Não há restrições especiais sobre o tipo de controles de interface do usuário que ele pode usar. Para começar a usar o design da experiência de tela inteira, consulte os princípios de design da Microsoft Store.

  6. Se você estiver escrevendo seu aplicativo com C# ou JavaScript, adicione o projeto PrinterExtensionLibrary à sua solução de aplicativo de dispositivo UWP. Você pode encontrar esse projeto no exemplo Gerenciamento de trabalho de impressão e manutenção de impressora.

Como o C++ pode acessar o COM diretamente, os aplicativos C++ não requerem uma biblioteca separada para trabalhar com o contexto do dispositivo de impressora baseado em COM.

Etapa 1: Localizar impressora

Para que seu aplicativo possa gerenciar trabalhos de impressão, primeiro ele deve localizar a impressora que tem os trabalhos de impressão. Para fazer isso, o exemplo Gerenciamento de trabalho de impressão e manutenção de impressora inclui uma classe útil denominada PrinterEnumeration (no arquivo PrinterEnumeration.cs). Essa classe localiza todas as impressoras associadas ao seu aplicativo por meio de metadados do dispositivo e retorna uma lista de objetos PrinterInfo, que contém os nomes e as IDs de dispositivo para cada impressora.

Este exemplo mostra o método EnumeratePrinters_Click no arquivo PrintJobManagement.xaml.cs. Ele mostra como o exemplo usa a classe PrinterEnumeration para obter uma lista de impressoras associadas.

private async void EnumeratePrinters_Click(object sender, RoutedEventArgs e)
{
    try
    {
        rootPage.NotifyUser("Enumerating printers. Please wait", NotifyType.StatusMessage);

        // Retrieve the running app's package family name, and enumerate associated printers.
        string currentPackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;

        // Enumerate associated printers.
        PrinterEnumeration pe = new PrinterEnumeration(currentPackageFamilyName);
        List<PrinterInfo> associatedPrinters = await pe.EnumeratePrintersAsync();

        // Update the data binding source on the combo box that displays the list of printers.
        PrinterComboBox.ItemsSource = associatedPrinters;
        if (associatedPrinters.Count > 0)
        {
            PrinterComboBox.SelectedIndex = 0;
            rootPage.NotifyUser(associatedPrinters.Count + " printers enumerated", NotifyType.StatusMessage);
        }
        else
        {
            rootPage.NotifyUser(DisplayStrings.NoPrintersEnumerated, NotifyType.ErrorMessage);
        }
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

Para obter mais informações sobre as classes PrinterEnumeration e PrinterInfo, consulte o arquivo PrinterEnumeration.cs.

Etapa 2: Obter fila de impressora

Depois que você identificar a impressora que tem os trabalhos de impressão que você deseja gerenciar, crie uma exibição dos trabalhos de impressão, com o objeto baseado na interface IPrinterQueueView (definida no arquivo PrinterExtensionTypes.cs do projeto PrinterExtensionLibrary). No exemplo Gerenciamento de trabalho de impressão e manutenção de impressora, esse objeto é denominado currentPrinterQueueView e recriado sempre que a seleção da impressora é alterada.

No método Printer_SelectionChanged, o exemplo primeiro usa um objeto PrinterInfo para criar um objeto de contexto de extensão de impressora denominado context. Em seguida, ele usa o método GetPrinterQueueView no context para criar o objeto currentPrinterQueueView. Finalmente, um manipulador de eventos é adicionado para lidar com o evento manipular o evento OnChanged do objeto currentPrinterQueueView.

Este exemplo mostra o método Printer_SelectionChanged no arquivo PrintJobManagement.xaml.cs. Ele mostra como criar um objeto de exibição de fila de impressora com base em IPrinterQueueView.

private void Printer_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    try
    {
        // Remove the current printer queue view (if any) before displaying the new view.
        if (currentPrinterQueueView != null)
        {
            currentPrinterQueueView.OnChanged -= OnPrinterQueueViewChanged;
            currentPrinterQueueView = null;
        }

        // Retrieve a COM IPrinterExtensionContext object, using the static WinRT factory.
        // Then instantiate one "PrinterExtensionContext" object that allows operations on the COM object.
        PrinterInfo queue = (PrinterInfo)PrinterComboBox.SelectedItem;
        Object comContext = Windows.Devices.Printers.Extensions.PrintExtensionContext.FromDeviceId(queue.DeviceId);
        PrinterExtensionContext context = new PrinterExtensionContext(comContext);

        // Display the printer queue view.
        const int FirstPrintJobEnumerated = 0;
        const int LastPrintJobEnumerated = 10;

        currentPrinterQueueView = context.Queue.GetPrinterQueueView(FirstPrintJobEnumerated, LastPrintJobEnumerated);
        currentPrinterQueueView.OnChanged += OnPrinterQueueViewChanged;
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

Além disso, sempre que houver uma alteração na exibição dos trabalhos de impressão, um manipulador de eventos chamará o método OnPrinterQueueViewChanged. Esse método é responsável por associar novamente o PrintJobListBox a uma coleção IEnumerable de objetos IPrintJob. A coleção é passada para o método por meio do objeto PrinterQueueViewEventArgs, que é definido no arquivo PrinterExtensionTypes.cs.

Este exemplo mostra o método OnPrinterQueueViewChanged no arquivo PrintJobManagement.xaml.cs.

private async void OnPrinterQueueViewChanged(object sender, PrinterQueueViewEventArgs e)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        // Update the data binding on the ListBox that displays print jobs.
        PrintJobListBox.ItemsSource = e.Collection;
        if (PrintJobListBox.Items.Count > 0)
        {
            // If there are print jobs in the current view, mark the first job as selected.
            PrintJobListBox.SelectedIndex = 0;
        }
    });
}

Etapa 3: Exibir o status do trabalho de impressão

Como o PrintJobListBox está vinculado a uma coleção de objetos IPrintJob, exibir o status de um trabalho é bastante simples. O trabalho de impressão selecionado é convertido como um objeto IPrintJob e, em seguida, as propriedades desse objeto são usadas para preencher a TextBox PrintJobDetails.

No exemplo Gerenciamento de trabalho de impressão e manutenção de impressora, o status do trabalho de impressão é exibido sempre que um trabalho de impressão diferente é selecionado. Essa atualização é feita pelo método PrintJob_SelectionChanged.

Este exemplo mostra o método PrintJob_SelectionChanged no arquivo PrintJobManagement.xaml.cs. Ele mostra como exibir o status de um trabalho de impressão, com base em um objeto IPrintJob.

private void PrintJob_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    try
    {
        // Display details of the selected print job.
        IPrintJob job = (IPrintJob)PrintJobListBox.SelectedItem;
        if (job != null)
        {
            PrintJobDetails.Text =
                "Details of print job: " + job.Name + "\r\n" +
                "Pages printed: " + job.PrintedPages + "/" + job.TotalPages + "\r\n" +
                "Submission time: " + job.SubmissionTime + "\r\n" +
                "Job status: " + DisplayablePrintJobStatus.ToString(job.Status);
        }
        else
        {
            PrintJobDetails.Text = "Please select a print job";
        }
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

Para ajudar a exibir a descrição do status do trabalho de impressão, o método PrintJob_SelectionChanged usa um dicionário estático, denominado printJobStatusDisplayNames, para ajudar a exibir as descrições de status do trabalho que estão em um formato de texto fácil de usar.

Este exemplo mostra a classe DisplayablePrintJobStatus no arquivo PrintJobManagement.xaml.cs. Essa classe contém os membros estáticos usados pelo método PrintJob_SelectionChanged.

internal class DisplayablePrintJobStatus
{
    /// <summary>
    /// Converts the PrintJobStatus bit fields to a display string.
    /// </summary>
    internal static string ToString(PrintJobStatus printJobStatus)
    {
        StringBuilder statusString = new StringBuilder();

        // Iterate through each of the PrintJobStatus bits that are set and convert it to a display string.
        foreach (var printJobStatusDisplayName in printJobStatusDisplayNames)
        {
            if ((printJobStatusDisplayName.Key & printJobStatus) != 0)
            {
                statusString.Append(printJobStatusDisplayName.Value);
            }
        }

        int stringlen = statusString.Length;
        if (stringlen > 0)
        {
            // Trim the trailing comma from the string.
            return statusString.ToString(0, stringlen - 1);
        }
        else
        {
            // If no print job status field was set, display "Not available".
            return "Not available";
        }
    }

    /// <summary>
    /// Static constructor that initializes the display name for the PrintJobStatus field.
    /// </summary>
    static DisplayablePrintJobStatus()
    {
        printJobStatusDisplayNames = new Dictionary<PrintJobStatus, string>();

        printJobStatusDisplayNames.Add(PrintJobStatus.Paused, "Paused,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Error, "Error,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Deleting, "Deleting,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Spooling, "Spooling,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Printing, "Printing,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Offline, "Offline,");
        printJobStatusDisplayNames.Add(PrintJobStatus.PaperOut, "Out of paper,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Printed, "Printed,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Deleted, "Deleted,");
        printJobStatusDisplayNames.Add(PrintJobStatus.BlockedDeviceQueue, "Blocked device queue,");
        printJobStatusDisplayNames.Add(PrintJobStatus.UserIntervention, "User intervention required,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Restarted, "Restarted,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Complete, "Complete,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Retained, "Retained,");
    }
    
    /// <summary>
    /// Private constructor to prevent default instantiation.
    /// </summary>
    private DisplayablePrintJobStatus() { }

    /// <summary>
    /// Contains the mapping between PrintJobStatus fields and display strings.
    /// </summary>
    private static Dictionary<PrintJobStatus, string> printJobStatusDisplayNames;
}

Etapa 4: Cancelar o trabalho de impressão

Semelhante à exibição do status do trabalho de impressão, cancelar um trabalho de impressão é bastante simples quando você tem um objeto IPrintJob. A classe IPrintJob fornece um método RequestCancel que inicia o cancelamento do trabalho de impressão correspondente. Isso é demonstrado no método CancelPrintJob_Click do exemplo.

Este exemplo mostra o método CancelPrintJob_Click no arquivo PrintJobManagement.xaml.cs.

private void CancelPrintJob_Click(object sender, RoutedEventArgs e)
{
    try
    {
        IPrintJob job = (IPrintJob)PrintJobListBox.SelectedItem;
        job.RequestCancel();
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

Testando

Para que você possa testar seu aplicativo de dispositivo UWP, ele deve estar vinculado à impressora usando metadados do dispositivo.

Você precisa de uma cópia do pacote de metadados do dispositivo para sua impressora, a fim de adicionar as informações do aplicativo do dispositivo a ele. Se você não tiver metadados de dispositivo, poderá criá-los usando o Assistente de Criação de Metadados de Dispositivo, conforme descrito no tópico Criar metadados de dispositivo para seu aplicativo de dispositivo UWP.

Para usar o Assistente de Criação de Metadados de Dispositivo, você deve instalar o Microsoft Visual Studio Professional, o Microsoft Visual Studio Ultimate ou o SDK autônomo para Windows 8.1, antes de concluir as etapas neste tópico. A instalação do Microsoft Visual Studio Express para Windows instala uma versão do SDK que não inclui o assistente.

As etapas a seguir criam seu aplicativo e instalam os metadados do dispositivo.

  1. Habilite a assinatura para teste.

    1. Inicie o Assistente de Criação de Metadados de Dispositivo em %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86, clicando duas vezes DeviceMetadataWizard.exe

    2. No menu Ferramentas, selecione Habilitar Assinatura para Teste.

  2. Reinicialize o computador

  3. Crie a solução abrindo o arquivo de solução (.sln). Pressione F7 ou vá para Criar->Criar Solução no menu superior depois que o exemplo foi carregado.

  4. Desconecte e desinstale a impressora. Esta etapa será requerida para que o Windows leia os metadados de dispositivo atualizados na próxima vez que o dispositivo for detectado.

  5. Edite e salve o metadados do dispositivo. Para vincular o aplicativo de dispositivo ao seu dispositivo, você deve associá-lo ao seu dispositivo.

    Se você ainda não criou os metadados do dispositivo, consulte Criar metadados de dispositivo para seu aplicativo de dispositivo UWP.

    1. Se o Assistente de Criação de Metadados de Dispositivo ainda não estiver aberto, inicie-o em %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86, clicando duas vezes em DeviceMetadataWizard.exe.

    2. Clique em Editar metadados do dispositivo. Isso permitirá que você edite o pacote de metadados do dispositivo existente.

    3. Na caixa de diálogo Abrir, localize o pacote de metadados do dispositivo associado ao seu aplicativo de dispositivo UWP. (Ele tem uma extensão de arquivo devicemetadata-ms.)

    4. Na página Especificar informações do aplicativo de dispositivo UWP, insira as informações do aplicativo da Microsoft Store na caixa Aplicativo de dispositivo UWP. Clique em Importar arquivo de manifesto do aplicativo UWP para inserir automaticamente o Nome do pacote, o Nome do editor e a ID de aplicativo UWP.

    5. Se seu aplicativo estiver registrado para receber notificações de impressora, preencha a caixa Manipuladores de notificação. Em ID do evento, insira o nome do manipulador de eventos de impressão. Em Ativo de Evento, insira o nome do arquivo em que esse código reside.

    6. Quando terminar, clique em Avançar até chegar à página Concluir.

    7. Na página Revisar o pacote de metadados do dispositivo, verifique se todas as configurações estão corretas e marque a caixa de seleção Copiar o pacote de metadados de dispositivo para o repositório de metadados no computador local. Em seguida, clique em Salvar.

  6. Reconecte a impressora para que o Windows leia os metadados atualizados do dispositivo quando ele está conectado.

Gerenciamento de trabalho (driver de impressora v4)

Desenvolvendo drivers de impressão v4

Comunicação bidirecional

Introdução aos aplicativos UWP

Criar um aplicativo de dispositivo UWP (guia passo a passo)

Criar metadados de dispositivo para um aplicativo de dispositivo UWP (guia passo a passo)