Compartir a través de


Cómo personalizar la configuración de impresión (aplicaciones de dispositivos para UWP)

En Windows 8.1, las aplicaciones de dispositivos para UWP permiten a los fabricantes de impresoras personalizar el control flotante que muestra la configuración avanzada de impresión. En este tema se presenta el control flotante de configuración avanzada de impresión y se muestra cómo la versión de C# del ejemplo de Configuración de impresión y notificaciones de impresión reemplaza el control flotante predeterminado por un control flotante personalizado. Para obtener más información sobre las aplicaciones de dispositivos para UWP en general, consulte Conocer las aplicaciones de dispositivos para UWP.

La versión de C# del ejemplo Configuración de impresión y notificaciones de impresión usa la página Preferences.xaml para mostrar la interfaz de usuario de un control flotante personalizado para la configuración avanzada de impresión. Se usa una clase auxiliar de impresión para crear un contexto de dispositivo (IPrinterExtensionContext) y realizar las consultas del dispositivo. El archivo PrinterHelperClass.cs se encuentra en el proyecto DeviceAppForPrintersLibrary y usa las API definidas en el proyecto PrinterExtensionLibrary. La biblioteca de extensiones de impresora proporciona una manera cómoda de acceder a las interfaces de extensión de impresora del controlador de impresión v4. Para obtener más información, consulte Información general sobre la biblioteca de extensiones de impresora.

Nota:

Los ejemplos de código que se muestran en este tema se basan en la versión de C# del ejemplo Configuración de impresión y notificaciones de impresión. Este ejemplo también está disponible en JavaScript y C++. Tenga en cuenta que, dado que C++ puede acceder directamente a COM, la versión de C++ del ejemplo no incluye proyectos de biblioteca de código. Descargue los ejemplos para ver las versiones más recientes del código.

Configuración avanzada de impresión

La experiencia de configuración avanzada de impresión es la funcionalidad que ofrece una impresora cuando un usuario quiere seleccionar la configuración de impresión que no se ofrece en la ventana Imprimir. Se puede acceder a ella a través del vínculo Más opciones de configuración en la ventana Imprimir. Aunque no es una experiencia a pantalla completa, se muestra dentro de un control flotante, que es un control para mostrar una interfaz de usuario contextual ligera que se descarta cuando un usuario hace clic o pulsa fuera de él.

Esta experiencia se puede usar para resaltar características diferenciadas para su impresora, como la capacidad de aplicar marcas de agua a una página de documentos, ofrecer opciones de impresión segura u opciones de mejora de imágenes.

Cuando una aplicación de dispositivo para UWP no está instalada para una impresora, Windows proporciona una experiencia de configuración de impresión predeterminada. Si Windows detecta que hay instalada una aplicación de dispositivo para UWP para la impresora y que la aplicación ha optado por la extensión windows.printTaskSettings, la aplicación reemplaza la experiencia predeterminada proporcionada por Windows.

Para invocar el control flotante para la configuración avanzada de impresión:

  1. Abrir una aplicación para UWP que admita la impresión

  2. Acceda a los accesos deslizando el dedo en el lado derecho de la pantalla (o mediante la tecla del logotipo de Windows + C)

  3. Toque el acceso Dispositivos.

  4. Toque Imprimir

  5. Toque una impresora

  6. Se abre la ventana Imprimir

  7. Haga clic en el vínculo Más opciones de configuración en la ventana Imprimir

  8. Se abre el control flotante de configuración avanzada de impresión

    • El control flotante predeterminado aparece cuando no hay instalada ninguna aplicación de dispositivo para UWP para la impresora

    • Aparece un control flotante personalizado cuando hay instalada una aplicación de dispositivo para UWP para la impresora

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

Requisitos previos

Antes de comenzar:

  1. Asegúrese de que la impresora esté instalada con un controlador de impresión v4. Para obtener más información, consulte Desarrollo de controladores de impresión v4.

  2. Configure su equipo de desarrollo. Consulte Introducción para obtener información sobre cómo descargar las herramientas y crear una cuenta de desarrollador.

  3. Asocie la aplicación con la tienda. Consulte Creación de una aplicación de dispositivo para UWP para obtener información.

  4. Cree metadatos de dispositivo para la impresora que la asocien con la aplicación. Consulte Creación de metadatos de dispositivo para obtener más información.

  5. Cree la interfaz de usuario para la página principal de la aplicación. Todas las aplicaciones de dispositivos para UWP se pueden iniciar desde Inicio, donde se mostrarán a pantalla completa. Use la experiencia de Inicio para resaltar el producto o los servicios de forma que coincida con la personalización de marca y las características específicas de los dispositivos. No hay restricciones especiales en cuanto al tipo de controles de interfaz de usuario que puede usar. Para empezar a trabajar con el diseño de la experiencia a pantalla completa, consulte los Principios de diseño de Microsoft Store.

  6. Si está escribiendo su aplicación con C# o JavaScript, agregue los proyectos PrinterExtensionLibrary y DeviceAppForPrintersLibrary a la solución de aplicación de dispositivo para UWP. Puede encontrar cada uno de estos proyectos en el ejemplo Configuración de impresión y notificaciones de impresión.

Nota:

Dado que C++ puede acceder directamente a COM, las aplicaciones de C++ no requieren una biblioteca independiente para trabajar con el contexto del dispositivo de impresora basado en COM.

Paso 1: Registrar la extensión

Para que Windows reconozca que la aplicación puede proporcionar un control flotante personalizado para la configuración avanzada de impresión, debe registrar la extensión de configuración de tareas de impresión. Esta extensión se declara en un elemento Extension, con un atributo Category establecido en un valor de windows.printTaskSettings. En los ejemplos de C# y C++, el atributo Executable se establece en $targetnametoken$.exe y el atributo EntryPoint se establece en DeviceAppForPrinters.App.

Puede agregar la extensión de configuración de la tarea de impresión en la pestaña Declaraciones del Diseñador de manifiestos en Microsoft Visual Studio. También puede editar el XML del manifiesto del paquete de la aplicación manualmente mediante el Editor XML (texto). Haga clic con el botón derecho en el archivo Package.appxmanifest, en el Explorador de soluciones, para ver las opciones de edición.

En este ejemplo se muestra la extensión de configuración de la tarea de impresión en el elemento Extension, tal como aparece en el archivo de manifiesto del paquete de la aplicación, 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>

Paso 2: Crear la interfaz de usuario

Antes de crear la aplicación, debe trabajar con los diseñadores y el equipo de marketing para diseñar la experiencia del usuario. La experiencia del usuario debe proyectar los aspectos de personalización de marca de su empresa y ayudarle a crear una conexión con los usuarios.

Guías de diseño

Es importante revisar las directrices de control flotante de la aplicación para UWP antes de diseñar el control flotante personalizado. Las directrices ayudan a garantizar que el control flotante proporcione una experiencia intuitiva que sea coherente con otras aplicaciones para UWP.

Para la página principal de la aplicación, tenga en cuenta que Windows 8.1 puede mostrar varias aplicaciones en varios tamaños en un solo monitor. Consulte las siguientes directrices para obtener más información sobre cómo su aplicación puede cambiar de tamaño de pantalla, tamaño de ventana y orientación.

Dimensiones de control flotante

El control flotante que muestra la configuración avanzada de impresión es de 646 píxeles de ancho y al menos 768 píxeles de alto (el alto real depende de la resolución de la pantalla del usuario). Windows proporciona el botón Atrás en el área de título del control flotante. El texto "Título de la aplicación" es el título de la aplicación del manifiesto de la aplicación. El área de título es de 80 píxeles de alto, dejando 688 píxeles para el área visible del control flotante personalizado.

flyout dimensions for advanced printer settings.

Nota:

Si el control flotante personalizado tiene más de 688 píxeles de altura, el usuario puede deslizarse o desplazarse para ver partes del control flotante que quedan por encima o por debajo del área visible.

Definición del color y el icono del título de la aplicación

El título, color de fondo, color de texto y el logotipo pequeño del control flotante personalizado se toman del elemento VisualElements del archivo de manifiesto del paquete de la aplicación.

En este ejemplo se muestra el título y el icono, tal como se definen en el elemento VisualElements, en el archivo de manifiesto del paquete de la aplicación (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>

procedimientos recomendados

  • Mantenga la misma apariencia. Alinee el control flotante personalizado con el diseño de la experiencia de Inicio (la página principal de la aplicación), incluidos elementos como fuentes, colores y controles. La aplicación debe resultar familiar a los usuarios, independientemente del lugar desde el que la invoquen.

  • Mantenga las interacciones sencillas. Evite las interacciones largas o complejas. En la mayoría de los casos, acciones como configurar una impresora, ver el estado, pedir tinta y solucionar problemas se realizan mejor dentro de la experiencia Inicio.

  • Reduzca la navegación al mínimo. Evite hacer que los usuarios naveguen hacia delante y hacia atrás entre varias páginas en el control flotante personalizado. En su lugar, utilice el desplazamiento vertical o controles en línea, como controles de divulgación progresiva, listas desplegables y mensajes de error en línea.

  • No use controles flotantes de cierre del elemento por cambio de foco. La experiencia de impresión ya usa un control flotante de cierre del elemento por cambio de foco. Incluir otro elemento de cierre del elemento por cambio de foco en el control flotante personalizado puede confundir a los usuarios.

  • Deshabilite los enlaces que alejan a los usuarios de la experiencia de impresión. Cuando un usuario está imprimiendo contenido, debe tomar medidas para asegurarse de que permanece en el contexto de impresión. Por ejemplo, si la aplicación tiene vínculos que llevan a otras áreas de su aplicación (como a una página de inicio o a una página para comprar tinta), debe deshabilitarlos para que el usuario no abandone accidentalmente la experiencia de configuración avanzada de impresión.

Paso 3: Controlar la activación

Si la aplicación tiene declarada la extensión de configuración de la tarea de impresión, debe implementar un método OnActivated para controlar el evento de activación de la aplicación. La activación de la aplicación consiste en que la aplicación puede elegir qué página se lanzará al iniciarse. En el caso de las aplicaciones que tienen declarada la extensión de configuración de la tarea de impresión, Windows transfiere el contexto de la extensión de la tarea de impresión en los argumentos del evento Activado: Windows.ApplicationModel.Activation.IActivatedEventArgs.

Una aplicación de dispositivo para UWP puede determinar que la activación está pensada para la configuración avanzada de impresión (que alguien acaba de pulsar Más opciones en el cuadro de diálogo de configuración de impresión) cuando la propiedad kind del argumento del evento es igual a Windows.ApplicationModel.Activation.ActivationKind.printTaskSettings.

Nota:

En algunos casos, si el usuario descarta la aplicación inmediatamente después de iniciarla, se puede producir una excepción dentro del controlador de activación. Para evitarlo, asegúrese de que el controlador de activación se completa de forma eficaz y no realiza un procesamiento intensivo de recursos.

En este ejemplo se muestra el controlador de eventos de activación en el método OnActivated, tal como aparece en el archivo Constants.cs. A continuación, los argumentos del evento se proyectan como Windows.ApplicationModel.Activation.PrintTaskSettingsActivatedEventArgs. Aunque el ejemplo incluye este código en el archivo Constants.cs, en realidad forma parte de la clase de la aplicación que también se define en el archivo 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);
        }
    }
}

Paso 4: Mostrar la configuración

Cuando se llama al método LoadAdvancedPrintSettingsContext, el contexto de configuración de la tarea de impresión se asigna a las variables de la clase MainPage. Esto permitirá que el control flotante personalizado acceda a la configuración de impresión cuando se inicie.

Los argumentos de evento que se transfieren al método LoadAdvancedPrintSettingsContext exponen las propiedades para acceder y controlar la impresora:

  • La propiedad args.configuration proporciona un objeto de tipo Windows.Devices.Printers.Extensions.PrintTaskConfiguration. Este objeto proporciona acceso al contexto de extensión de la tarea de impresión y también permite agregar un controlador de eventos para actualizar el vale de impresión.
  • La propiedad args.configuration.printerExtensionContext proporciona un objeto de tipo Windows.Devices.Printer.Extensions.PrinterExtensionContext. Este objeto es un puntero a las interfaces PrinterExtensionLibrary para la información sobre el esquema de impresión, PrintTicket y la cola de impresión. Será nulo si no se expone ninguna interfaz. Para obtener más información, consulte Información general sobre la biblioteca de extensiones de impresora.

En este ejemplo se muestra el método LoadAdvancedPrintSettingsContext, tal como aparece en el archivo Constants.cs.

public PrintTaskConfiguration Config;
public Object Context;

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

En la página de control flotante personalizada, Preferences.xaml.cs, una clase denominada rootPage actúa como puntero a la clase MainPage para que se pueda acceder al contexto de extensión de la tarea de impresión y al contexto del dispositivo de impresora desde el control flotante.

En este ejemplo se muestra el puntero en una parte de la clase Preferences del archivo Preferences.xaml.cs. Descargue el ejemplo Configuración de impresión y notificaciones de impresión para ver el 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 };

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

Cuando se llama al constructor de páginas para Preferences.xaml.cs , se crean objetos para el contexto de extensión de la tarea de impresión (un objeto PrintTaskConfiguration denominado configuration) y el contexto del dispositivo de impresora (un objeto PrintHelperClass denominado printHelper).

Una vez creados esos objetos, el contexto del dispositivo de impresora se usa en el método DisplaySettings para cargar TextBlocks y ComboBoxes. Tenga en cuenta que, a diferencia de JavaScript, los cambios en la selección no se activan en el mismo subproceso que el resto de la aplicación. Tiene que mantener una caché local de selecciones de usuario para usarlas más adelante.

En este ejemplo se muestra el constructor de página de control flotante personalizado, DisplaySettings y otros métodos auxiliares en el archivo 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;
        }
    }
}

Paso 5: Guardar la configuración

Cuando el usuario haya terminado de establecer la configuración avanzada de impresión, la aplicación de dispositivo de Microsoft Store debe guardar los cambios antes de que el usuario vuelva a la ventana Imprimir. Para ello, la aplicación debe escuchar cuándo el usuario pulsa el botón Atrás (desde la página de control flotante personalizada). Cuando esto sucede, se desencadena el evento SaveRequested del contexto de extensión de la tarea de impresión (el objeto configuration).

En este ejemplo se muestra el agente de escucha de eventos para SaveRequested, que se agrega en el controlador de eventos OnNavigatedTo del control flotante personalizado, en el archivo Preferences.xaml.cs. Cuando se desencadena el evento SaveRequested, se invocará el método OnSaveRequested (ese método también se encuentra en el archivo 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;
}

En el método OnSaveRequested, la aplicación usa primero el objeto printHelper para establecer las opciones seleccionadas actualmente para cada característica en el contexto de la extensión de impresora. A continuación, llama al método Save en el objeto request que se transfiere como argumento al método OnSaveRequested. El método Save, de la clase Windows.Devices.Printers.Extensions.PrintTaskConfigurationSaveRequest, usa el contexto de la extensión de impresora para validar el vale de impresión y guarda la configuración de la tarea de impresión.

Importante

Si el vale de impresión no es válido de ninguna manera, el método Save produce una excepción que la aplicación debe controlar. Si la aplicación no controla la excepción, se detiene el flujo, lo que obliga al usuario a cerrar el elemento por cambio de foco del control flotante y reiniciar el flujo de impresión.

En este ejemplo se muestra el método OnSaveRequested en el archivo Preferences.xaml.cs. Dado que el evento SaveRequested no se genera en el subproceso de la interfaz de usuario, debe usar Windows.UI.Core.CoreDispatcher para publicar mensajes en el subproceso de la interfaz de usuario para mostrar los mensajes adecuados al validar y guardar el vale.

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();
}

Guardado de opciones que requieren la entrada de usuario

En el ejemplo Configuración de impresión y notificaciones de impresión se muestra cómo establecer características definidas, que abarcan la mayoría de las opciones de impresión. Sin embargo, algunas opciones requieren una interfaz de usuario personalizada para obtener un valor especificado por el usuario. Por ejemplo, si una aplicación usa la configuración avanzada de impresión para especificar un tamaño de página personalizado, realizaría estos pasos para guardar el valor especificado por el usuario:

  1. Recuperar el vale de impresión durante la activación de la aplicación. La activación de la aplicación para la configuración de impresión se describe anteriormente en el Paso 3: Controlar la activación.

  2. Comprobar si se ha especificado la opción de tamaño de página. En una aplicación de C# o JS, la clase auxiliar de impresión puede comprobar esta opción. En una aplicación de C++, llama a QueryInterface en IPrintSchemaOption para recuperar IPrintSchemaPageMediaSizeOption.

    En este ejemplo se muestra un método en una clase auxiliar de impresión que comprueba si se ha especificado la opción de tamaño de página.

    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. En el control flotante personalizado, muestra una interfaz de usuario personalizada que solicita al usuario el alto y el ancho de la página, y recupera el alto y ancho especificados por el usuario de IPrintSchemaPageMediaSizeOption.

    En este ejemplo se muestra un método para un control flotante personalizado que solicita al usuario el alto y el ancho de la 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. Actualizar el objeto IPrintSchemaPageMediaSizeOption con los valores especificados por el usuario y comprobar que el alto y el ancho coinciden con los valores especificados por el usuario.

    Este ejemplo es un método auxiliar para actualizar el objeto IPrintSchemaPageMediaSizeOption en una clase auxiliar de impresora. El controlador OnSaveRequested del control flotante personalizado llamaría a esta función si determina que se ha solicitado una opción de tamaño de página personalizada.

    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);
       }
    }
    

Prueba

Para poder probar la aplicación de dispositivo para UWP, debe estar vinculada a la impresora mediante metadatos del dispositivo.

  • Necesita una copia del paquete de metadatos del dispositivo para la impresora, para agregarle la información de la aplicación del dispositivo. Si no tiene metadatos de dispositivo, puede crearlos mediante el Asistente para creación de metadatos de dispositivo, tal como se describe en el tema Creación de metadatos de dispositivo para la aplicación de dispositivo para UWP.

    Nota:

    Para usar el Asistente para creación de metadatos de dispositivo, debe instalar Microsoft Visual Studio Professional, Microsoft Visual Studio Ultimate o el SDK independiente para Windows 8.1, antes de completar los pasos de este tema. La instalación de Microsoft Visual Studio Express para Windows instala una versión del SDK que no incluye el asistente.

Los pasos siguientes permiten crear la aplicación e instalar los metadatos del dispositivo.

  1. Habilite la firma de pruebas.

    1. Inicie el Asistente para creación de metadatos de dispositivo desde %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86, haciendo doble clic en DeviceMetadataWizard.exe

    2. En el menú Herramientas, seleccione Habilitar firma de pruebas.

  2. Reinicie el equipo.

  3. Cree la solución abriendo el archivo de solución (.sln). Pulse F7 o vaya a Crear->Crear solución en el menú superior después de cargar el ejemplo.

  4. Desconecte y desinstale la impresora. Este paso es necesario para que Windows lea los metadatos del dispositivo actualizado la próxima vez que se detecte el dispositivo.

  5. Edite y guarde los metadatos del dispositivo. Para vincular la aplicación de dispositivo al dispositivo, debe asociar la aplicación de dispositivo al dispositivo

    Nota:

    Si aún no ha creado los metadatos del dispositivo, consulte Creación de metadatos de dispositivo para la aplicación de dispositivo para UWP.

    1. Si el Asistente para creación de metadatos de dispositivo todavía no está abierto, inícielo desde %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86, haciendo doble clic en DeviceMetadataWizard.exe.

    2. Haga clic en Editar metadatos del dispositivo. Esto le permitirá editar el paquete de metadatos del dispositivo existente.

    3. En el cuadro de diálogo Abrir, busque el paquete de metadatos del dispositivo asociado a la aplicación de dispositivo para UWP. (Tiene una extensión de archivo devicemetadata-ms).

    4. En la página Especificar información de la aplicación de dispositivo para UWP, escriba la información de la aplicación de Microsoft Store en el cuadro Aplicación de dispositivo para UWP. Haga clic en Importar archivo de manifiesto de aplicación para UWP para introducir automáticamente el Nombre del paquete, el Nombre del publicador y el Identificador de la aplicación para UWP.

    5. Si la aplicación está registrada para recibir notificaciones de impresora, rellene el cuadro Controladores de notificaciones. En Identificador de evento, escriba el nombre del controlador de eventos de impresión. En Recurso de evento, escriba el nombre del archivo donde reside ese código.

    6. Cuando haya terminado, haga clic en Siguiente hasta llegar a la página Finalizar.

    7. En la página Revisar el paquete de metadatos del dispositivo, asegúrese de que toda la configuración sea correcta y active la casilla Copiar el paquete de metadatos del dispositivo en el almacén de metadatos del equipo local. A continuación, haga clic en Save(Guardar).

  6. Vuelva a conectar la impresora para que Windows lea los metadatos del dispositivo actualizados cuando se conecte el dispositivo.

Solución de problemas

Problema: la configuración avanzada de impresión muestra el control flotante predeterminado en lugar del control flotante personalizado

Si el control flotante de configuración avanzada de impresión muestra el control flotante predeterminado en lugar del control flotante personalizado que implementa la aplicación...

  • Causa posible: la firma de prueba no está activada. Consulte la sección Depuración de este tema para obtener información sobre cómo activarla.

  • Causa posible: la aplicación no está consultando el nombre de familia de paquete adecuado. Compruebe el nombre de familia del paquete en el código. Abra package.appxmanifest en Visual Studio y asegúrese de que el nombre de familia de paquete que está consultando coincide con el de la pestaña Empaquetado, en el campo Nombre de familia de paquete.

  • Causa posible: los metadatos del dispositivo no están asociados con el nombre de familia de paquete. Use el Asistente para creación de metadatos de dispositivo para abrir los metadatos del dispositivo y comprobar el nombre de familia de paquete. Inicie el asistente desde %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86, haciendo doble clic en DeviceMetadataWizard.exe.

Problema: la aplicación se inicia en el control flotante y, a continuación, se descarta inmediatamente.

Si el control flotante personalizado para la configuración avanzada de impresión desaparece inmediatamente después de iniciarse...

  • Causa posible: en Windows 8, hay un problema conocido que, dentro de un control flotante, las aplicaciones para UWP se descartarán en el depurador. Desactive la depuración una vez que sepa que la activación funciona. Si necesita depurar el guardado del vale de impresión, asocie el depurador después de la activación.

Desarrollo de controladores de impresión v4

Interfaces de extensión de impresora (controlador de impresión v4)

Comunicaciones bidireccionales

Introducción a las aplicaciones para UWP

Creación de una aplicación de dispositivo para UWP (guía paso a paso)

Creación de metadatos de dispositivo para una aplicación de dispositivo para UWP (guía paso a paso)