Ontwerphandleiding voor Print Support App v1 en v2
Dit artikel bevat richtlijnen en voorbeelden voor printer-OEM's en IHD's voor het ontwikkelen van een printondersteunings-app (PSA) waarmee de afdrukervaring van een Windows-gebruiker op verschillende manieren kan worden verbeterd.
Belangrijk
Vanaf de release van Windows 11 SDK (22000.1) zijn Print Support Apps (PSA) de aanbevolen methode voor het ontwikkelen van UWP-apps voor printers. Als u een printondersteunings-app voor uw afdrukapparaat wilt ontwikkelen, downloadt en installeert u de Windows 11 SDK voor de Windows-versie die u wilt gebruiken.
Belangrijk
Dit artikel bevat secties waarin de PSA-functionaliteit wordt beschreven die beschikbaar is vanaf Windows 11, versie 22H2. Deze secties bevatten een opmerking die aangeeft dat deze van toepassing is op die versie.
Zie de volgende artikelen voor meer informatie:
Onderwerp | Beschrijving |
---|---|
ontwerphandleiding voor Print Support App v3 API | Biedt richtlijnen en voorbeelden voor printer-OEM's en IHD's die een v3 Print Support App (PSA) implementeren voor hun apparaat. |
ontwerphandleiding voor Print Support App v4 API | Biedt richtlijnen en voorbeelden voor printer-OEM's en IHD's die een v4 Print Support App (PSA) implementeren voor hun apparaat. |
MSIX-manifestspecificatie voor afdrukondersteuning van virtuele printers | Biedt richtlijnen en voorbeelden van MSIX-manifesten voor OEM's en IHV's van printers die een Print Support Virtuele Printer implementeren. |
Koppeling met app voor afdrukondersteuning | Bevat richtlijnen en voorbeelden voor het koppelen van een print support-app (PSA) aan een printer. |
Sommige printerfuncties worden niet weergegeven in afdrukdialoogvensters die door Windows worden weergegeven, omdat ze speciale functies zijn die hulp nodig hebben van een fabrikant-app om correct te worden geconfigureerd. Ze kunnen ook functies zijn die niet zijn opgegeven in de standaardmogelijkheden van de printer.
Printerspecifieke functies kunnen worden gegroepeerd op een manier waarmee de gebruiker eenvoudig een optie kan kiezen en vertrouwt dat alle functies die in dat scenario betrokken zijn, automatisch worden ingesteld op de juiste waarden. Een voorbeeld hiervan kan een keuze zijn tussen inktbesparing, papierbesparing en modi van de hoogste kwaliteit waarmee verschillende afdrukfuncties automatisch kunnen worden bewerkt op basis van één selectie van de gebruiker. Windows kan ze niet automatisch groeperen, omdat hiervoor alle aangepaste functies van elk printermodel moeten worden begrepen.
Deze noodzaak voor het weergeven van aangepaste afdrukvoorkeuren wordt door deze API aangepakt met een optioneel UWP-extensiecontract dat door de gebruiker kan worden geactiveerd vanuit alle Dialoogvensters voor Afdrukken in Windows en aangepaste afdrukdialoogvensters die gebruikmaken van API die wordt geleverd door Windows. Fabrikanten kunnen hun gebruikersinterface aanpassen om de beste afdrukervaring te bieden voor de specifieke printer die de gebruiker eigenaar is.
Een ander gebied waar de printerfabrikanten de afdrukkwaliteit kunnen verbeteren en onderscheiden, is de afdrukkwaliteit. Fabrikanten kunnen de afdrukkwaliteit na rendering verbeteren door de inhoud voor de specifieke printer te optimaliseren. Ze kunnen ook een voorbeeld van hoge kwaliteit presenteren dat beter de uiteindelijke uitvoer vertegenwoordigt, omdat er rekening kan worden gehouden met printerspecifieke functies.
Terminologie
Term | Definitie |
---|---|
PSA | Afdrukondersteuningstoepassing. Een UWP-app die gebruikmaakt van de API die in dit artikel wordt beschreven. |
MPD | Modern Afdrukken Dialoogvenster. Dit wordt aan de gebruiker weergegeven wanneer een app afdrukt met behulp van de Windows.Graphics.Printing-API. |
CPD (Voortdurende Professionele Ontwikkeling) | Algemeen dialoogvenster Afdrukken. Dit wordt weergegeven aan de gebruiker wanneer de app afdrukt met behulp van de Win32-API. Apps die het afdrukvoorbeeld moeten weergeven, activeren dit dialoogvenster niet en implementeren zelf een versie van het dialoogvenster. Office-apps zijn een uitstekend voorbeeld hiervan. |
IPP | Internet Printing Protocol. Wordt gebruikt vanaf een clientapparaat om met de printer te communiceren om afdrukvoorkeuren op te halen en in te stellen en om het document te verzenden dat moet worden afgedrukt. |
Afdrukondersteuning gekoppelde printer | Printer die is gekoppeld aan PSA. |
IPP-printer | Printer die het IPP-protocol ondersteunt. |
Meer instellingen | Koppeling waarmee de door de partner geleverde app-gebruikersinterface in MPD wordt geopend. Standaard wordt de ingebouwde gebruikersinterface voor afdrukvoorkeuren geopend wanneer er geen PSA is geïnstalleerd. |
Printervoorkeuren gebruikersinterface | Dialoogvenster dat wordt gebruikt om standaardprinteropties in te stellen die tijdens de afdruktijd worden toegepast. Bijvoorbeeld: afdrukstand, papierformaat, kleur, afdrukken aan beide zijden, enzovoort. |
PDL | Taal voor paginabeschrijving. De indeling waarin een document naar de printer wordt verzonden. |
Gekoppelde PSA-printer | Fysieke IPP-printer die is gekoppeld aan een PSA-toepassing. |
Printapparaatmogelijkheden | XML-documentindeling voor het definiëren van printermogelijkheden. Zie Print Ticket and Print Capabilities Technologiesvoor meer informatie. |
PrintTicket | Verzameling van verschillende afdrukgerelateerde functies en hun waarden die worden gebruikt om de intentie van de gebruiker voor een bepaalde afdruktaak vast te leggen. |
Afdrukondersteuningsextensie | PSA-achtergrondtaak die verantwoordelijk is voor het bieden van uitbreidingsmogelijkheden voor printerbeperkingen. |
Naamruimte voor printondersteuning
Deze voorbeelden verwijzen naar een printsupport naamruimte, die is gedefinieerd als:
xmlns:printsupport="http://schemas.microsoft.com/appx/manifest/printsupport/windows10"
Gebruikersinterface voor ondersteuningsinstellingen afdrukken
Wanneer een gebruiker op het punt staat een document af te drukken, willen ze vaak bepaalde voorkeuren instellen waarmee het document moet worden afgedrukt. Ze kunnen er bijvoorbeeld voor kiezen om een document af te drukken in de afdrukstand Liggend. Ze kunnen ook profiteren van een aangepaste functie die de printer ondersteunt. Windows biedt standaardgebruikersinterface om aangepaste voorkeuren weer te geven, maar de gebruiker begrijpt deze mogelijk niet omdat er geen geschikte pictogrammen of beschrijvingen zijn. Windows gebruikt mogelijk ook het verkeerde UI-besturingselement om het te tonen. Een dergelijke aangepaste functie wordt het beste gepresenteerd door een app die de functie volledig begrijpt. Dit is de motivatie achter het aanbieden van een API waarmee de printerfabrikanten apps kunnen maken die zijn afgestemd op de verschillende printermodellen die ze maken.
Er wordt een nieuw UAP-extensiecontract gemaakt met een nieuwe categorie met de naam windows.printSupportSettingsUI. Apps die met dit contract zijn geactiveerd, ontvangen een nieuw ActivationKind met de naam PrintSupportSettingsUI. Voor dit contract is geen nieuwe mogelijkheid vereist.
<Extensions>
<printsupport:Extension Category="windows.printSupportSettingsUI"
EntryPoint="PsaSample.PsaSettingsUISample"/>
</Extensions>
Dit contract wordt aangeroepen wanneer de gebruiker Meer instellingen selecteert in MPD of Voorkeuren in CPD. Dit contract kan ook worden aangeroepen vanuit Afdrukvoorkeuren in de app Instellingen. Wanneer het contract is geactiveerd, ontvangt de app een PrintSupportSettingsUISession object dat kan worden gebruikt om de huidige PrintTicket- en PrintDevice--objecten op te halen. Het PrintDevice--object kan worden gebruikt om met de printer te communiceren om printer- en taakkenmerken te ontvangen. De app kan vervolgens gebruikersinterface met de juiste opties van de printer aan de gebruiker weergeven. Wanneer de gebruiker de keuzes maakt en OKselecteert, kan de toepassing het afdrukticket wijzigen, valideren en vervolgens opnieuw verzenden met PrintSupportPrintTicketTarget--object. Als de gebruiker ervoor kiest om het voorkeurenvenster te annuleren, moeten wijzigingen worden verwijderd en moet de toepassing worden afgesloten door de uitstel uit te voeren van het PrintSupportSettingsUISession--object.
De printondersteunings-app zal naar verwachting meerdere gelijktijdige activeringen verwerken voor verschillende afdruktaken. Een dergelijke app moet dus meerdere exemplaren ondersteunen met behulp van de SupportsMultipleInstances element in het bestand package.appxmanifest. Als u dit niet doet, kan dit leiden tot situaties waarin het bevestigen van voorkeuren van een afdruktaak andere voorkeurenvensters sluit die mogelijk geopend zijn. De gebruiker moet deze voorkeurenvensters opnieuw openen.
Het volgende sequentiediagram vertegenwoordigt het concept voor het bewerken van afdruktickets in de gebruikersinterface van Settings:
PrintTicket wijzigen in de gebruikersinterface van de instellingen
C#-voorbeeldcode voor activering van de gebruikersinterface instellingen wanneer deze wordt gestart vanuit een afdrukdialoogvenster (MPD/CPD of aangepast afdrukdialoogvenster) of vanuit systeeminstellingen:
namespace PsaSampleApp
{
sealed partial class App : Application
{
Deferral settingsDeferral;
protected override void OnActivated(IActivatedEventArgs args)
{
if (args.Kind == ActivationKind.PrintSupportSettingsUI)
{
// Get the activation arguments
var settingsEventArgs = args as PrintSupportSettingsActivatedEventArgs;
PrintSupportSettingsUISession settingsSession = settingsEventArgs.Session;
// Take deferral
this.settingsDeferral = settingsEventArgs.GetDeferral();
// Create root frame
var rootFrame = new Frame();
// Choose the page to be shown based upon where the application is being launched from
switch (settingsSession.LaunchKind)
{
case SettingsLaunchKind.UserDefaultPrintTicket:
{
// Show settings page when launched for default printer settings
rootFrame.Navigate(typeof(DefaultSettingsView), settingsSession);
}
break;
case SettingsLaunchKind.JobPrintTicket:
{
// Show settings page when launched from printing app
rootFrame.Navigate(typeof(JobSettingsView), settingsSession);
}
break;
}
Window.Current.Content = rootFrame;
}
}
internal void ExitSettings()
{
settingsDeferral.Complete();
}
}
}
XAML voor DefaultSettingsView klasse:
<Page
x:Class="PsaSampleApp.DefaultSettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PsaSampleApp"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical" Margin="30,50,0,0">
<ComboBox x:Name="OrientationOptions" ItemsSource="{x:Bind OrientationFeatureOptions}" SelectedItem="{x:Bind SelectedOrientationOption, Mode=TwoWay}" DisplayMemberPath="DisplayName" HorizontalAlignment="Left" Height="Auto" Width="Auto" VerticalAlignment="Top"/>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button x:Name="Ok" Content="Ok" HorizontalAlignment="Left" Margin="50,0,0,0" VerticalAlignment="Top" Click="OkClicked"/>
<Button x:Name="Cancel" Content="Cancel" HorizontalAlignment="Left" Margin="20,0,0,0" VerticalAlignment="Top" Click="CancelClicked"/>
</StackPanel>
</Grid>
</Page>
C#-voorbeeldcode voor het weergeven van de gebruikersinterface en het wijzigen van PrintTicket:
namespace PsaSampleApp
{
/// <summary>
/// Class for showing print settings to the user and allow user to modify it
/// </summary>
public sealed partial class DefaultSettingsView: Page
{
private IppPrintDevice printer;
private PrintSupportSettingsUISession uiSession;
private WorkflowPrintTicket printTicket;
private App application;
// Bound to XAML combo box
public ObservableCollection<PrintTicketOption> OrientationFeatureOptions { get; } = new ObservableCollection<PrintTicketOption>();
public PrintTicketOption SelectedOrientationOption { get; set; }
public SettingsView()
{
this.InitializeComponent();
this.application = Application.Current as App;
this.orientationFeatureOptions = new ObservableCollection<PrintTicketOption>();
}
internal void OnNavigatedTo(NavigationEventArgs e)
{
this.uiSession = = e.Parameter as PrintSupportSettingsUISession;
this.printer = session.SessionInfo.Printer;
this.printTicket = session.SessionPrintTicket;
PrintTicketCapabilities printTicketCapabilities = this.printTicket.GetCapabilities();
// Read orientation feature from PrintTicket capabilities
PrintTicketFeature feature = printTicketCapabilities.PageOrientationFeature;
// Populate XAML combo box with orientation feature options
this.PopulateOrientationOptionComboBox(feature.Options);
PrintTicketOption printTicketOrientationOption = printTicket.PageOrientationFeature.GetSelectedOption();
// Update orientation option in XAML combo box
this.SelectedOrientationOption = this.orientationFeatureOptions.Single((option)=> (option.Name == printTicketOrientationOption.Name && option.XmlNamespace == printTicketOrientationOption.XmlNamespace));
}
private async void OkClicked(object sender, RoutedEventArgs e)
{
// Disable Ok button while the print ticket is being submitted
this.Ok.IsEnabled = false;
// Set selected orientation option in the PrintTicket and submit it
PrintTicketFeature orientationFeature = this.printTicket.PageOrientationFeature;
orientationFeature.SetSelectedOption(this.SelectedOrientationOption);
// Validate and submit PrintTicket
WorkflowPrintTicketValidationResult result = await printTicket.ValidateAsync();
if (result.Validated)
{
// PrintTicket validated successfully – submit and exit
this.uiSession.UpdatePrintTicket(printTicket);
this.application.ExitSettings();
}
else
{
this.Ok.IsEnabled = true;
// PrintTicket is not valid – show error
this.ShowInvalidPrintTicketError(result.ExtendedError);
}
}
private void CancelClicked(object sender, RoutedEventArgs e)
{
this.application.ExitSettings();
}
}
}
Printerkenmerken ophalen van het printerapparaat
WireShark-antwoord van een IPP-printer naar een get-printer-attributen-query:
C#-voorbeeldcode voor het ophalen van inktnamen en inktniveaus van de printer:
namespace PsaSampleApp
{
/// <summary>
/// Class for showing print settings to the user
/// </summary>
public sealed partial class SettingsView : Page
{
IList<string> inkNames;
IList<int> inkLevels;
private async void GetPrinterAttributes()
{
// Read ink names and levels, along with loaded media-sizes
var attributes = new List<string>();
attributes.Add("marker-names");
attributes.Add("marker-levels");
attributes.Add("media-col-ready");
IDictionary<string, IppAttributeValue> printerAttributes = this.printer.GetPrinterAttributes(attributes);
IppAttributeValue inkNamesValue = printerAttributes["marker-names"];
CheckValueType(inkNamesValue, IppAttributeValueKind.Keyword);
this.inkNames = inkNamesValue.GetKeywordArray();
IppAttributeValue inkLevelsValue = printerAttributes["marker-levels"];
CheckValueType(inkLevelsValue, IppAttributeValueKind.Integer);
this.inkLevels = inkLevelsValue.GetIntegerArray();
// Read loaded print media sizes
IppAttributeValue mediaReadyCollectionsValue = printerAttributes["media-col-ready"];
foreach (var mediaReadyCollection in mediaReadyCollectionsValue.GetCollectionArray())
{
IppAttributeValue mediaSizeCollection;
if (mediaReadyCollection.TryGetValue("media-size", out mediaSizeCollection))
{
var xDimensionValue = mediaSizeCollection.GetCollectionArray().First()["x-dimension"];
var yDimensionValue = mediaSizeCollection.GetCollectionArray().First()["y-dimension"];
CheckValueType(xDimensionValue, IppAttributeValueKind.Integer);
CheckValueType(yDimensionValue, IppAttributeValueKind.Integer);
int xDimension = xDimensionValue.GetIntegerArray().First();
int yDimension = yDimensionValue.GetIntegerArray().First();
this.AddMediaSize(xDimension, yDimension);
}
}
}
private void CheckValueType(IppAttributeValue value, IppAttributeValueKind expectedKind)
{
if (value.Kind != expectedKind)
{
throw new Exception(string.Format("Non conformant type found: {0}, expected: {1}", value.Kind, expectedKind));
}
}
}
}
Printerkenmerken instellen op de printer
C#-voorbeeldcode voor het instellen van printerkenmerken:
int defaultResolutionX = 1200;
int defaultResolutionY = 1200;
string pdlFormat = "image/pwg-raster";
private async void SetPrinterAttributes()
{
var attributes = new Dictionary<string, IppAttributeValue>();
attributes.Add("document-format-default", IppAttributeValue.CreateKeyword(this.pdlFormat));
var resolution = new IppResolution(this.defaultResolutionX, this.defaultResolutionY, IppResolutionUnit.DotsPerInch);
attributes.Add("printer-resolution-default", IppAttributeValue.CreateResolution(resolution));
var result = this.printer.SetPrinterAttributes(attributes);
if (!result.Succeeded)
{
foreach (var attributeError in result.AttributeErrors)
{
var attributeName = attributeError.Key;
switch (attributeError.Value.Reason)
{
case IppAttributeErrorReason.AttributeValuesNotSupported:
var values = attributeError.Value.GetUnsupportedValues().First();
this.LogUnSupportedValues(attributeName, values);
break;
case IppAttributeErrorReason.AttributeNotSettable:
this.LogAttributeNotSettable(attributeName);
break;
case IppAttributeErrorReason.AttributeNotSupported:
this.LogAttributeNotSupported(attributeName);
break;
case IppAttributeErrorReason.RequestEntityTooLarge:
this.LogAttributeNotEntityTooLarge(attributeName);
break;
case IppAttributeErrorReason. ConflictingAttributes:
this.LogConflictingAttributes(attributeName);
break;
}
}
}
}
Printerbeperkingen uitbreiden
De printondersteunings-app ondersteunt aangepaste PrintTicket-validatie en het definiëren van de standaard PrintTicket. In deze sectie wordt beschreven hoe deze functies worden ondersteund.
Ter ondersteuning van beperkingen voor printeruitbreidingen is een nieuw type achtergrondtaak, PrintSupportExtension, geïmplementeerd. Het Package.appxmanifest heeft een uitbreidbaarheidsvermelding voor de printondersteuningsextensie, zoals hier wordt weergegeven:
<Extensions>
<printsupport:Extension Category="windows.printSupportExtension"
EntryPoint="PsaBackgroundTasks.PrintSupportExtension"/>
</Extensions>
Deze service kan op elk moment in een afdruktaak worden uitgevoerd voor de bijbehorende IPP-printer. Wanneer de printondersteuningsextensie wordt geactiveerd via de functie IBackgroundTaskInstance, wordt een exemplaar van IBackgroundTaskInstance gegeven aan PrintSupportExtension om toegang te bieden tot de runtimeklasse PrintSupportExtensionTriggerDetails, die intern PrintSupportExtensionSession als eigenschap levert. De achtergrondklasse PrintSupportExtension kan vervolgens het sessieobject gebruiken om te registreren voor gebeurtenissen die het wil voorzien van aangepaste functionaliteit.
event Windows.Foundation.TypedEventHandler<PrintSupportExtensionSession, PrintSupportPrintTicketValidationRequestedEventArgs>; PrintTicketValidationRequested;
Als de printondersteuningsextensie een eigen PrintTicket validatiemechanisme biedt, kan deze zich registreren voor deze gebeurtenis. Wanneer een PrintTicket moet worden gevalideerd, wordt dit evenement door het afdruksysteem gegenereerd. PrintSupportExtension- krijgt vervolgens het huidige PrintTicket- dat gevalideerd moet worden binnen de EventArgs. De PrintSupportExtension achtergrondklasse kan vervolgens de PrintTicket- controleren en wijzigen om conflicten op te lossen. De PrintSupportExtension achtergrondklasse moet vervolgens het resultaat voor validatie instellen met behulp van de functie SetPrintTicketResult om aan te geven of de PrintTicket- is opgelost, conflicten heeft of ongeldig is. Deze gebeurtenis kan op elk gewenst moment worden gegenereerd tijdens de levensduur van een afdruktaak. Als de PrintSupportExtension- klasse niet wordt geregistreerd voor deze gebeurtenis, voert het afdruksysteem een eigen validatie van het PrintTicket uit.
event Windows.Foundation.TypedEventHandler<PrintSupportExtensionSession, PrintSupportPrintDeviceCapabilitiesChangedEventArgs>; PrintDeviceCapabilitiesChanged;
De gebeurtenis wordt gegenereerd nadat het afdruksysteem de in de cache opgeslagen PrintDeviceCapabilities van de bijbehorende IPP-printer bijwerkt. Wanneer deze gebeurtenis wordt gegenereerd, kan de PrintSupportExtension achtergrondklasse de gewijzigde PrintDeviceCapabilities controleren en wijzigen.
Aangepaste validatie van afdrukticket
C#-voorbeeldcode voor het leveren van PrintTicket validatieservice:
public void Run(IBackgroundTaskInstance taskInstance)
{
// Take task deferral
this.taskDeferral = taskInstance.GetDeferral();
// Associate a cancellation handler with the background task
taskInstance.Canceled += OnTaskCanceled;
var psaTriggerDetails = taskInstance.TriggerDetails as PrintSupportExtensionTriggerDetails;
var serviceSession = psaTriggerDetails.Session as PrintSupportExtensionSession;
this.ippPrintDevice = serviceSession.Printer;
serviceSession.PrintTicketValidationRequested += this.OnPrintTicketValidationRequested;
serviceSession.PrinterDeviceCapabilitiesChanged += this.OnPdcChanged;
serviceSession.Start();
}
private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
// Complete the deferral
this.taskDeferral.Complete();
}
private void OnPrintTicketValidationRequested(PrintSupportExtensionSession session, PrintSupportPrintTicketValidationRequestedEventArgs args)
{
using (args.GetDeferral())
{
// Get PrintTicket that needs needs to be validated and resolved
var printTicket = args.PrintTicket;
// Validate and resolve PrintTicket
WorkflowPrintTicketValidationStatus validationStatus = this.ValidateAndResolvePrintTicket(printTicket);
args.SetPrintTicketValidationStatus(validationStatus);
}
}
PrintDeviceCapabilities bijwerken
private void OnPdcChanged(PrintSupportExtensionSession session, PrintSupportPrintDeviceCapabilitiesChangedEventArgs args)
{
using (args.GetDeferral())
{
var pdc = args.GetCurrentPrintDeviceCapabilities();
// Check current PDC and make changes according to printer device capabilities
XmlDocument newPdc = this.CheckAndUpdatePrintDeviceCapabilities(pdc);
args.UpdatePrintDeviceCapabilities(newPdc);
}
}
Verbetering van afdrukkwaliteit
Zodra de gebruiker zich heeft verplicht af te drukken door op de afdrukknop in het afdrukdialoogvenster te drukken, wordt het document dat moet worden afgedrukt verzonden naar de afdrukstack vanuit de app die wordt afgedrukt. Dit document ondergaat vervolgens transformatie (rendering naar PDL) om het geschikt te maken voor de doelprinter. Windows bepaalt welke transformatie moet worden gekozen op basis van kenmerken die door de printer worden opgevraagd. Het getransformeerde document wordt vervolgens naar de printer verzonden. Hoewel dit goed werkt voor de meeste printers, zijn er gevallen waarin de kwaliteit van de afdruk kan worden verbeterd door een partner-app toe te staan deel te nemen aan de transformatie. Om dit mogelijk te maken, wordt de huidige werkstroom-API voor afdrukken uitgebreid met aanroepen naar de app op extra punten van de afdrukstack. Deze API ondersteunt twee nieuwe gebeurtenissen waarvoor de PSA-app zich kan registreren. Dit zijn de enige toegangspunten in het PSA API-oppervlak:
WerkStart-
- Deze gebeurtenis wordt gegenereerd wanneer een afdruktaak wordt gestart door een toepassing. Wanneer de gebeurtenis optreedt, kan een Print Support-app ervoor kiezen om de systeemweergave over te slaan door SetSkipSystemRendering aan te roepen op PrintWorkflowJobStartingEventArgs. Als systeemweergave overslaan is gekozen, converteert het afdruksysteem het XPS-document niet naar de PDL-indeling die vereist is voor de printer. In plaats daarvan wordt de XPS die door de afdruktoepassing wordt gegenereerd, rechtstreeks aan de PSA gegeven die vervolgens verantwoordelijk is voor het converteren van XPS naar PDL-indeling.
Wijzigingsverzoek Pdl
- Deze gebeurtenis wordt gegenereerd wanneer Windows de conversie van de XPS-stroom start naar de PDL-indeling die wordt aangegeven door de printer. Runtimeklasse PrintWorkflowPdlModificationRequestedEventArgs wordt opgegeven als een argument voor deze gebeurtenis. Deze gebeurtenisklasse biedt PDL-bron- en doelobjecten voor het lezen en schrijven van de inhoud van de afdruktaak. Als de app bepaalt dat deze gebruikersinvoer nodig heeft, kan de gebruikersinterface worden gestart met behulp van PrintWorkflowUILauncher vanuit de EventArgs. Deze API maakt gebruik van het Tester-Doer patroon. PrintWorkflowUILauncher kan de gebruikersinterface niet aanroepen als de functie IsUILaunchEnabled onwaar retourneert. Deze functie retourneert 'false' als de PSA-sessie in stille modus (headless- of kioskmodus) draait. De app voor printondersteuning zou niet moeten proberen de gebruikersinterface te starten als de functie false retourneert.
Een OutputStream- is beschikbaar als onderdeel van PrintWorkflowPdlTargetStream- die wordt geretourneerd door de functie GetStreamTargetAsync-. Inhoud die naar de doeluitvoerstream wordt geschreven, wordt als documentinhoud doorgegeven aan de printer.
Sequentiediagram voor de PDL-wijzigings gebeurtenis:
De PSA-voorgrondtoepassing wordt gestart wanneer de PSA-achtergrondtaak het starten van de gebruikersinterface aanvraagt. De PSA kan het voorgrondcontract gebruiken om gebruikersinvoer op te halen en/of om een afdrukvoorbeeld voor de gebruiker weer te geven.
Achtergrondtaak voor ondersteunende afdrukwerkstroom
Er is een nieuw printSupportWorkflow achtergrondtaaktype gedefinieerd. Het Package.appxmanifest heeft de volgende uitbreidbaarheidsvermelding voor het PrintSupportWorkflow contract:
<Extensions>
<printsupport:Extension Category="windows.printSupportWorkflow"
EntryPoint="PsaBackgroundTasks.PrintSupportWorkflowSample"/>
</Extensions>
Bij activering van het contract wordt PrintWorkflowJobTriggerDetails gegeven als IBackgroundTaskInstance->TriggerDetails. PrintWorkflowJobTriggerDetails biedt intern PrintWorkflowJobBackgroundSession binnen zijn eigenschappen aan. De app kan PrintWorkflowJobBackgroundSession gebruiken om zich aan te melden voor gebeurtenissen die verband houden met verschillende injectiepunten in de workflow van de afdruktaak. Nadat de gebeurtenisregistratie is voltooid, moet de app PrintWorkflowJobBackgroundSession::Start aanroepen, zodat het afdruksysteem kan beginnen met het afvuren van gebeurtenissen met betrekking tot verschillende injectiepunten.
Gebruikersinterface van werkstroomtaak afdrukken
Er wordt een nieuwe ActivationKind met de naam PrintSupportJobUI gedefinieerd. Hiervoor is geen nieuwe mogelijkheid vereist.
<Extensions>
<printsupport:Extension Category="windows.printSupportJobUI"
EntryPoint="PsaSample.PrintSupportJobUISample"/>
</Extensions>
Dit is een UI-contract dat kan worden gestart vanuit het achtergrondcontract voor de afdrukondersteuningsworkflow, of wanneer de gebruiker een foutmelding voor een afdruktaak selecteert. Bij activering wordt PrintWorkflowJobActivatedEventArgs geleverd, met een PrintWorkflowJobUISession--object. Met PrintWorkflowJobUISessionmoet de voorgrondtoepassing zich registreren voor de gebeurtenis PdlDataAvailable als deze toegang wil krijgen tot de PDL-gegevens. Als de voorgrondtoepassing aangepaste foutberichten wilt weergeven voor fouten die kunnen optreden tijdens de taak, moet deze zich registreren voor de gebeurtenis JobNotification. Zodra de gebeurtenissen zijn geregistreerd, moet de toepassing de PrintWorkflowJobUISession::Start functie aanroepen om het afdruksysteem te laten beginnen met het starten van gebeurtenissen.
Systeemweergave overslaan
namespace PsaBackground
{
class PrintSupportWorkflowBackgroundTask : IBackgroundTask
{
BackgroundTaskDeferral taskDeferral;
public void Run(IBackgroundTaskInstance taskInstance)
{
// Take Task Deferral
taskDeferral = taskInstance.GetDeferral();
var jobTriggerDetails = taskInstance.TriggerDetails as PrintWorkflowJobTriggerDetails;
var workflowBackgroundSession = jobTriggerDetails.PrintWorkflowJobSession as PrintWorkflowJobBackgroundSession;
// Register for events
workflowBackgroundSession.JobStarting += this.OnJobStarting;
workflowBackgroundSession.PdlModificationRequested += this.OnPdlModificationRequested;
// Start Firing events
workflowBackgroundSession.Start();
}
private void OnJobStarting(PrintWorkflowJobBackgroundSession session, PrintWorkflowJobStartingEventArgs args)
{
using (args.GetDeferral())
{
// Call SetSkipSystemRendering to skip conversion for XPS to PDL, so that PSA can directly manipulate the XPS file.
args.SetSkipSystemRendering();
}
}
}
}
PDL-wijzigingsevenement
Sequentiediagram voor de PDL-wijzigings gebeurtenis:
C#-voorbeeldcode voor het lezen en schrijven van afdruktaakinhoud voor afdrukondersteuningstaakcontrole:
private void OnPdlModificationRequested(PrintWorkflowJobBackgroundSession session, PrintWorkflowPdlModificationRequestedEventArgs args)
{
using (args.GetDeferral())
{
IInputStream pdlContent = args.SourceContent.GetInputStream();
// Specify the Content type of stream that will be written to target that is passed to printer accordingly.
PrintWorkflowPdlTargetStream streamTarget = args.CreateJobOnPrinter(args.SourceStream.ContentType);
IOutputStream outputStream = streamTarget.GetOutputStream();
using (var inputReader = new Windows.Storage.Streams.DataReader(pdlContent))
{
inputReader.InputStreamOptions = InputStreamOptions.Partial;
using (var outputWriter = new Windows.Storage.Streams.DataWriter(outputStream))
{
// Write the updated Print stream from input stream to the output stream
uint chunkSizeInBytes = 256 * 1024; // 256K chunks
uint lastAllocSize = 0;
byte[] contentData = new byte[chunkSize];
while(this.ReadChunk(inputReader, ref contentData))
{
// Make any changes required to the input data
// ...
// Write out the modified content
outputWriter.WriteBytes(contentData);
await outputWriter.StoreAsync();
}
}
}
streamTarget.CompleteStreamSubmission(PrintWorkflowSubmittedStatus.Succeeded);
this.taskDeferral.Complete();
}
}
}
UI starten vanuit de achtergrond van het werkproces
C#-voorbeeldcode voor het starten van de gebruikersinterface van de Print Support Job vanuit het PSA PDL-wijzigingsverzoek gebeurteniscontract.
private async void OnPdlModificationRequested(PrintWorkflowJobBackgroundSession session, PrintWorkflowPdlModificationRequestedEventArgs args)
{
IInputStream pdlContent = args.SourceContent.GetInputStream();
WorkflowPrintTicket printTicket = args.PrinterJob.GetJobPrintTicket();
bool uiRequired = this.IsUIRequired(pdlContent, printTicket);
if (!uiRequired)
{
// Specify the Content type of content that will be written to target that is passed to printer accordingly.
PrintWorkflowPdlTargetStream streamTarget = args.CreateJobOnPrinter (args.SourceStream.ContentType);
// Process content directly if UI is not required
this.ProcessContent(pdlContent, streamTarget);
}
else if (args.UILauncher.IsUILaunchEnabled())
{
// LaunchAndCompleteUIAsync will launch the UI and wait for it to complete before returning
PrintWorkflowUICompletionStatus status = await args.UILauncher.LaunchAndCompleteUIAsync();
if (status == PrintWorkflowUICompletionStatus.Completed)
{
PrintWorkflowPdlTargetStream streamTarget = args.CreateJobOnPrinter(args.SourceStream.ContentType);
this.ProcessContent(pdlContent, streamTarget);
}
else
{
if (status == PrintWorkflowUICompletionStatus.UserCanceled)
{
// Log user cancellation and cleanup here.
this.taskDeferral.Complete();
}
else
{
// UI launch failed, abort print job.
args.Configuration.AbortPrintFlow(PrintWorkflowAbortReason.JobFailed);
this.taskDeferral.Complete();
}
}
}
else
{
// PSA requires to show UI, but launching UI is not supported at this point because of user selection.
args.Configuration.AbortPrintFlow(PrintWorkflowAbortReason.JobFailed);
this.taskDeferral.Complete();
}
}
Activering van de UI van de workflow-job voor het PDLDataAvailable-evenement
Sequentiediagram voor het activeren van de gebruikersinterface van de afdruktaak bij het PdlDataAvailable-gebeurtenis:
C#-voorbeeldcode voor het activeringscontract van de gebruikersinterface voor de PSA-opdracht.
namespace PsaSampleApp
{
sealed partial class App : Application
{
protected override void OnActivated(IActivatedEventArgs args)
{
if (args.Kind == ActivationKind.PrintSupportJobUI)
{
var rootFrame = new Frame();
rootFrame.Navigate(typeof(JobUIPage));
Window.Current.Content = rootFrame;
var jobUI = rootFrame.Content as JobUIPage;
// Get the activation arguments
var workflowJobUIEventArgs = args as PrintWorkflowJobActivatedEventArgs;
PrintWorkflowJobUISession session = workflowJobUIEventArgs.Session;
session.PdlDataAvailable += jobUI.OnPdlDataAvailable;
session.JobNotification += jobUI.OnJobNotification;
// Start firing events
session.Start();
}
}
}
}
namespace PsaSampleApp
{
public sealed partial class JobUIPage : Page
{
public JobUIPage()
{
this.InitializeComponent();
}
public string WorkflowHeadingLabel;
public void OnPdlDataAvailable(PrintWorkflowJobUISession session, PrintWorkflowPdlDataAvailableEventArgs args)
{
using (args.GetDeferral())
{
string jobTitle = args.Configuration.JobTitle;
string sourceApplicationName = args.Configuration.SourceAppDisplayName;
string printerName = args.Printer.PrinterName;
this.WorkflowHeadingLabel = string.Format(this.formatHeading, jobTitle, sourceApplicationName, printerName);
// Get pdl stream and content type
IInputStream pdlContent = args.SourceContent.GetInputStream();
string contentType = args.SourceContent.ContentType;
this.ShowPrintPreview(pdlContent, contentType);
}
}
}
}
Kenmerken van printertaak ophalen
C#-voorbeeldcode voor het ophalen van taakkenmerken voor een afdruktaak:
namespace PsaBackground
{
class PrintSupportWorkflowBackgroundTask : IBackgroundTask
{
private async void OnPdlModificationRequested(PrintWorkflowJobBackgroundSession session,
PrintWorkflowPdlModificationRequestedEventArgs args)
{
using (args.GetDeferral())
{
string colorMode = this.GetJobColorMode(args.PrinterJob);
if (colorMode != "monochrome")
{
this.SetJobColorModeToMonochrome(args.PrinterJob);
}
}
}
private string GetJobColorMode(PrintWorkflowPrinterJob printerJob)
{
var attributes = new List<string>();
attributes.Add("print-color-mode");
// Gets the IPP attributes from the current print job
IDictionary<string, IppAttributeValue> printerAttributes = printerJob.GetJobAttributes(attributes);
var colorModeValue = printerAttributes["print-color-mode"];
this.CheckValueType(colorModeValue, IppAttributeValueKind.Keyword);
return colorModeValue.GetKeywordArray().First();
}
}
}
Kenmerken van printertaak instellen
C#-voorbeeldcode, verdergaand vanuit de Kenmerken van printertaak ophalen sectie hierboven, waarin het instellen van taakkenmerken wordt gedemonstreerd:
private async void SetJobColorModeToMonochrome(PrintWorkflowPrinterJob printerJob)
{
var attributes = new Dictionary<string, IppAttributeValue>();
attributes.Add("print-color-mode", IppAttributeValue.CreateKeyword("monochrome"));
var result = PrinterJob.SetJobAttributes(attributes);
if (!result.Succeeded)
{
this.LogSetAttributeError(result.AttributeErrors);
}
}
Sommige IPP-printers bieden geen ondersteuning voor het verkrijgen/instellen van taakkenmerken nadat de taak is gemaakt. Voor deze printers is bij PrintJob de eigenschap JobId ingesteld op "0" en GetJobAttributes/SetJobAttributes zal direct mislukken met een uitzondering.
Opslagbestandstoegang bieden tot PDL-inhoud
Sommige PDL-indelingen, zoals PDF, hebben een volledige gegevensstroom nodig om met verwerken te kunnen beginnen. Daarom wordt een nieuwe methode met de naam GetContentFileAsync- geleverd in de klasse PrintWorkflowPdlSourceContent die een StorageFile- van de broninhoud retourneert.
public sealed partial class JobUIPage : Page
{
public async void OnPdlDataAvailable(PrintWorkflowJobUISession session, PrintWorkflowPdlDataAvailableEventArgs args)
{
using (args.GetDeferral())
{
if (String.Equals(args.SourceContent.ContentType, "application/pdf", StringComparison.OrdinalIgnoreCase))
{
// Wait for all PDL data to be available
StorageFile sourceFile == await args.SourceContent.GetContentFileAsync();
IRandomAccessStream sourceStream = await sourceFile.OpenReadAsync();
PdfDocument pdfDocument = await PdfDocument.LoadFromStreamAsync(sourceStream);
for (uint i = 0; i < pdfDocument.PageCount; i++)
{
PdfPage page = pdfDocument.GetPage(i);
var pageImage = new InMemoryRandomAccessStream();
await page.RenderToStreamAsync(pageImage);
this.AddImageToPreviewImageList(pageImage);
}
}
}
}
}
PDL-conversie van XPS naar PDF
C#-voorbeeldcode met PDL-conversie van XPS naar PDF:
private async void OnPdlModificationRequested(PrintWorkflowJobBackgroundSession session, PrintWorkflowPdlModificationRequestedEventArgs args)
{
using (args.GetDeferral())
{
if (String.Equals(args.SourceContent.ContentType, "application/oxps", StringComparison.OrdinalIgnoreCase))
{
var xpsContent = args.SourceContent.GetInputStream();
var printTicket = args.PrinterJob.GetJobPrintTicket();
PrintWorkflowPdlTargetStream streamTarget = args.CreateJobOnPrinter("application/pdf");
// Modify XPS stream here to make the needed changes
// for example adding a watermark
PrintWorkflowPdlConverter pdlConverter = args.GetPdlConverter(PrintWorkflowPdlConversionType.XpsToPdf);
await pdlConverter.ConvertPdlAsync(printTicket, xpsContent, streamTarget.GetOutputStream());
streamTarget.CompleteStreamSubmission(PrintWorkflowSubmittedStatus.Succeeded);
}
else
{
// We except source content to be XPS in this case, abort the session if it is not XPS.
args.Configuration.AbortPrintFlow(PrintWorkflowAbortReason.JobFailed);
}
}
this.taskDeferral.Complete();
}
Gebeurtenis voor taakmelding
Sequentiediagram voor taakmeldings gebeurtenis:
C#-voorbeeldcode, voortgaand vanuit de activering van de gebruikersinterface van de werkstroomtaak voor PDLDataAvailable hierboven, om de fout bij taakmelding weer te geven:
public sealed partial class JobUIPage : Page
{
public void OnJobNotification(PrintWorkflowJobUISession session, PrintWorkflowJobNotificationEventArgs args)
{
using (args.GetDeferral())
{
PrintWorkflowPrinterJobStatus jobStatus = args.PrintJob.GetJobStatus();
switch (jobStatus)
{
case PrintWorkflowPrinterJobStatus::Error:
// Show print job error to the user
Frame->Navigate(JobErrorPage::typeid, this);
break;
case PrintWorkflowPrinterJobStatus::Abort:
// Show message that print job has been aborted.
Frame->Navigate(JobAbortPage::typeid, this);
break;
case PrintWorkflowPrinterJobStatus::Completed:
// Show job successfully completed message to the user.
Frame->Navigate(JobCompletedPage::typeid, this);
break;
}
}
}
}
Taak maken met initiële taakkenmerken
Op dit moment bieden sommige IPP-printers geen ondersteuning voor setkenmerkbewerkingen. De CreateJobOnPrinterWithAttributes-functie en de CreateJobOnPrinterWithAttributesBuffer-functie op PrintWorkflowPdlDataAvailableEventArgs zijn beschikbaar om dit probleem te verhelpen. Met behulp van deze API's kan een PSA-ontwikkelaar taakkenmerken opgeven die worden doorgegeven aan de printer wanneer de taak op de printer wordt gemaakt.
public sealed partial class JobUIPage : Page
{
public async void OnPdlDataAvailable(PrintWorkflowJobUISession session, PrintWorkflowPdlDataAvailableEventArgs args)
{
var attributes = new Dictionary<string, IppAttributeValue>();
attributes.Add("print-color-mode", IppAttributeValue.CreateKeyword("monochrome"));
// Create job on printer with initial job attributes
PrintWorkflowPdlTargetStream streamTarget = args.CreateJobOnPrinterWithAttributes(attributes, "application/pdf");
// Write data to target stream
}
}
Sequentiële XPS-verwerking
C++/Winrt-voorbeeldcode voor het verwerken van XPS sequentieel voordat spooling is voltooid.
namespace winrt
{
struct WorkflowReceiver : public winrt::implements<WorkflowReceiver, IPrintWorkflowXpsReceiver2>
{
STDMETHODIMP SetDocumentSequencePrintTicket(_In_ IStream* documentSequencePrintTicket) noexcept override
{
// process document sequence print ticket
return S_OK;
}
STDMETHODIMP SetDocumentSequenceUri(PCWSTR documentSequenceUri) noexcept override
{
// process document sequence URI
}
STDMETHODIMP AddDocumentData(UINT32 documentId, _In_ IStream* documentPrintTicket,
PCWSTR documentUri) noexcept override
{
// process document URI and print ticket
return S_OK;
}
STDMETHODIMP AddPage(UINT32 documentId, UINT32 pageId,
_In_ IXpsOMPageReference* pageReference, PCWSTR pageUri) noexcept override
{
// process XPS page
return S_OK;
}
STDMETHODIMP Close() noexcept override
{
// XPS processing finished
return S_OK;
}
STDMETHODIMP Failed(HRESULT XpsError) noexcept override
{
// XPS processing failed, log error and exit
return S_OK;
}
};
void PsaBackgroundTask::OnPdlModificationRequested(PrintWorkflowJobBackgroundSession session,
PrintWorkflowPdlModificationRequestedEventArgs args)
{
auto contentType = args.SourceContent().ContentType();
if (contentType == L"application/oxps")
{
auto xpsContent = args.SourceContent().GetInputStream();
PrintWorkflowObjectModelSourceFileContent xpsContentObjectModel(xpsContent);
com_ptr<IPrintWorkflowObjectModelSourceFileContentNative> xpsContentObjectModelNative;
check_hresult(winrt::get_unknown(xpsContentObjectModel)->QueryInterface(
IID_PPV_ARGS(xpsContentObjectModelNative.put())));
auto xpsreceiver = make_self<WorkflowReceiver>();
check_hresult(xpsContentObjectModelNative->StartXpsOMGeneration(xpsreceiver.get()));
}
}
}
Lokalisatie van weergavenamen en INTEGRATIE van PDL Passthrough-API
Belangrijk
In deze sectie wordt de PSA-functionaliteit beschreven die beschikbaar is vanaf Windows 11, versie 22H2.
In dit scenario past de PSA de mogelijkheden van het afdrukapparaat (PDC) aan en biedt PDR (Print Device Resources) voor tekenreekslokalisatie.
De PSA stelt ook de ondersteunde PDL Passthrough-API-inhoudstypen (PDL-indelingen) in. Als de PSA zich niet abonneert op het event of SetSupportedPdlPassthroughContentTypes niet expliciet aanroept, wordt de PDL Passthrough uitgeschakeld voor de printers die aan deze PSA-app zijn gekoppeld.
// Event handler called every time PrintSystem updates PDC or BindPrinter is called
private void OnPdcChanged(PrintSupportExtensionSession session, PrintSupportPrintDeviceCapabilitiesChangedEventArgs args)
{
using (args.GetDeferral())
{
XmlDocument pdc = args.GetCurrentPrintDeviceCapabilities();
XmlDocument pdr = args.GetCurrentPrintDeviceResources();
// Check current PDC and make changes according to printer device capabilities
XmlDocument newPdc = this.CheckAndUpdatePrintDeviceCapabilities(pdc);
// Get updated printer devices resources, corresponding to the new PDC
XmlDocument newPdr = this.GetPrintDeviceResourcesInfo(newPdc, pdr, args.ResourceLanguage);
// Update supported PDL formats
args.SetSupportedPdlPassthroughContentTypes(GetSupportedPdlContentTypes());
args.UpdatePrintDeviceCapabilities(newPdc);
args.UpdatePrintDeviceResources(newPdr);
}
}
Ondersteuning van functies en operationele kenmerken op paginaniveau
Belangrijk
In deze sectie wordt de PSA-functionaliteit beschreven die beschikbaar is vanaf Windows 11, versie 22H2.
De scenario's voor functieondersteuning en bewerkingskenmerken op paginaniveau worden gegroepeerd omdat ze worden aangepakt door wijzigingen aan te brengen op dezelfde plaats in de voorbeeldcode.
ondersteuning voor functie op paginaniveau: In dit scenario geeft de PSA-toepassing het kenmerk paginaniveau op, dat niet moet worden overschreven door een IPP-kenmerk dat is geparseerd uit de PrintTicket.
Afzonderlijke verzameling voor ondersteuning van bewerkingskenmerken (afdrukken van pincodes): In dit scenario geeft PSA-toepassing aangepaste IPP-bewerkingskenmerken op (bijvoorbeeld pincode).
De volgende C#-voorbeeldcode toont vereiste wijzigingen voor functieondersteuning op paginaniveau en Afzonderlijke verzameling voor bewerkingskenmerken scenario's.
private void OnPdlModificationRequested(PrintWorkflowJobBackgroundSession session, PrintWorkflowPdlModificationRequestedEventArgs args)
{
using (args.GetDeferral())
{
IInputStream pdlContent = args.SourceContent.GetInputStream();
// Custom job attributes to add to the printJob
IDictionary<string, IppAttributeValue> jobAttributes = LocalStorageUtil.GetCustomIppJobAttributes();
// Custom operation attributes to add to printJob
IDictionary<string, IppAttributeValue> operationAttributes = LocalStorageUtil.GetCustomIppOperationAttributes();
// PSA has an option to select preferred PDL format
string documentFormat = GetDocumentFormat(args.PrinterJob.Printer);
// Create PrintJob with specified PDL and custom attributes
PrintWorkflowPdlTargetStream targetStream = args.CreateJobOnPrinterWithAttributes(jobAttributes, documentFormat , operationAttributes,
PrintWorkflowAttributesMergePolicy .DoNotMergeWithPrintTicket /*jobAttributesMergePolicy*/, PrintWorkflowAttributesMergePolicy.MergePreferPsaOnConflict /*operationAttributesMergePolicy*/);
// Adding a watermark to the output(targetStream) if source payload type is XPS
this.ModifyPayloadIfNeeded(targetStream, args, documentFormat, deferral);
// Marking the stream submission as Succeeded.
targetStream.CompleteStreamSubmission(PrintWorkflowSubmittedStatus.Succeeded);
this.taskDeferral.Complete();
}
}
Het afdrukdialoogvenster verbeteren met PSA
Belangrijk
In deze sectie wordt de PSA-functionaliteit beschreven die beschikbaar is vanaf Windows 11, versie 22H2.
In dit scenario maakt het gebruik van het afdrukdialoogvenster met PSA-integratie de volgende acties mogelijk:
Ontvang een callback wanneer de selectie in de MPD wordt gewijzigd naar de printer die is gekoppeld aan PSA
Eén AdaptiveCard weergeven met ondersteuning van openUrl actie
Aangepaste functies en parameters weergeven in het dialoogvenster Afdrukken
De PrintTicket wijzigen, waardoor de selectie voor functieopties in het afdrukdialoogvenster wordt gewijzigd
De Windows.ApplicationModel.AppInfo- van de afdruk-app ophalen om het dialoogvenster Afdrukken te openen.
In het volgende C#-voorbeeld ziet u de volgende verbeteringen in het afdrukdialoogvenster:
public BackgroundTaskDeferral TaskInstanceDeferral { get; set; }
public void Run(IBackgroundTaskInstance taskInstance)
{
// Take task deferral
TaskInstanceDeferral = taskInstance.GetDeferral();
// Associate a cancellation handler with the background task
taskInstance.Canceled += OnTaskCanceled;
if (taskInstance.TriggerDetails is PrintSupportExtensionTriggerDetails extensionDetails)
{
PrintSupportExtensionSession session = extensionDetails.Session;
session.PrintTicketValidationRequested += OnSessionPrintTicketValidationRequested;
session.PrintDeviceCapabilitiesChanged += OnSessionPrintDeviceCapabilitiesChanged;
session.PrinterSelected += this.OnPrinterSelected;
}
}
private void OnTaskInstanceCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
TaskInstanceDeferral.Complete();
}
// Event handler called when the PSA Associated printer is selected in Print Dialog
private void OnPrinterSelected(PrintSupportExtensionSession session, PrintSupportPrinterSelectedEventArgs args)
{
using (args.GetDeferral())
{
// Show adaptive card in the Print Dialog (generated based on Printer and Printing App)
args.SetAdaptiveCard (GetCustomAdaptiveCard(session.Printer, args.SourceAppInfo));
// Request to show Features and Parameters in the Print Dialog if not shown already
const string xmlNamespace = "\"http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords\"";
var additionalFeatures= new List<PrintSupportPrintTicketElement> { new PrintSupportPrintTicketElement { LocalName = "PageMediaType", NamespaceUri = xmlNamespace } };
var additionalParameters = new List<PrintSupportPrintTicketElement> { new PrintSupportPrintTicketElement { LocalName = "JobCopiesAllDocuments", NamespaceUri = xmlNamespace } };
if ((featuresToShow.Count + parametersToShow.Count) <= args.AllowedCustomFeaturesAndParametersCount)
{
args.SetAdditionalFeatures(additionalFeatures);
args.SetAdditionalParameter(additionalParameters);
}
else
{
// Cannot show that many additional features and parameters, consider reducing the number
// of additional features and parameters by selecting only the most important ones
}
}
}
// Create simple AdaptiveCard to show in MPD
public IAdaptiveCard GetCustomAdaptiveCard(IppPrintDevice ippPrinter, AppInfo appInfo)
{
return AdaptiveCardBuilder.CreateAdaptiveCardFromJson($@"
{{""body"": [
{{
""type"": ""TextBlock"",
""text"": ""Hello {appInfo.DisplayInfo.DisplayName} from {ippPrinter.PrinterName}!""
}}
],
""$schema"": ""http://adaptivecards.io/schemas/adaptive-card.json"",
""type"": ""AdaptiveCard"",
""version"": ""1.0""
}}");
}
PDL-conversie met op host gebaseerde verwerkingsvlagmen
Belangrijk
In deze sectie wordt de PSA-functionaliteit beschreven die beschikbaar is vanaf Windows 11, versie 22H2.
De huidige PDL-conversie-API, PrintWorkflowPdlConverter.ConvertPdlAsync, voert standaard hostverwerking uit. Dit betekent dat de host-/afdrukcomputer de rotatie, paginavolgorde, enzovoort uitvoert, zodat de printer deze bewerkingen niet hoeft uit te voeren. Printerfabrikanten willen echter mogelijk PDL-conversie zonder hostverwerking, omdat hun printer dit beter kan doen. De functie ConvertPdlAsync gebruikt op host gebaseerde verwerkingsvlagmen om aan deze vereiste te voldoen. De PSA kan alle op de host gebaseerde verwerking of een bepaalde hostverwerkingsbewerking overslaan met behulp van deze vlag.
class HostBaseProcessingRequirements
{
public bool CopiesNeedsHostBasedProcessing = false;
public bool PageOrderingNeedsHostBasedProcessing = false;
public bool PageRotationNeedsHostBasedProcessing = false;
public bool BlankPageInsertionNeedsHostBasedProcessing = false;
}
private async void OnPdlModificationRequested(PrintWorkflowJobBackgroundSession sender, PrintWorkflowPdlModificationRequestedEventArgs args)
{
using (args.GetDeferral())
{
var targetStream = args.CreateJobOnPrinter("application/pdf");
var pdlConverter = args.GetPdlConverter(PrintWorkflowPdlConversionType.XpsToPdf);
var hostBasedRequirements = this.ReadHostBasedProcessingRequirements(args.PrinterJob.Printer);
PdlConversionHostBasedProcessingOperations hostBasedProcessing = PdlConversionHostBasedProcessingOperations.None;
if (hostBasedRequirements.CopiesNeedsHostBasedProcessing)
{
hostBasedProcessing |= PdlConversionHostBasedProcessingOperations.Copies;
}
if (hostBasedRequirements.PageOrderingNeedsHostBasedProcessing)
{
hostBasedProcessing |= PdlConversionHostBasedProcessingOperations.PageOrdering;
}
if (hostBasedRequirements.PageRotationNeedsHostBasedProcessing)
{
hostBasedProcessing |= PdlConversionHostBasedProcessingOperations.PageRotation;
}
if (hostBasedRequirements.BlankPageInsertionNeedsHostBasedProcessing)
{
hostBasedProcessing |= PdlConversionHostBasedProcessingOperations.BlankPageInsertion;
}
await pdlConverter.ConvertPdlAsync(args.PrinterJob.GetJobPrintTicket(), args.SourceContent.GetInputStream(), targetStream.GetOutputStream(), hostBasedProcessing);
}
}
private HostBaseProcessingRequirements ReadHostBasedProcessingRequirements(IppPrintDevice printDevice)
{
// Read Host based processing requirements for the printer
}
Updatebeleid voor Print Device Capabilities (PDC) instellen
Belangrijk
In deze sectie wordt de PSA-functionaliteit beschreven die beschikbaar is vanaf Windows 11, versie 22H2.
Printer-IHV's kunnen verschillende vereisten hebben voor wanneer de functies van het afdrukapparaat (PDC) moeten worden bijgewerkt. Om aan deze vereisten te voldoen, kan PrintSupportPrintDeviceCapabilitiesUpdatePolicy een updatebeleid voor de PDC instellen. PSA kan het PDC-updatebeleid instellen op basis van tijd of het aantal afdruktaken met behulp van deze API.
PDC-updatebeleid instellen op basis van het aantal taken
// Event handler called every time PrintSystem updates PDC
private void OnPdcChanged(PrintSupportExtensionSession session, PrintSupportPrintDeviceCapabilitiesChangedEventArgs args)
{
using (args.GetDeferral())
{
// Set update policy to update the PDC on bind printer of every print job.
var updatePolicy = PrintSupportPrintDeviceCapabilitiesUpdatePolicy.CreatePrintJobRefresh(1);
args.SetPrintDeviceCapabilitiesUpdatePolicy(updatePolicy);
}
}
PDC-updatebeleid instellen op basis van TimeOut
// Event handler called every time PrintSystem updates PDC
private void OnPdcChanged(PrintSupportExtensionSession session, PrintSupportPrintDeviceCapabilitiesChangedEventArgs args)
{
using (args.GetDeferral())
{
// Set update policy to update the PDC on bind printer of every print job.
var updatePolicy = PrintSupportPrintDeviceCapabilitiesUpdatePolicy.CreatePrintJobRefresh(1);
args.SetPrintDeviceCapabilitiesUpdatePolicy(updatePolicy);
}
}
Ontwerprichtlijnen voor de algemene printondersteunings-app (PSA)
Bij het ontwerpen van een afdrukondersteunings-app is het belangrijk om deze aspecten in het ontwerp op te nemen:
Zowel voorgrond- als achtergrondcontracten moeten worden gemarkeerd als het ondersteunen van meerdere instanties. Bijvoorbeeld, SupportsMultipleInstance moet aanwezig zijn in het pakketmanifest. Dit is om ervoor te zorgen dat de levensduur van de contracten betrouwbaar kan worden beheerd voor meerdere gelijktijdige taken.
Behandel het starten van de gebruikersinterface voor PDL-aanpassing als een optionele stap. Doe je best om de afdruktaak te voltooien, ook als het starten van de gebruikersinterface niet is toegestaan. Afdruktaken mogen alleen worden afgebroken als er geen manier is om ze zonder gebruikersinvoer te voltooien tijdens het wijzigen van PDL. Overweeg om de PDL in dergelijke gevallen ongewijzigd te verzenden.
Wanneer u de gebruikersinterface voor PDL-wijziging start, roept u IsUILaunchEnabled aan voordat u LaunchAndCompleteUIAsync-aanroept. Dit is om ervoor te zorgen dat scenario's die de gebruikersinterface op het huidige moment niet kunnen weergeven, correct blijven afdrukken. Deze scenario's kunnen zich op een headless apparaat of een apparaat bevinden dat zich momenteel in de kioskmodus bevindt of de modus niet storen.
Verwante artikelen
einde van het onderhoudsplan voor printerstuurprogramma's van derden in Windows
IPP-specificatie (Internet Printing Protocol)
App-associatie voor ondersteuning van afdrukken