Partilhar via


Como personalizar configurações de impressão (aplicativos de dispositivo UWP)

No Windows 8.1, os aplicativos de dispositivo UWP permitem que os fabricantes de impressora personalizem o submenu que exibe as configurações de impressão avançadas. Este tópico apresenta o submenu de configurações de impressão avançadas e mostra como a versão C# do exemplo de Configurações de impressão e notificações de impressão substitui o submenu padrão por um submenu personalizado. Para saber mais sobre aplicativos de dispositivo UWP em geral, consulte Conhecer os aplicativos de dispositivo UWP.

A versão C# do exemplo Configurações de impressão e notificações usa a página Preferences.xaml para demonstrar a interface do usuário de um submenu personalizado para configurações de impressão avançadas. Uma classe auxiliar de impressão é usada para criar um contexto de dispositivo (IPrinterExtensionContext) e executar as consultas de dispositivo. O arquivo PrinterHelperClass.cs está no projeto DeviceAppForPrintersLibrary e usa APIs definidas 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.

Observação

Os exemplos de código mostrados neste tópico são baseados na versão C# do exemplo Configurações de impressão e notificações de impressão. 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.

Configurações de impressão avançadas

A experiência de configurações de impressão avançadas é a funcionalidade que uma impressora oferece quando um usuário deseja selecionar configurações de impressão que não são oferecidas na janela Imprimir. Ela está acessível por meio do link Mais configurações na janela Imprimir. Ela não é uma experiência de tela inteira, mas é exibida em um submenu, que é um controle para exibir uma interface de usuário contextual leve que é descartada quando um usuário clica ou toca fora dela.

Essa experiência pode ser usada para destacar recursos diferenciados para a impressora, como o recurso para aplicar marcas-d'água a uma página de documento, oferecer opções de impressão seguras ou opções de aprimoramento de imagem.

Quando um aplicativo de dispositivo UWP não está instalado para uma impressora, o Windows fornece uma experiência de configurações de impressão padrão. Se o Windows detectar que um aplicativo de dispositivo UWP está instalado para sua impressora e que o aplicativo aceitar a extensão windows.printTaskSettings, seu aplicativo substituirá a experiência padrão fornecida pelo Windows.

Para invocar o submenu para configurações de impressão avançadas:

  1. Abra um aplicativo UWP que ofereça suporte à impressão.

  2. Acesse os botões passando o dedo no lado direito da tela (ou usando a tecla do logotipo do Windows + C).

  3. Toque no botão Dispositivos.

  4. Toque em Imprimir.

  5. Toque em uma impressora.

  6. A janela Imprimir é aberta.

  7. Clique no link Mais configurações na janela Imprimir.

  8. O submenu de configurações de impressão avançadas é aberto.

    • O submenu padrão é exibido quando nenhum aplicativo de dispositivo UWP para a impressora estiver instalado.

    • Um submenu personalizado é exibido quando um aplicativo de dispositivo UWP para a impressora estiver instalado.

examples of the default and custom flyouts for advanced print settings.

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 os projetos PrinterExtensionLibrary e DeviceAppForPrintersLibrary à sua solução de aplicativo de dispositivo UWP. Você pode encontrar cada um desses projetos no exemplo Configurações de impressão e notificações de impressão.

Observação

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: Registrar a extensão

Para que o Windows reconheça que o aplicativo pode fornecer um submenu personalizado para configurações de impressão avançadas, o aplicativo deve registrar a extensão de configurações da tarefa de impressão. Essa extensão é declarada em um elemento Extension, com um atributo Category definido como um valor de windows.printTaskSettings. Nos exemplos de C# e C++, o atributo Executable é definido como $targetnametoken$.exe, e o atributo EntryPoint é definido como DeviceAppForPrinters.App.

Você pode adicionar a extensão de configurações da tarefa de impressão na guia Declarações do Designer de Manifesto no Microsoft Visual Studio. Você também pode editar o XML de manifesto do pacote de aplicativos manualmente, usando o Editor XML (Texto). Clique com o botão direito do mouse no arquivo Package.appxmanifest no Gerenciador de Soluções para editar as opções.

Este exemplo mostra a extensão de configurações da tarefa de impressão no elemento Extension, como aparece no arquivo de manifesto do pacote de aplicativos, Package.appxmanifest.

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
  <Identity Name="Microsoft.SDKSamples.DeviceAppForPrinters.CS" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="1.0.0.0" />
  <Properties>
    <DisplayName>Device App For Printers C# sample</DisplayName>
    <PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
    <Logo>Assets\storeLogo-sdk.png</Logo>
  </Properties>
  <Prerequisites>
    <OSMinVersion>6.3.0</OSMinVersion>
    <OSMaxVersionTested>6.3.0</OSMaxVersionTested>
  </Prerequisites>
  <Resources>
    <Resource Language="x-generate" />
  </Resources>
  <Applications>
    <Application Id="DeviceAppForPrinters" Executable="$targetnametoken$.exe" EntryPoint="DeviceAppForPrinters.App">
      <VisualElements DisplayName="Device App For Printers C# sample" Logo="Assets\squareTile-sdk.png" SmallLogo="Assets\smallTile-sdk.png" Description="DeviceAppForPrinters C# sample" ForegroundText="light" BackgroundColor="#00b2f0" ToastCapable="true">
<DefaultTile ShowName="allLogos" ShortName="App4PrinterCS" WideLogo="Assets\tile-sdk.png" />
<SplashScreen Image="Assets\splash-sdk.png" BackgroundColor="#00b2f0" />
      </VisualElements>
      <Extensions>
<Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTask.PrintBackgroundTask">
  <BackgroundTasks>
    <Task Type="systemEvent" />
  </BackgroundTasks>
</Extension>
<Extension Category="windows.printTaskSettings" Executable="$targetnametoken$.exe" EntryPoint="DeviceAppForPrinters.App" />
      </Extensions>
    </Application>
  </Applications>
</Package>

Etapa 2: Criar a interface do usuário

Antes de criar o aplicativo, você deve trabalhar com seus designers e sua equipe de marketing para projetar a experiência do usuário. A experiência do usuário deve projetar os aspectos de identidade visual da sua empresa e ajudá-lo a criar uma conexão com seus usuários.

Diretrizes de design

É importante revisar as diretrizes do submenu do aplicativo UWP antes de criar seu submenu personalizado. As diretrizes ajudam a garantir que o submenu forneça uma experiência intuitiva consistente com outros aplicativos UWP.

Para a página principal do aplicativo, tenha em mente que o Windows 8.1 pode exibir múltiplos aplicativos de vários tamanhos em um único monitor. Consulte as diretrizes a seguir para saber mais sobre como o aplicativo pode refluir normalmente entre tamanhos de tela, tamanhos de janela e orientações.

Dimensões do submenu

O submenu que exibe as configurações de impressão avançadas tem 646 pixels de largura e pelo menos 768 pixels de altura (a altura real depende da resolução da tela do usuário). O botão Voltar na área de título do submenu é fornecido pelo Windows. O texto "Título do aplicativo" é o título do aplicativo proveniente do manifesto do aplicativo. A área de título tem 80 pixels de altura, deixando 688 pixels para a área visível do submenu personalizado.

flyout dimensions for advanced printer settings.

Observação

Se o submenu personalizado tiver mais de 688 pixels de altura, o usuário poderá deslizar ou rolar para exibir as partes do submenu que estão acima ou abaixo da área visível.

Definindo a cor e o ícone do título do aplicativo

O título, a cor da tela de fundo, a cor do texto e o logotipo pequeno no submenu personalizado são retirados do elemento VisualElements no arquivo de manifesto do pacote de aplicativo.

Este exemplo mostra o título e o ícone, conforme definido no elemento VisualElements, no arquivo de manifesto do pacote de aplicativo (Package.appxmanifest).

      <VisualElements DisplayName="Device App For Printers C# sample" Logo="Assets\squareTile-sdk.png" SmallLogo="Assets\smallTile-sdk.png" Description="DeviceAppForPrinters C# sample" ForegroundText="light" BackgroundColor="#00b2f0" ToastCapable="true">
        <DefaultTile ShowName="allLogos" ShortName="App4PrinterCS" WideLogo="Assets\tile-sdk.png" />
        <SplashScreen Image="Assets\splash-sdk.png" BackgroundColor="#00b2f0" />
      </VisualElements>

Práticas recomendadas

  • Mantenha a mesma aparência. Alinhe seu submenu personalizado com o design da sua experiência de Iniciar (a página principal do aplicativo), incluindo elementos como fontes, cores e controles. O aplicativo deve parecer familiar para as pessoas, independentemente de onde ele for invocado.

  • Mantenha as interações simples. Evite interações demoradas ou complexas. Na maioria dos casos, ações como configurar uma impressora, exibir status, solicitar tinta e solucionar problemas são melhor executadas dentro da experiência Iniciar.

  • Mantenha a navegação em um mínimo. Evite fazer com que os usuários avancem e voltem entre várias páginas no submenu personalizado. Em vez disso, use os controles de rolagem vertical ou embutidos, como controles de divulgação progressiva, listas suspensas e mensagens de erro embutidas.

  • Não use submenus light dismiss. A experiência de impressão já usa um submenu light dismiss. A inclusão de outro elemento light dismiss em seu submenu personalizado pode confundir os usuários.

  • Desabilite os links que afastam os usuários da experiência de impressão. Quando um usuário está imprimindo conteúdo, você deve tomar medidas para garantir que eles permaneçam no contexto de impressão. Por exemplo, se seu aplicativo tiver links que levam a outras áreas do aplicativo (como a uma home page ou a uma página para comprar tinta), desative-os para que o usuário não saia da experiência de configurações de impressão avançadas acidentalmente.

Etapa 3: Manipular a ativação

Se o aplicativo tiver declarado a extensão de configurações da tarefa de impressão, deverá implementar um método OnActivated para manipular o evento Activation do aplicativo. A ativação do aplicativo ocorre quando seu aplicativo pode escolher qual página será iniciada quando o aplicativo for iniciado. Para aplicativos que declararam a extensão de configurações de tarefa de impressão, o Windows transmite o contexto da extensão de tarefa de impressão nos argumentos de evento Activated: Windows.ApplicationModel.Activation.IActivatedEventArgs.

Um aplicativo de dispositivo UWP pode determinar que a ativação se destina a configurações de impressão avançadas (que alguém acabou de tocar em Mais opções na caixa de diálogo de configurações de impressão) quando a propriedade kind do argumento do evento é igual a Windows.ApplicationModel.Activation.ActivationKind.printTaskSettings.

Observação

Em alguns casos, se o usuário descartar o aplicativo logo depois que ele for iniciado, uma exceção poderá ser lançada dentro do manipulador de ativação. Para evitar isso, verifique se o manipulador de ativação é concluído com eficiência e não executa o processamento que consome muitos recursos.

Este exemplo mostra o manipulador de eventos de ativação no método OnActivated, como ele é exibido no arquivo Constants.cs. Os argumentos do evento são então convertidos como Windows.ApplicationModel.Activation.PrintTaskSettingsActivatedEventArgs. Embora o exemplo inclua esse código no arquivo Constants.cs, na verdade faz parte da classe App que também é definida no arquivo App.xaml.cs.

partial class App : Application
{
    protected override void OnActivated(IActivatedEventArgs args)
    {
        if (args.Kind == ActivationKind.PrintTaskSettings)
        {
            Frame rootFrame = new Frame();
            if (null == Window.Current.Content)
            {
                rootFrame.Navigate(typeof(MainPage));
                Window.Current.Content = rootFrame;
            }
            Window.Current.Activate();

            MainPage mainPage = (MainPage)rootFrame.Content;

            // Load advanced printer preferences scenario
            mainPage.LoadAdvancedPrintSettingsContext((PrintTaskSettingsActivatedEventArgs)args);
        }
    }
}

Etapa 4: Exibir configurações

Quando o método LoadAdvancedPrintSettingsContext é chamado, o contexto de configuração da tarefa de impressão é atribuído a variáveis da classe MainPage. Isso permitirá que o submenu personalizado acesse as configurações de impressão quando for iniciado.

Os argumentos de evento que são transmitidos para o método LoadAdvancedPrintSettingsContext expõem propriedades para acessar e controlar a impressora:

  • A propriedade args.configuration fornece um objeto do tipo Windows.Devices.Printers.Extensions.PrintTaskConfiguration. Esse objeto fornece acesso ao contexto de extensão de tarefa de impressão e também permite que você adicione um manipulador de eventos para atualizar o tíquete de impressão.
  • A propriedade args.configuration.printerExtensionContext fornece um objeto do tipo Windows.Devices.Printers.Extensions.PrinterExtensionContext. Esse objeto é um indicador para as interfaces PrinterExtensionLibrary para PrintSchema, PrintTicket e fila de impressão. Ele será nulo se nenhuma interface for exposta. Para obter mais informações, consulte Visão geral da biblioteca de extensões de impressora.

Este exemplo mostra o método LoadAdvancedPrintSettingsContext, como ele aparece no arquivo Constants.cs.

public PrintTaskConfiguration Config;
public Object Context;

public void LoadAdvancedPrintSettingsContext(PrintTaskSettingsActivatedEventArgs args)
{
    Config = args.Configuration;
    Context = Config.PrinterExtensionContext;
    LoadScenario(typeof(DeviceAppForPrinters.Preferences));
}

Na página do submenu personalizado, Preferences.xaml.cs, uma classe denominada rootPage, atua como um ponteiro para a classe MainPage para que o contexto da extensão da tarefa de impressão e o contexto do dispositivo da impressora possam ser acessados no submenu.

Este exemplo mostra o indicador em uma parte da classe Preferences, no arquivo Preferences.xaml.cs. Baixe o exemplo Configurações de impressão e notificações de impressão para ver o código completo.

public sealed partial class Preferences : SDKTemplate.Common.LayoutAwarePage
{
    // A pointer back to the main page.  
    MainPage rootPage = MainPage.Current;

    // To listen for save requests.
    PrintTaskConfiguration configuration;

    // To create the printer device context.
    Object printerExtensionContext;
    PrintHelperClass printHelper;

    // The features in this sample were chosen because they're available on a wide range of printer drivers.
    private string[] features = { "PageOrientation", "PageOutputColor", "PageMediaSize", "PageMediaType" };
    private string[] selections = { null, null, null, null };

    // . . .
    // . . .
    // . . .

Quando o construtor de página para Preferences.xaml.cs é chamado, os objetos são criados para o contexto de extensão da tarefa de impressão (um objeto PrintTaskConfiguration denominado configuration) para o contexto de dispositivo de impressora (um objeto PrintHelperClass denominado printHelper).

Depois que esses objetos são criados, o contexto de dispositivo de impressora é usado no método DisplaySettings para carregar TextBlocks e ComboBoxes. Observe que, ao contrário do JavaScript, as alterações na seleção não são disparadas no mesmo thread que o restante do aplicativo. Você precisa manter um cache local de seleções de usuário para usar posteriormente.

Este exemplo mostra o construtor de páginas do submenu personalizado, DisplaySettings, e outros métodos de página de submenu personalizado e outros métodos auxiliares no arquivo Preferences.xaml.cs.

public Preferences()
{
    this.InitializeComponent();

    configuration = rootPage.Config;
    printerExtensionContext = rootPage.Context;
    printHelper = new PrintHelperClass(printerExtensionContext);

    // Disable scenario navigation by hiding the scenario list UI elements
    ((UIElement)rootPage.FindName("Scenarios")).Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    ((UIElement)rootPage.FindName("ScenarioListLabel")).Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    ((UIElement)rootPage.FindName("DescriptionText")).Visibility = Windows.UI.Xaml.Visibility.Collapsed;

    DisplaySettings();
}


private void DisplaySettings(bool constraints=false)
{
    PrintOptions.Visibility = Windows.UI.Xaml.Visibility.Visible;
    WaitPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;

    // Fill in the drop-down select controls for some common printing features.
    TextBlock[] featureLabels = { PageOrientationLabel, PageOutputColorLabel, PageMediaSizeLabel, PageMediaTypeLabel };
    ComboBox[] featureBoxes = { PageOrientationBox, PageOutputColorBox, PageMediaSizeBox, PageMediaTypeBox };

    for (int i = 0; i < features.Length; i++)
    {
        // Only display a feature if it exists
        featureLabels[i].Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        featureBoxes[i].Visibility = Windows.UI.Xaml.Visibility.Collapsed;

        string feature = features[i];

        // Check whether the currently selected printer's capabilities include this feature.
        if (!printHelper.FeatureExists(feature))
        {
            continue;
        }

        // Fill in the labels so that they display the display name of each feature.
        featureLabels[i].Text = printHelper.GetFeatureDisplayName(feature);
        string[] index = printHelper.GetOptionInfo(feature, "Index");
        string[] displayName = printHelper.GetOptionInfo(feature, "DisplayName");
        string selectedOption = printHelper.GetSelectedOptionIndex(feature);

        // Unless specified, do not get constraints
        bool[] constrainedList = constraints ? printHelper.GetOptionConstraints(feature) : new bool[index.Length];

        // Populate the combo box with the options for the current feature.
        PopulateBox(featureBoxes[i], index, displayName, selectedOption, constrainedList);
        selections[i] = selectedOption;

        // Every time the selection for a feature changes, we update our local cached set of selections.
        featureBoxes[i].SelectionChanged += OnFeatureOptionsChanged;

        // Show existing features
        featureLabels[i].Visibility = Windows.UI.Xaml.Visibility.Visible;
        featureBoxes[i].Visibility = Windows.UI.Xaml.Visibility.Visible;
    }
}

void PopulateBox(ComboBox box, string[] index, string[] displayName, string selectedOption, bool[] constrainedList)
{
    // Clear the combobox of any options from previous UI refresh before repopulating it.
    box.SelectionChanged -= OnFeatureOptionsChanged;
    box.Items.Clear();
    // There should be only one displayName for each possible option.
    if (index.Length == displayName.Length)
    {
        for (int i = 0; i < index.Length; i++)
        {
            // Create a new DisplayItem so the user will see the friendly displayName instead of the index.
            ComboBoxItem newItem = new ComboBoxItem();
            newItem.Content = displayName[i];
            newItem.DataContext = index[i];
            newItem.Foreground = constrainedList[i] ? new SolidColorBrush(Colors.Red) : new SolidColorBrush(Colors.Black);
            box.Items.Add(newItem);

            // Display current selected option as selected in the combo box.
            if (selectedOption == index[i])
            {
                box.SelectedIndex = i;
                box.Foreground = newItem.Foreground;
            }
        }
    }
}

private void OnFeatureOptionsChanged(object sender, SelectionChangedEventArgs args)
{
    ComboBox comboBox = sender as ComboBox;

    for (int i = 0; i < features.Length; i++)
    {
        if (features[i] + "Box" == comboBox.Name)
        {
            selections[i] = (comboBox.SelectedItem as ComboBoxItem).DataContext as string;
        }
    }
}

Etapa 5: Salvar configurações

Quando o usuário terminar de definir as configurações de impressão avançadas, o aplicativo de dispositivo da Microsoft Store precisará salvar as alterações antes que o usuário volte para a janela Imprimir. Para fazer isso, o aplicativo precisa escutar quando o usuário tocar no botão Voltar (na página do submenu personalizado). Quando isso acontece, o evento SaveRequested do contexto de extensão da tarefa de impressão (o objeto configuration) é acionado.

Este exemplo mostra o ouvinte de eventos para SaveRequested, sendo adicionado ao manipulador de eventos OnNavigatedTo do submenu personalizado, no arquivo Preferences.xaml.cs. Quando o evento SaveRequested for acionado, o método OnSaveRequested será invocado (esse método também está no arquivo Preferences.xaml.cs).

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (null == configuration)
    {
        rootPage.NotifyUser("Configuration arguments cannot be null", NotifyType.ErrorMessage);
        return;
    }

    // Add an event listener for saverequested (the back button of the flyout is pressed).
    configuration.SaveRequested += OnSaveRequested;
}

No método OnSaveRequested, o aplicativo primeiro usa o objeto printHelper para definir as opções atualmente selecionadas para cada recurso no contexto de extensão da impressora. Em seguida, ele chama o método Save no objeto request que é transmitido como um argumento para o método OnSaveRequested. O método Save, da classe Windows.Devices.Printers.Extensions.PrintTaskConfigurationSaveRequest, usa o contexto de extensão de impressora para validar o tíquete de impressão e salvar a configuração da tarefa de impressão.

Importante

Se o tíquete de impressão for inválido de alguma forma, o método Save lançará uma exceção que o aplicativo deve manipular. Se o aplicativo não lidar com a exceção, o fluxo será interrompido, forçando o usuário a fazer um light dismiss do submenu e reiniciar o fluxo de impressão.

Este exemplo mostra o método OnSaveRequested no arquivo Preferences.xaml.cs. Como o evento SaveRequested não é gerado no thread da interface do usuário, precisará usar um Windows.UI.Core.CoreDispatcher para postar mensagens no thread da interface do usuário para exibir as mensagens apropriadas enquanto valida e salva o tíquete.

async private void OnSaveRequested(object sender, PrintTaskConfigurationSaveRequestedEventArgs args)
{
    if (null == printHelper || null == printerExtensionContext || null == args)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser("onSaveRequested: args, printHelper, and context cannot be null", NotifyType.ErrorMessage);
        });
        return;
    }

    // Get the request object, which has the save method that allows saving updated print settings.
    PrintTaskConfigurationSaveRequest request = args.Request;

    if (null == request)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser("onSaveRequested: request cannot be null", NotifyType.ErrorMessage);
        });
        return;
    }

    PrintTaskConfigurationSaveRequestedDeferral deferral = request.GetDeferral();

    // Two separate messages are dispatched to:
    // 1) put up a popup panel,
    // 2) set the each options to the print ticket and attempt to save it,
    // 3) tear down the popup panel if the print ticket could not be saved.
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        PrintOptions.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        WaitPanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
    });

    // Go through all the feature select elements, look up the selected
    // option name, and update the context
    // for each feature
    for (var i = 0; i < features.Length; i++)
    {
        // Set the feature's selected option in the context's print ticket.
        // The printerExtensionContext object is updated with each iteration of this loop
        printHelper.SetFeatureOption(features[i], selections[i]);
    }

    bool ticketSaved;
    try
    {
        // This save request will throw an exception if ticket validation fails.
        // When the exception is thrown, the app flyout will remain.
        // If you want the flyout to remain regardless of outcome, you can call
        // request.Cancel(). This should be used sparingly, however, as it could
        // disrupt the entire the print flow and will force the user to
        // light dismiss to restart the entire experience.
        request.Save(printerExtensionContext);

        if (configuration != null)
        {
            configuration.SaveRequested -= OnSaveRequested;
        }
        ticketSaved = true;
    }
    catch (Exception exp)
    {
        // Check if the HResult from the exception is from an invalid ticket, otherwise rethrow the exception
        if (exp.HResult.Equals(unchecked((int)0x8007000D))) // E_INVALID_DATA
        {
            ticketSaved = false;
        }
        else
        {
            throw;
        }
    }

    // If ticket isn't saved, refresh UI and notify user
    if (!ticketSaved)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser("Failed to save the print ticket", NotifyType.ErrorMessage);
            DisplaySettings(true);
        });
    }
    deferral.Complete();
}

Salvando opções que exigem entrada de usuário

O exemplo Configurações de impressão e notificações de impressão demonstra como especificar os recursos definidos, o que abrange a maioria das opções de impressão. No entanto, algumas opções requerem uma interface do usuário personalizada para obter um valor especificado pelo usuário. Por exemplo, se um aplicativo tiver usado as configurações de impressão avançadas para especificar um tamanho de página personalizado, ele seguirá estas etapas para salvar o valor especificado pelo usuário:

  1. Recupere o tíquete de impressão durante a ativação do aplicativo. A ativação do aplicativo para configurações de impressão está descrita anteriormente na Etapa 3: Manipular a ativação.

  2. Verifique se a opção de tamanho de página está especificada. Em um aplicativo C# ou JS, a classe auxiliar de impressão pode verificar essa opção. Em um aplicativo C++, chame QueryInterface em IPrintSchemaOption para recuperar IPrintSchemaPageMediaSizeOption.

    Este exemplo mostra um método em uma classe auxiliar de impressão que verifica se a opção de tamanho de página está especificada.

    public bool ShouldShowCustomUI(string index)
    {
        if (null != index)
        {
            string feature = "PageMediaSize";
            int i = int.Parse(index);
            IPrintSchemaOption selectedOption = GetCachedFeatureOptions(feature)[i];
            if (selectedOption.Name.Equals("CustomMediaSize", StringComparison.CurrentCulture)
                || selectedOption.Name.Equals("PSCustomMediaSize", StringComparison.CurrentCulture))
            {
                return true;
            }
        }
        return false;
    }
    
  3. No submenu personalizado, exiba uma interface do usuário personalizada que solicite ao usuário a altura e a largura da página e recupere a altura e a largura especificadas pelo usuário de IPrintSchemaPageMediaSizeOption.

    Este exemplo mostra um método para um submenu personalizado que solicita ao usuário a altura e a largura da página.

    private void ShowCustomPageMediaSizeUI(string index, bool keepValue)
    {
        //Hide custom media size UI unless needed
        if (IsCustomSizeSelected(index))
        {
           if (keepValue && (!customWidth.Equals("")) && (!customHeight.Equals("")))
           {
                        CustomWidthBox.Text = customWidth;
                        CustomHeightBox.Text = customHeight;
           }
           else
           {
              // Use a helper function from the WinRT helper component
              CustomWidthBox.Text = printHelper.GetCustomWidth(index);
              CustomHeightBox.Text = printHelper.GetCustomHeight(index);
           }
           CustomUIPanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
           CustomWidthBox.KeyDown += OnCustomValueEntered;
           CustomHeightBox.KeyDown += OnCustomValueEntered;
        }
        else
        {
           CustomUIPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
           CustomWidthBox.KeyDown -= OnCustomValueEntered;
           CustomHeightBox.KeyDown -= OnCustomValueEntered;
        }
    }
    
  4. Atualize o objeto IPrintSchemaPageMediaSizeOption com os valores especificados pelo usuário e valide se a altura e a largura correspondem aos valores especificados pelo usuário.

    Este exemplo é um método auxiliar para atualizar o objeto IPrintSchemaPageMediaSizeOption em uma classe auxiliar da impressora. O manipulador OnSaveRequested no submenu personalizado chamará essa função se determinar que uma opção de tamanho de página personalizada foi solicitada.

    public void SetCustomMediaSizeDimensions(string width, string height)
    {
      if ((null == width) && (null == height) && (null == Capabilities))
      {
                    return;
      }
      try
      {
                    CheckSizeValidity(width, height);
      }
      catch (FormatException e)
      {
                    throw new ArgumentException(e.Message);
      }
      catch (OverflowException e)
      {
                    throw new ArgumentException(e.Message);
      }
    
      // The context is retrieved during app activation.
      IPrintSchemaTicket ticket = context.Ticket;
    
      //
      // Input XML as Stream
      //
      XElement ticketRootXElement = null;
      using (Stream ticketReadStream = ticket.GetReadStream())
      {
         ticketRootXElement = XElement.Load(ticketReadStream);
      }
    
      XNamespace psfNs = PrintSchemaConstants.FrameworkNamespaceUri;
      XNamespace pskNs = PrintSchemaConstants.KeywordsNamespaceUri;
      string pskPrefix = ticketRootXElement.GetPrefixOfNamespace(pskNs);
    
      // Modify the MediaSizeHeight and MediaSizeWidth
      IEnumerable<XElement> parameterInitCollection =
        from c in ticketRootXElement.Elements(psfNs + "ParameterInit")
    
      select c;
    
      foreach (XElement parameterInit in parameterInitCollection)
      {
        if (0 == String.Compare((string)parameterInit.Attribute("name"), pskPrefix + ":PageMediaSizePSWidth"))
        {
          IEnumerable<XElement> valueCollection = from c in parameterInit.Elements(psfNs + "Value")
          select c;
          valueCollection.ElementAt(0).Value = width;
        }
    
         else if (0 == String.Compare((string)parameterInit.Attribute("name"), pskPrefix + ":PageMediaSizePSHeight"))
        {
          IEnumerable<XElement> valueCollection = from c in parameterInit.Elements(psfNs + "Value")
          select c;
          valueCollection.ElementAt(0).Value = height;
         }
      }
    
      //
      // Write XLinq changes back to DOM
      //
       using (Stream ticketWriteStream = ticket.GetWriteStream())
       {
         ticketRootXElement.Save(ticketWriteStream);
       }
    }
    

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.

    Observação

    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.

    Observação

    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.

Solução de problemas

Problema: configurações de impressão avançadas mostram o submenu padrão, em vez do submenu personalizado

Se o submenu de configurações de impressão avançadas mostrar o submenu padrão, em vez do submenu personalizado que seu aplicativo implementa...

  • Causa possível: a assinatura de teste não está ativada. Consulte a seção Depuração neste tópico para obter informações sobre como ativá-la.

  • Causa possível: o aplicativo não está consultando o Nome da Família de Pacotes correto. Verifique o Nome da Família de Pacotes em seu código. Abra package.appxmanifest no Visual Studio e verifique se o nome da família de pacotes que você está consultando corresponde ao especificado na guia Empacotamento, no campo Nome da Família de Pacotes.

  • Causa possível: os metadados do dispositivo não estão associados ao Nome da Família de Pacotes. Use o Assistente de Criação de Metadados de Dispositivo para abrir os metadados do dispositivo e verificar o nome da família de pacotes. Inicie o assistente em %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86, clicando duas vezes em DeviceMetadataWizard.exe.

Problema: aplicativo é iniciado no submenu e é imediatamente descartado

Se o submenu personalizado para configurações de impressão avançadas desaparecer imediatamente após ser iniciado...

  • Causa possível: no Windows 8, há um problema conhecido de que, em um submenu, os aplicativos UWP serão descartados no depurador. Desative a depuração quando você souber que a ativação funciona. Se você precisar depurar salvando o tíquete de impressão, anexe o depurador após a ativação.

Desenvolvendo drivers de impressão v4

Interfaces de extensão de impressora (driver 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)