Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede, Windows kullanıcısının yazdırma deneyimini çeşitli yollarla geliştirebilecek bir yazdırma destek uygulaması (PSA) geliştirmeye yönelik yazıcı OEM'leri ve IHV'leri için yönergeler ve örnekler sağlanmaktadır.
Windows 11 SDK'sının (22000.1) piyasaya sürülmesiyle başlayarak Yazdırma Desteği Uygulamaları (PSA), yazıcılar için UWP uygulamaları geliştirmenin önerilen yöntemidir. Yazdırma cihazınız için bir Yazdırma Desteği Uygulaması geliştirmek için, hedeflediğiniz Windows sürümü için Windows 11 SDK'sını indirip yükleyin.
Bu makale, Windows 11, sürüm 22H2'den itibaren kullanılabilen PSA işlevselliğini açıklayan bölümler içerir. Bu bölümler, bu sürüm için geçerli olduğunu belirten bir not içerir.
Daha fazla bilgi için aşağıdaki makalelere bakın:
| Konu | Açıklama |
|---|---|
| Yazdırma Desteği Uygulaması v3 API tasarım kılavuzu | Cihazları için v3 Yazdırma Desteği Uygulaması (PSA) uygulayan yazıcı OEM'leri ve IHV'leri için rehberlik ve örnekler sağlar. |
| Yazdırma Desteği Uygulaması v4 API tasarım kılavuzu | Cihazları için v4 Yazdırma Desteği Uygulaması (PSA) uygulayan yazıcı OEM'leri ve IHV'leri için rehberlik ve örnekler sağlar. |
| Yazdırma Desteği Sanal Yazıcı için MSIX Bildirim Spesifikasyonu | Yazıcı OEM'leri ve IHD'lerin, Yazdırma Desteği Sanal Yazıcısı uygulaması yaparken ihtiyaç duyacağı MSIX bildirim kılavuzu ve örneklerini sağlar. |
| Yazdırma desteği uygulaması ilişkilendirme | Yazdırma desteği uygulamasını (PSA) yazıcıyla ilişkilendirmek için rehberlik ve örnekler sağlar. |
Bazı yazıcı özellikleri, bir üretici uygulamasının doğru yapılandırılması için yardıma ihtiyaç duyan özel özellikler olduğundan, Windows tarafından gösterilen yazdırma iletişim kutularına sunulmaz. Bunlar, yazıcının varsayılan özelliklerinde sağlanmayan özellikler de olabilir.
Yazıcıya özgü özellikler, kullanıcının bir seçenek belirlemesini ve bu senaryoda yer alan tüm özelliklerin otomatik olarak doğru değerlere ayarlandığına güvenmesini kolaylaştıracak şekilde gruplandırılabilir. Bunun bir örneği, mürekkep tasarrufu, kağıt tasarrufu ve en yüksek kalite modları arasında, çeşitli yazdırma özelliklerini kullanıcıdan gelen bir seçime göre otomatik olarak işleyebilecek bir seçim olabilir. Windows, her yazıcı modelinin tüm özel özelliklerinin anlaşılmasını gerektirdiğinden bunları otomatik olarak gruplandıramaz.
Özel yazdırma tercihlerini gösterme gereksinimi, bu API tarafından tüm Windows yazdırma iletişim kutuları ve Windows tarafından sağlanan API kullanan özel yazdırma iletişim kutuları aracılığıyla kullanıcı tarafından etkinleştirilebilen isteğe bağlı bir UWP uzantısı sözleşmesiyle giderilmiştir. Üreticiler kullanıcı arabirimini, kullanıcının sahip olduğu yazıcı için en iyi yazdırma deneyimini sağlayacak şekilde uyarlayabilmektedir.
Yazıcı üreticilerinin geliştirebileceği ve ayırt ettiği bir diğer alan da baskı kalitesidir. Üreticiler, belirli bir yazıcının içeriğini iyileştirerek işleme sonrasında baskı kalitesini geliştirebilir. Ayrıca, yazıcıya özgü özellikleri dikkate alabildiği için son çıkışı daha iyi temsil eden yüksek kalitede bir önizleme de sunabilirler.
Terminoloji
| Terim | Tanım |
|---|---|
| PSA | Yazdırma Desteği Uygulaması. Bu makalede açıklanan API'yi kullanan bir UWP uygulaması. |
| Metropol Polis Departmanı (MPD) | Modern Yazdırma İletişim Kutusu. Bu, bir uygulama Windows.Graphics.Printing API'sini kullanarak yazdırırken kullanıcıya gösterilir. |
| Sürekli Mesleki Gelişim | Genel Yazdırma İletişim Kutusu. Bu, uygulama Win32 API'sini kullanarak yazdırırken kullanıcıya gösterilir. Baskı önizlemesi göstermesi gereken uygulamalar bu iletişim kutusunu tetiklemez ve bunun yerine kendi iletişim kutusu sürümlerini uygular. Office uygulamaları bunun en önemli örneklerindendir. |
| IPP | İnternet Yazdırma Protokolü. Yazdırma tercihlerini alıp ayarlamak ve yazdırılacak belgeyi göndermek üzere yazıcıyla etkileşim kurmak için bir istemci cihazdan kullanılır. |
| Yazdırma Desteğine Bağlı Yazıcı | PSA'ya bağlı yazıcı. |
| IPP Yazıcısı | IPP protokollerini destekleyen yazıcı. |
| Diğer Ayarlar | MPD'de iş ortağı uygulamasının sağladığı kullanıcı arabirimini açan bağlantı. PSA yüklü olmadığında yerleşik yazdırma tercihleri kullanıcı arabirimini açma varsayılanlarıdır. |
| Yazıcı Tercihleri Kullanıcı Arabirimi | Yazdırma zamanında uygulanan varsayılan yazıcı seçeneklerini ayarlamak için kullanılan iletişim kutusu. Örneğin: yönlendirme, kağıt boyutu, renk, her iki tarafa da yazdırma vb. |
| PDL | Sayfa Açıklaması Dili. Belgenin yazıcıya gönderildiği biçim. |
| İlişkili PSA Yazıcısı | PSA uygulamasıyla ilişkili fiziksel IPP yazıcısı. |
| Yazıcı Cihaz Yetenekleri | Yazıcı özelliklerini tanımlamak için XML belge biçimi. Daha fazla bilgi için bkz. Yazdırma Bileti ve Yazdırma Özellikleri Teknolojileri. |
| PrintTicket | Belirli bir yazdırma işi için kullanıcının amacını yakalamak için kullanılan yazdırmayla ilgili çeşitli özelliklerin ve değerlerinin koleksiyonu. |
| Yazdırma Destek Uzantısı | Yazıcı kısıtlama uzantısı özelliklerini sağlamakla sorumlu olan bir PSA arka plan görevi. |
Yazdırma desteği ad alanı
Bu örnekler, aşağıdaki gibi tanımlanan printsupport ad alanına başvurur:
xmlns:printsupport="http://schemas.microsoft.com/appx/manifest/printsupport/windows10"
Yazdırma desteği kullanıcı arabirimi ayarları
Bir kullanıcı belgeyi yazdırmak üzereyken, çoğunlukla belgeyi yazdırmak için bazı tercihler ayarlamak ister. Örneğin, belgeyi yatay yönde yazdırmayı seçebilirler. Ayrıca yazıcılarının desteklediği özel özelliklerden de yararlanabilirler. Windows, özel tercihleri göstermek için varsayılan kullanıcı arabirimi sağlar, ancak uygun simgeler veya açıklamalar olmadığından kullanıcı bunları anlamayabilir. Windows bunu sunmak için yanlış kullanıcı arabirimi denetimini de kullanıyor olabilir. Böyle özel bir özellik en iyi şekilde özelliği tamamen anlayan bir uygulama tarafından sunulur. Bu, yazıcı üreticilerinin yaptıkları çeşitli yazıcı modellerine göre uyarlanmış uygulamalar oluşturmasına olanak tanıyan bir API sunmanın ardındaki motivasyondur.
windows.printSupportSettingsUI adlı yeni bir kategoriyle yeni bir UAP uzantı sözleşmesi oluşturulur. Bu sözleşmeyle etkinleştirilen uygulamalar PrintSupportSettingsUI adlı yeni bir ActivationKind alır. Bu sözleşme yeni bir özellik gerektirmez.
<Extensions>
<printsupport:Extension Category="windows.printSupportSettingsUI"
EntryPoint="PsaSample.PsaSettingsUISample"/>
</Extensions>
Bu sözleşme, kullanıcı MPD'de
Yazdırma Desteği Uygulamasının farklı yazdırma işleri için birden çok eşzamanlı etkinleştirmeyi işlemesi beklenir, bu nedenle böyle bir uygulamanın package.appxmanifest dosyasındaki SupportsMultipleInstances öğesini kullanarak birden çok örneği desteklemesi gerekir. Bunun yapılmaması, bir yazdırma işinin tercihlerini onaylamanın açık olabilecek diğer tercih pencerelerini kapatabileceği durumlara neden olabilir. Kullanıcının bu tercih pencerelerini yeniden açması gerekir.
Aşağıdaki sıra diyagramı, Ayarlar arayüzünün yazdırma bileti düzenleme kavramını temsil eder.
Ayarlar arayüzünde PrintTicket ayarını değiştirme
Herhangi bir yazdırma iletişim kutusundan (MPD/CPD veya özel yazdırma iletişim kutusu) veya sistem ayarlarından başlatıldığında Ayarlar kullanıcı arabiriminin etkinleştirilmesi için C# örnek kodu:
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();
}
}
}
DefaultSettingsView sınıfı için XAML:
<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>
Kullanıcı arabirimini göstermek ve PrintTicket'i değiştirmek için C# örnek kodu:
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();
}
}
}
Yazıcı cihazından yazıcı özniteliklerini alma
IPP yazıcısından get-printer-attributes sorgusuna WireShark yanıtı:
Yazıcıdan mürekkep adlarını ve mürekkep düzeylerini almak için C# örnek kodu:
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));
}
}
}
}
Yazıcıda yazıcı özniteliklerini ayarlama
Yazıcı özniteliklerini ayarlamak için C# örnek kodu:
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;
}
}
}
}
Yazıcı kısıtlamalarını genişletme
Yazdırma Desteği Uygulaması özel PrintTicket doğrulamasını ve varsayılan PrintTicket'i tanımlamayı destekler. Bu bölümde bu özellikleri nasıl desteklediğimiz açıklanmaktadır.
Yazıcı uzantısı kısıtlamalarını desteklemek için PrintSupportExtension adlı yeni bir arka plan görev türü uygulanmıştır. Package.appxmanifest,burada gösterildiği gibi Yazdırma Desteği Uzantısı için bir genişletilebilirlik girdisine sahiptir:
<Extensions>
<printsupport:Extension Category="windows.printSupportExtension"
EntryPoint="PsaBackgroundTasks.PrintSupportExtension"/>
</Extensions>
Bu hizmet, ilişkili IPP yazıcısı için yazdırma işinin herhangi bir noktasında çalışabilir. Print Desteği Uzantısı, IBackgroundTaskInstance
event Windows.Foundation.TypedEventHandler<PrintSupportExtensionSession, PrintSupportPrintTicketValidationRequestedEventArgs>; PrintTicketValidationRequested;Yazdırma Desteği Uzantısı kendi PrintTicket doğrulama mekanizmasını sağlıyorsa, bu olaya kaydolabilir. Bir PrintTicket doğrulanması gerektiğinde, yazdırma sistemi bu etkinliği tetikler. PrintSupportExtension, EventArgs içinde doğrulanması gereken geçerli PrintTicket alır. PrintSupportExtension arka plan sınıfı, PrintTicket belgesinin geçerliliğini kontrol edebilir ve çakışmaları çözmek için onu değiştirebilir. PrintSupportExtension arka plan sınıfı daha sonra SetPrintTicketResult işlevini kullanarak doğrulama sonucunu ayarlayarak PrintTicket çözümlenip çözümlenmediğini, çakışmalar olup olmadığını veya geçersiz olduğunu belirtmelidir. Bu olay, yazdırma işinin ömrü boyunca her zaman tetiklenebilir. PrintSupportExtension sınıfı bu olay için kaydedilmezse, yazdırma sistemi kendi PrintTicket doğrulamasını yapar.
event Windows.Foundation.TypedEventHandler<PrintSupportExtensionSession, PrintSupportPrintDeviceCapabilitiesChangedEventArgs>; PrintDeviceCapabilitiesChanged;Olay, yazdırma sistemi, ilişkili IPP yazıcısının önbelleğe alınmış PrintDeviceCapabilities'ini güncelledikten sonra tetiklenir. Bu olay tetiklendiğinde, PrintSupportExtension arka plan sınıfı, değiştirilen PrintDeviceCapabilities inceleyebilir ve değiştirebilir.
Yazdırma belgesinin özelleştirilmiş doğrulaması
PrintTicket doğrulama hizmeti sağlamaya yönelik C# örnek kodu:
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);
}
}
Yazdırma Cihazı Yetkinlikleri Güncelleniyor
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);
}
}
Baskı kalitesinin geliştirilmesi
Kullanıcı yazdırma iletişim kutusundaki yazdır düğmesine basarak yazdırmayı taahhüt ettikten sonra, yazdırılacak belge yazdırılan uygulamadan yazdırma yığınına gönderilir. Bu belge daha sonra hedef yazıcıya uygun hale getirmek için dönüştürmeden (PDL'ye işleme) geçer. Windows, yazıcıdan sorgulanan özniteliklere göre hangi dönüşümün seçileceğini belirler. Dönüştürülen belge daha sonra yazıcıya gönderilir. Bu, çoğu yazıcı için iyi olsa da, bir iş ortağı uygulamasının dönüşüme katılmasına izin vererek yazdırma kalitesinin iyileştirilebileceği durumlar vardır. Bunu kolaylaştırmak için geçerli yazdırma İş Akışı API'si, yazdırma yığınından ek noktalarda uygulamaya yapılan çağrıları içerecek şekilde genişletilir. Bu API, PSA uygulamasının kaydolabileceği iki yeni olayı destekler. PSA API yüzeyine tek giriş noktaları şunlardır:
İşi Başlatma
- Bu olay, herhangi bir uygulama tarafından bir yazdırma işi başlatıldığında oluşturulur. Olay oluşturulduğunda, Yazdırma Desteği Uygulaması sistem işlemeyi atlamak için PrintWorkflowJobStartingEventArgsüzerinde SetSkipSystemRendering çağırmayı tercih edebilir. Sistem işlemeyi atla seçilirse, yazdırma sistemi XPS belgesini yazıcının gerektirdiği PDL biçimine dönüştürmez. Bunun yerine, yazdırma uygulaması tarafından oluşturulan XPS doğrudan XPS'yi PDL biçimine dönüştürmekle sorumlu olan PSA'ya verilir.
PdlModificationRequested
- Bu olay, Windows XPS akışını yazıcı tarafından belirtilen PDL biçimine dönüştürmeyi başlattığında tetiklenir. Çalışma zamanı sınıfı PrintWorkflowPdlModificationRequestedEventArgs, bu olay için bağımsız değişken olarak sağlanır. Bu olay sınıfı, yazdırma işi içeriğini okumak ve yazmak için PDL kaynağı ve hedef nesneleri sağlar. Uygulama kullanıcı girişi gerektiğini belirlerse, EventArgs'den PrintWorkflowUILauncher kullanarak kullanıcı arabirimini başlatabilir. Bu API Tester-Doer desenini kullanır. IsUILaunchEnabled
işlevi false döndürürse PrintWorkflowUILauncher kullanıcı arabirimini çağıramaz. PSA oturumu sessiz modda (headless veya kiosk modu) çalışıyorsa bu işlev yanlış döndürür. İşlev false döndürürse Yazdırma Desteği Uygulaması kullanıcı arabirimini başlatmayı denememelidir.
GetStreamTargetAsync işlevi tarafından döndürülen PrintWorkflowPdlTargetStream'in bir parçası olarak bir OutputStream sağlanır. Hedef OutputStream'e yazılan içerik, yazıcıya belge içeriği olarak geçirilir.
- Bu olay, Windows XPS akışını yazıcı tarafından belirtilen PDL biçimine dönüştürmeyi başlattığında tetiklenir. Çalışma zamanı sınıfı PrintWorkflowPdlModificationRequestedEventArgs, bu olay için bağımsız değişken olarak sağlanır. Bu olay sınıfı, yazdırma işi içeriğini okumak ve yazmak için PDL kaynağı ve hedef nesneleri sağlar. Uygulama kullanıcı girişi gerektiğini belirlerse, EventArgs'den PrintWorkflowUILauncher kullanarak kullanıcı arabirimini başlatabilir. Bu API Tester-Doer desenini kullanır. IsUILaunchEnabled
PDL değişiklik olayı için sıralı diyagram:
PSA arka plan görevi kullanıcı arabirimini başlatmayı istediğinde PSA ön plan uygulaması başlatılır. PSA, ön plan kontratını kullanarak kullanıcı girişi alabilir ve/veya kullanıcıya baskı önizlemesi gösterebilir.
Yazdırma desteği iş akışı arka plan görevi
Yeni bir printSupportWorkflow arka plan görev türü tanımlandı. Package.appxmanifest PrintSupportWorkflow sözleşmesi için aşağıdaki genişletilebilirlik girdisine sahiptir:
<Extensions>
<printsupport:Extension Category="windows.printSupportWorkflow"
EntryPoint="PsaBackgroundTasks.PrintSupportWorkflowSample"/>
</Extensions>
Sözleşme etkinleştirildiğinde, PrintWorkflowJobTriggerDetailsIBackgroundTaskInstance->TriggerDetailsolarak verilir. PrintWorkflowJobTriggerDetails, özellikleri arasında PrintWorkflowJobBackgroundSession sağlar. Uygulama, PrintWorkflowJobBackgroundSession'i yazdırma işi iş akışındaki çeşitli ekleme noktalarıyla ilgili olaylara kaydolmak için kullanabilir. Olay kaydı tamamlandıktan sonra, uygulamanın yazdırma sisteminin çeşitli ekleme noktalarıyla ilgili olayları tetiklemesi için PrintWorkflowJobBackgroundSession::Start çağrısı yapması gerekir.
Yazdırma iş akışı kullanıcı arayüzü
PrintSupportJobUI adlı yeni bir ActivationKind tanımlanır. Bunun için yeni bir özellik gerekmez.
<Extensions>
<printsupport:Extension Category="windows.printSupportJobUI"
EntryPoint="PsaSample.PrintSupportJobUISample"/>
</Extensions>
Bu, ya Yazdırma Desteği İş Akışı arka plan sözleşmesinden ya da kullanıcı bir yazdırma işi hata uyarısını seçtiğinde başlatılabilen bir kullanıcı arabirimi sözleşmesidir. Etkinleştirildiğinde, PrintWorkflowJobActivatedEventArgs sağlanır, bu da bir PrintWorkflowJobUISession nesnesi içerir. PrintWorkflowJobUISessionkullanarak, ön plan uygulaması PDL verilerine erişmek istiyorsa PdlDataAvailable olayına kaydolmalıdır. Ön plan uygulaması iş sırasında oluşabilecek hatalar için özel hata iletileri göstermek istiyorsa, JobNotification olayına kaydolması gerekir. Olaylar kaydedildikten sonra, yazdırma sisteminin olayları tetiklemesi için uygulamanın PrintWorkflowJobUISession::Start işlevini çağırması gerekir.
Sistem rendering atlanıyor
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 değişiklik olayı
PDL değişiklik olayı için sıralı diyagram:
Yazdırma Desteği İş İzleyicisi'nin yazdırma işi içeriğini okuması ve yazması için C# örnek kodu:
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();
}
}
}
İş akışı arka planından kullanıcı arabirimini başlatma
PSA PDL değişikliği talep edilen olay sözleşmesinden Yazdırma Destek İşi kullanıcı arayüzünü başlatmak için C# örnek kodu:
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();
}
}
PDLDataAvailable olayı için iş akışı kullanıcı arabirimi etkinleştirme
PdlDataAvailable olayı için yazdırma işi kullanıcı arabirimini etkinleştirme dizilim diyagramı:
PSA işi kullanıcı arayüzü etkinleştirme sözleşmesi için C# örnek kodu:
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);
}
}
}
}
Yazıcı işi özniteliklerini alma
Yazdırma işinin iş özniteliklerini almak için C# örnek kodu:
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();
}
}
}
Yazıcı işi özniteliklerini ayarlama
C# örnek kodu, yukarıdaki Yazıcı işi özniteliklerini alma bölümünden devam ederek iş özniteliklerini ayarlamayı gösterir:
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);
}
}
Bazı IPP yazıcıları, iş oluşturulduktan sonra iş özniteliklerini almayı/ayarlamayı desteklemez. Bu yazıcılar için PrintJobJobId özelliği "0" olarak ayarlanmıştır ve GetJobAttributes/SetJobAttributes hemen bir özel durumla başarısız olur.
PDL içeriğine depolama dosyası erişimi sağlama
PDF gibi bazı PDL biçimlerinin işlemeye başlayabilmeniz için tam bir akışa sahip olması gerekir. Bu nedenle, kaynak içeriğin bir StorageFile nesnesini döndüren GetContentFileAsync adlı yeni bir yöntem, PrintWorkflowPdlSourceContent sınıfında sağlanmıştır.
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);
}
}
}
}
}
XPS'nin PDF'ye PDL dönüşümü
XPS'nin PDF'ye PDL dönüşümünün gösterildiği C# örnek kodu:
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();
}
İş bildirimi olayı
İş bildirimi olayı için sıralı diyagram:
C# örnek kodu, yukarıdaki PDLDataAvailable olay bölümünden iş akışı işinin kullanıcı arabirimini etkinleştirme işlemine devam ederek, iş bildiriminde bir hata gösterecek şekilde tasarlanmıştır.
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;
}
}
}
}
Başlangıç iş öznitelikleriyle bir iş oluşturma
Şu anda bazı IPP yazıcıları set-attribute işlemini desteklememektedir. CreateJobOnPrinterWithAttributes işlevi ve CreateJobOnPrinterWithAttributesBuffer işlevi, PrintWorkflowPdlDataAvailableEventArgs'da bu sorunu azaltmak için sağlanır. Bir PSA geliştiricisi bu API'leri kullanarak, yazıcıda iş oluşturulduğunda yazıcıya geçirilen iş özniteliklerini sağlayabilir.
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
}
}
Sıralı XPS işleme
Biriktirme tamamlanmadan önce XPS'yi sıralı olarak işlemek için C++/Winrt örnek kodu.
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()));
}
}
}
Görünen ad yerelleştirmesi ve PDL Geçiş API entegrasyonu
Önemli
Bu bölümde, Windows 11, sürüm 22H2'den itibaren kullanılabilen PSA işlevselliği açıklanmaktadır.
Bu senaryoda PSA, Yazdırma Cihazı Özelliklerini (PDC) özelleştirir ve dize yerelleştirmesi için Yazdırma Cihazı Kaynakları (PDR) sağlar.
PSA, desteklenen PDL Geçiş API'sinin içerik türlerini de (PDL biçimleri) ayarlar. Eğer PSA olaya abone olmazsa veya SetSupportedPdlPassthroughContentTypes fonksiyonunu açıkça çağırmazsa, bu PSA uygulamasıyla ilişkili yazıcılar için PDL Passthrough devre dışı bırakılır.
// 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);
}
}
Sayfa düzeyi özellik desteği ve işlem öznitelikleri
Önemli
Bu bölümde, Windows 11, sürüm 22H2'den itibaren kullanılabilen PSA işlevselliği açıklanmaktadır.
Sayfa düzeyi özellik desteği ve işlem öznitelikleri senaryoları, örnek kodda aynı yerde değişiklikler yapılarak ele alındıkları için gruplandırılır.
Sayfa düzeyi özellik desteği: Bu senaryoda PSA uygulaması, PrintTicket'ten ayrıştırılan bir IPP özniteliği tarafından geçersiz kılınmaması gereken sayfa düzeyi özniteliğini belirtir.
İşlem öznitelikleri için ayrı koleksiyon desteği (PIN yazdırma): Bu senaryoda PSA uygulaması özel IPP işlem özniteliklerini (örneğin, PIN) belirtir.
Aşağıdaki C# örnek kodu, Sayfa Düzeyi özellik desteği için gerekli değişiklikleri ve İşlem öznitelikleri senaryoları için ayrı koleksiyonları gösterir.
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();
}
}
PSA ile yazdırma iletişim kutusunu geliştirme
Önemli
Bu bölümde, Windows 11, sürüm 22H2'den itibaren kullanılabilen PSA işlevselliği açıklanmaktadır.
Bu senaryoda, PSA tümleştirmesi ile yazdırma iletişim kutusunun kullanılması aşağıdaki eylemleri etkinleştirir:
PSA ile ilişkilendirilmiş yazıcıya MPD'de seçim değiştirildiğinde geri arama alın.
openUrl eylemi desteğiyle bir AdaptiveCard göster
Yazdırma iletişim kutusunda özel özellikleri ve parametreleri gösterme
PrintTicket'i değiştirerek yazdırma iletişim kutusunda gösterilen özellik seçenekleri seçimini değiştirme
Yazdırma uygulamasının Windows.ApplicationModel.AppInfo edinin ve yazdırma iletişim kutusunu açın.
Aşağıdaki C# örneği bu yazdırma iletişim kutusu geliştirmelerini gösterir:
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""
}}");
}
Ana bilgisayar tabanlı işlem bayraklarıyla PDL dönüştürme
Önemli
Bu bölümde, Windows 11, sürüm 22H2'den itibaren kullanılabilen PSA işlevselliği açıklanmaktadır.
Geçerli PDL dönüştürme API'si, PrintWorkflowPdlConverter.ConvertPdlAsync, varsayılan olarak sunucu tabanlı işleme gerçekleştirir. Başka bir deyişle, ana bilgisayar/yazdırma bilgisayarı döndürme, sayfa sırası vb. yapar, böylece yazıcının bu işlemleri gerçekleştirmesi gerekmez. Ancak, yazıcı IHV'leri, yazıcının bunu daha iyi yapabileceğinden, konak tabanlı işleme olmadan PDL dönüştürmesi isteyebilir. ConvertPdlAsync işlevi, bu gereksinimi karşılamak için konak tabanlı işleme bayraklarını alır. PSA, bu bayrağı kullanarak tüm konak tabanlı işlemleri veya belirli bir konak tabanlı işleme işlemini atlayabilir.
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
}
Yazdırma Cihazı Özellikleri (PDC) güncelleştirme ilkesini ayarlama
Önemli
Bu bölümde, Windows 11, sürüm 22H2'den itibaren kullanılabilen PSA işlevselliği açıklanmaktadır.
Yazdırma Cihazı Özellikleri'nin (PDC) güncelleştirilmesi gerektiğinde yazıcı IHV'lerinin gereksinimleri farklı olabilir. Bu gereksinimleri karşılamak için PrintSupportPrintDeviceCapabilitiesUpdatePolicy PDC için bir güncelleştirme ilkesi ayarlayabilir. PSA, bu API'yi kullanarak pdc güncelleştirme ilkesini zamana veya yazdırma işlerinin sayısına göre ayarlayabilir.
pdc güncelleştirme ilkesini iş sayısına göre ayarlama
// 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 güncelleştirme ilkesini TimeOut'a göre ayarlama
// 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);
}
}
Genel yazdırma desteği uygulaması (PSA) tasarım kılavuzu
Yazdırma desteği uygulaması tasarlarken tasarıma şu özelliklerin eklenmesi önemlidir:
Hem ön plan hem de arka plan sözleşmeleri birden çok örneği destekliyor olarak işaretlenmelidir, örneğin, SupportsMultipleInstance paket bildiriminde bulunmalıdır. Bu, sözleşmelerin kullanım ömrünün birden çok eşzamanlı iş için güvenilir bir şekilde yönetilebilmesini sağlamaktır.
PDL değişikliği için kullanıcı arabirimi başlatmayı isteğe bağlı bir adım olarak değerlendirin. Kullanıcı arabiriminin başlatılmasına izin verilmese bile yazdırma işini başarıyla tamamlamak için elinden geleni yapın. Yazdırma işleri, PDL değişikliği sırasında kullanıcı girişi olmadan başarıyla tamamlanmalarının hiç bir yolu yoksa durdurulmalıdır. Bu gibi durumlarda PDL'yi değiştirilmemiş olarak göndermeyi göz önünde bulundurun.
PDL değişikliği için kullanıcı arabirimini başlatırken, IsUILaunchEnabled çağırın ve ardından LaunchAndCompleteUIAsyncçağırın. Bu, şu anda kullanıcı arabirimini gösteremeyen senaryoların doğru şekilde yazdırılmaya devam edilmesini sağlamak içindir. Bu senaryolar, başsız bir cihazda veya şu anda kiosk modunda ya da rahatsız etmeyin modunda olan bir cihazda olabilir.
İlgili makaleler
Windows'da üçüncü taraf yazıcı sürücüleri için hizmet sonu planı
İnternet Yazdırma Protokolü (IPP) belirtimi
Yazdırma desteği uygulaması ilişkilendirme
Windows.Devices.Printers
Windows.Graphics.Printing.PrintSupport
Windows.Graphics.Printing.Workflow