Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Penting
Metadata perangkat tidak digunakan lagi dan akan dihapus dalam rilis Windows mendatang. Untuk informasi tentang penggantian fungsionalitas ini, lihat Metadata Kontainer Paket Driver.
Artikel ini memberikan panduan dan contoh bagi OEM printer dan IHV untuk mengembangkan aplikasi dukungan cetak (PSA) yang dapat meningkatkan pengalaman cetak pengguna Windows dengan beberapa cara.
Dimulai dengan rilis Windows 11 SDK (22000.1), Print Support Apps (PSA) adalah metode yang direkomendasikan untuk mengembangkan aplikasi UWP untuk printer. Untuk mengembangkan Aplikasi Dukungan Cetak untuk perangkat cetak Anda, unduh dan instal Windows 11 SDK untuk versi Windows yang Anda targetkan.
Artikel ini berisi bagian yang menjelaskan fungsionalitas PSA yang tersedia mulai Windows 11, versi 22H2. Bagian tersebut berisi catatan yang menunjukkan bahwa itu berlaku untuk versi tersebut.
Untuk informasi selengkapnya, lihat artikel berikut ini:
| Topik | Deskripsi |
|---|---|
| Panduan Desain API Print Support App v3 | Memberikan panduan dan contoh untuk OEM printer dan IHV yang mengimplementasikan Aplikasi Dukungan Cetak (PSA) v3 untuk perangkat mereka. |
| panduan desain API Print Support App v4 | Memberikan panduan dan contoh untuk OEM printer dan IHV yang mengimplementasikan Aplikasi Dukungan Cetak (PSA) v4 untuk perangkat mereka. |
| Spesifikasi Manifes MSIX untuk Dukungan Pencetakan Printer Virtual | Menyediakan panduan dan contoh manifes MSIX untuk OEM printer dan IHV yang mengimplementasikan Printer Virtual untuk Dukungan Cetak. |
| Asosiasi Aplikasi Pendukung Cetak | Menyediakan panduan dan contoh untuk mengaitkan aplikasi dukungan cetak (PSA) dengan printer. |
Beberapa fitur printer tidak disajikan dalam dialog cetak yang ditunjukkan oleh Windows karena fitur tersebut adalah fitur khusus yang memerlukan bantuan dari aplikasi produsen untuk dikonfigurasi dengan benar. Mungkin ada fitur lain yang tidak disediakan dalam fungsi default printer.
Fitur spesifik printer dapat dikelompokkan dengan cara yang memudahkan pengguna untuk memilih opsi dan mempercayai bahwa semua fitur yang terlibat dalam skenario tersebut secara otomatis diatur ke nilai yang benar. Contohnya bisa menjadi pilihan antara penghemat tinta, penghemat kertas, dan mode kualitas tertinggi yang dapat memanipulasi berbagai fitur cetak secara otomatis berdasarkan satu pilihan dari pengguna. Windows tidak dapat mengelompokkannya secara otomatis karena memerlukan pemahaman semua fitur kustom dari setiap model printer.
Kebutuhan untuk menampilkan preferensi cetak kustom ditangani oleh API ini dengan kontrak ekstensi UWP opsional yang dapat diaktifkan oleh pengguna dari semua dialog cetak Windows dan dialog cetak kustom yang menggunakan API yang disediakan oleh Windows. Produsen dapat menyesuaikan UI mereka untuk memberikan pengalaman cetak terbaik untuk printer tertentu yang dimiliki pengguna.
Area lain di mana produsen printer dapat meningkatkan dan membedakan adalah kualitas cetak. Produsen dapat meningkatkan kualitas cetak setelah penyajian dengan mengoptimalkan isi untuk printer tertentu. Mereka juga dapat menyajikan pratinjau keakuratan tinggi yang lebih mewakili output akhir karena dapat mempertimbangkan fitur spesifik printer.
Terminologi
| Istilah | Definisi |
|---|---|
| PSA | Cetak Aplikasi Dukungan. Aplikasi UWP yang menggunakan API yang dijelaskan dalam artikel ini. |
| MPD | Dialog Cetak Modern. Ini ditampilkan kepada pengguna saat aplikasi mencetak menggunakan Windows.Graphics.Printing API. |
| Pengembangan Profesional Berkelanjutan | Dialog Cetak Umum. Ini ditampilkan kepada pengguna saat aplikasi mencetak menggunakan API Win32. Aplikasi yang perlu menampilkan pratinjau cetak tidak memicu dialog ini dan malah menerapkan versinya sendiri dari dialog tersebut. Aplikasi Office adalah contoh utama dari ini. |
| IPP | Protokol Pencetakan Internet. Digunakan dari perangkat klien untuk berinteraksi dengan printer untuk mengambil dan mengatur preferensi pencetakan dan mengirim dokumen yang akan dicetak. |
| Dukungan Pencetakan untuk Printer yang Terhubung | Printer yang ditautkan ke PSA. |
| IPP Printer | Printer yang mendukung protokol IPP. |
| Pengaturan Lainnya | Tautan yang membuka UI aplikasi yang disediakan mitra di MPD. Secara default membuka antarmuka pengguna (UI) preferensi cetak bawaan saat tidak ada PSA yang diinstal. |
| Antarmuka Pengguna Preferensi Printer | Dialog yang digunakan untuk mengatur opsi printer default yang diterapkan pada waktu cetak. Misalnya: orientasi, ukuran kertas, warna, cetak di kedua sisi, dan sebagainya. |
| PDL | Bahasa Deskripsi Halaman. Format di mana dokumen dikirim ke pencetak. |
| Printer PSA yang Terkait | Printer IPP fisik yang terkait dengan aplikasi PSA. |
| KemampuanPerangkatCetak | Format dokumen XML untuk menentukan kemampuan printer. Untuk informasi selengkapnya, lihat Tiket Cetak dan Teknologi Kemampuan Cetak. |
| PrintTicket | Kumpulan berbagai fitur terkait cetak dan nilainya yang digunakan untuk menangkap niat pengguna untuk pekerjaan cetak tertentu. |
| PrintSupportExtension | Tugas latar belakang PSA yang bertanggung jawab untuk menyediakan kemampuan perpanjangan batasan printer. |
Namespace dukungan cetak
Sampel ini mengacu pada namespace printsupport, yang didefinisikan sebagai:
xmlns:printsupport="http://schemas.microsoft.com/appx/manifest/printsupport/windows10"
Pengaturan dukungan cetak antarmuka pengguna
Ketika pengguna akan mencetak dokumen, mereka sering ingin mengatur beberapa preferensi untuk mencetaknya. Misalnya, mereka dapat memilih untuk mencetak dokumen dalam orientasi lanskap. Mereka juga dapat memanfaatkan fitur kustom yang didukung printer mereka. Windows menyediakan antarmuka pengguna default untuk menampilkan preferensi kustom, tetapi pengguna mungkin tidak memahaminya karena tidak ada ikon atau deskripsi yang sesuai. Windows mungkin juga menggunakan kontrol UI yang salah untuk menyajikannya. Fitur kustom seperti itu paling baik disajikan oleh aplikasi yang memahami fitur sepenuhnya. Ini adalah motivasi di balik penawaran API yang memungkinkan produsen printer membuat aplikasi yang disesuaikan dengan berbagai model printer yang mereka buat.
Kontrak ekstensi UAP baru dibuat dengan kategori baru bernama windows.printSupportSettingsUI. Aplikasi yang diaktifkan dengan kontrak ini menerima ActivationKind baru yang disebut PrintSupportSettingsUI. Kontrak ini tidak memerlukan kemampuan baru.
<Extensions>
<printsupport:Extension Category="windows.printSupportSettingsUI"
EntryPoint="PsaSample.PsaSettingsUISample"/>
</Extensions>
Kontrak ini dipanggil saat pengguna memilih Pengaturan Lainnya di Preferensi MPD atau di CPD. Kontrak ini juga dapat diakses dari Preferensi Pencetakan di aplikasi Pengaturan. Saat kontrak diaktifkan, aplikasi menerima objek PrintSupportSettingsUISession yang dapat digunakan untuk mendapatkan objek PrintTicket dan PrintDevice saat ini. Objek PrintDevice dapat digunakan untuk berkomunikasi dengan printer untuk menerima atribut printer dan atribut tugas. Aplikasi kemudian dapat menampilkan UI dengan opsi printer yang sesuai kepada pengguna. Ketika pengguna membuat pilihan dan memilih OK, aplikasi kemudian dapat mengubah tiket cetak, memvalidasinya, lalu mengirimkannya kembali menggunakan objek PrintSupportPrintTicketTarget. Jika pengguna memilih untuk membatalkan jendela preferensi, perubahan harus dibuang, dan aplikasi harus keluar dengan menyelesaikan penangguhan yang diambil dari objek PrintSupportSettingsUISession.
Aplikasi Dukungan Cetak diharapkan menangani beberapa aktivasi simultan untuk pekerjaan cetak yang berbeda, sehingga aplikasi tersebut harus mendukung beberapa instans menggunakan elemen SupportsMultipleInstances dalam file package.appxmanifest. Kegagalan untuk melakukannya dapat mengakibatkan situasi di mana mengonfirmasi preferensi dari satu pekerjaan cetak mungkin menutup jendela preferensi lain yang mungkin terbuka. Pengguna diharuskan untuk membuka jendela preferensi tersebut lagi.
Diagram urutan berikut mewakili konsep manipulasi tiket cetak UI Pengaturan:
Mengubah PrintTicket di UI pengaturan
Kode sampel C# untuk aktivasi antarmuka pengguna Pengaturan saat diluncurkan dari dialog cetak apa pun (MPD/CPD atau dialog cetak kustom) atau dari pengaturan sistem:
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 untuk kelas DefaultSettingsView:
<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>
Kode sampel C# untuk menampilkan UI dan mengubah 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();
}
}
}
Mendapatkan atribut printer dari perangkat printer
Respons WireShark dari printer IPP ke permintaan "get-printer-attributes":
Kode sampel C# untuk mendapatkan nama tinta dan tingkat tinta dari 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));
}
}
}
}
Menyetel atribut printer pada pencetak
Kode sampel C# untuk mengatur atribut printer:
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;
}
}
}
}
Memperluas batasan printer
Aplikasi Dukungan Cetak mendukung validasi PrintTicket kustom dan menentukan PrintTicket default. Bagian ini menjelaskan cara kami mendukung fitur-fitur ini.
Untuk mendukung batasan ekstensi printer, jenis tugas latar belakang baru, PrintSupportExtension, telah diimplementasikan. Package.appxmanifest memiliki entri ekstensibilitas untuk Ekstensi Dukungan Cetak seperti yang ditunjukkan di sini:
<Extensions>
<printsupport:Extension Category="windows.printSupportExtension"
EntryPoint="PsaBackgroundTasks.PrintSupportExtension"/>
</Extensions>
Layanan ini dapat berjalan kapan saja dalam pekerjaan cetak untuk printer IPP terkait. Saat Ekstensi Dukungan Cetak diaktifkan melalui fungsi IBackgroundTaskInstance, instans IBackgroundTaskInstance diberikan kepada PrintSupportExtension untuk menyediakan akses ke kelas runtime PrintSupportExtensionTriggerDetails, yang secara internal menyediakan PrintSupportExtensionSession sebagai properti. Kelas latar belakang PrintSupportExtension kemudian dapat menggunakan objek sesi untuk mendaftar peristiwa yang ingin menyediakan fungsionalitas kustom.
event Windows.Foundation.TypedEventHandler<PrintSupportExtensionSession, PrintSupportPrintTicketValidationRequestedEventArgs>; PrintTicketValidationRequested;Jika Ekstensi Dukungan Cetak menyediakan mekanisme validasi PrintTicket sendiri, maka ekstensi ini dapat mendaftar untuk peristiwa ini. Setiap kali PrintTicket perlu divalidasi, sistem cetak memicu kejadian ini. PrintSupportExtension kemudian akan mendapatkan PrintTicket saat ini yang perlu divalidasi dalam EventArgs. Kelas latar belakang PrintSupportExtension kemudian dapat memeriksa PrintTicket untuk memeriksa validitasnya dan memodifikasinya untuk menyelesaikan konflik apa pun. Kelas latar belakang PrintSupportExtension kemudian harus mengatur hasil untuk validasi menggunakan fungsi SetPrintTicketResult untuk menunjukkan apakah PrintTicket telah diselesaikan, mengalami konflik, atau tidak valid. Kejadian ini dapat dipicu kapan saja selama masa pakai pekerjaan cetak. Jika kelas PrintSupportExtension tidak mendaftar untuk peristiwa ini, sistem cetak melakukan validasinya terhadap PrintTicket.
event Windows.Foundation.TypedEventHandler<PrintSupportExtensionSession, PrintSupportPrintDeviceCapabilitiesChangedEventArgs>; PrintDeviceCapabilitiesChanged;Peristiwa diaktifkan setelah sistem cetak memperbarui data cache PrintDeviceCapabilities dari printer IPP terkait. Ketika peristiwa ini terjadi, kelas latar belakang PrintSupportExtension dapat memeriksa PrintDeviceCapabilities yang diubah dan memodifikasinya.
Validasi kustom tiket cetak
Kode sampel C# untuk menyediakan layanan validasi PrintTicket:
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);
}
}
Memperbarui Kemampuan Perangkat Cetak
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);
}
}
Peningkatan kualitas cetak
Setelah pengguna berkomitmen untuk mencetak dengan menekan tombol cetak pada dialog cetak, dokumen yang akan dicetak dikirim ke tumpukan cetak dari aplikasi yang sedang mencetak. Dokumen ini kemudian mengalami transformasi (penyajian ke PDL) agar cocok untuk printer target. Windows akan menentukan transformasi apa yang akan dipilih berdasarkan atribut yang dikueri dari printer. Dokumen yang diubah kemudian dikirim ke printer. Meskipun ini berfungsi dengan baik untuk sebagian besar printer, ada kasus di mana kualitas cetak dapat ditingkatkan dengan memungkinkan aplikasi mitra untuk berpartisipasi dalam transformasi. Untuk memfasilitasi hal ini, API Alur Kerja pencetakan saat ini diperluas untuk menyertakan panggilan ke aplikasi di titik tambahan dari tumpukan cetak. API ini mendukung dua peristiwa baru yang dapat didaftarkan oleh aplikasi PSA. Ini adalah satu-satunya titik masuk ke permukaan API PSA:
JobStarting
- Peristiwa ini terjadi ketika pekerjaan cetak dimulai oleh aplikasi apa pun. Ketika peristiwa diaktifkan, Aplikasi Dukungan Cetak dapat memilih untuk melewatkan proses render sistem dengan memanggil SetSkipSystemRendering di PrintWorkflowJobStartingEventArgs. Jika memilih untuk melewati rendering sistem, sistem cetak tidak akan mengonversi dokumen XPS menjadi format PDL yang diperlukan oleh printer. Sebaliknya, XPS yang dihasilkan oleh aplikasi pencetakan akan langsung diberikan kepada PSA yang kemudian bertanggung jawab untuk mengonversi XPS ke format PDL.
PdlModificationRequested
- Kejadian ini dimunculkan ketika Windows memulai konversi aliran XPS ke format PDL yang ditunjukkan oleh printer. Kelas runtime PrintWorkflowPdlModificationRequestedEventArgs disediakan sebagai argumen untuk peristiwa ini. Kelas peristiwa ini menyediakan objek sumber dan target PDL untuk membaca dan menulis isi pekerjaan cetak. Jika Aplikasi menentukan bahwa aplikasi memerlukan input pengguna, aplikasi dapat meluncurkan UI menggunakan PrintWorkflowUILauncher dari EventArgs. API ini menggunakan pola Tester-Doer. PrintWorkflowUILauncher tidak akan dapat memanggil UI jika fungsi IsUILaunchEnabled mengembalikan false. Fungsi ini akan mengembalikan nilai false jika sesi PSA dijalankan dalam mode senyap (mode tanpa kepala atau kios). Aplikasi Dukungan Cetak tidak boleh mencoba meluncurkan UI jika fungsi mengembalikan false.
OutputStream tersedia sebagai bagian dari PrintWorkflowPdlTargetStream yang dikembalikan oleh fungsi GetStreamTargetAsync. Konten yang ditulis ke target OutputStream diteruskan bersama ke printer sebagai konten dokumen.
Diagram urutan untuk peristiwa modifikasi PDL:
Aplikasi latar depan PSA diluncurkan ketika tugas latar belakang PSA meminta peluncuran antarmuka pengguna. PSA dapat menggunakan kontrak latar depan untuk mendapatkan input pengguna dan/atau untuk menampilkan pratinjau cetak kepada pengguna.
Tugas latar belakang alur kerja dukungan cetak
Jenis tugas latar belakang printSupportWorkflow baru telah ditentukan. Package.appxmanifest memiliki entri ekstensibilitas berikut untuk kontrak PrintSupportWorkflow:
<Extensions>
<printsupport:Extension Category="windows.printSupportWorkflow"
EntryPoint="PsaBackgroundTasks.PrintSupportWorkflowSample"/>
</Extensions>
Pada aktivasi kontrak, PrintWorkflowJobTriggerDetails dinyatakan sebagai IBackgroundTaskInstance->TriggerDetails. PrintWorkflowJobTriggerDetails secara internal menyediakan PrintWorkflowJobBackgroundSession sebagai bagian dari propertinya. Aplikasi ini dapat menggunakan PrintWorkflowJobBackgroundSession untuk mendaftar kejadian yang terkait dengan berbagai titik injeksi dalam alur kerja cetak. Setelah pendaftaran peristiwa selesai, aplikasi harus memanggil PrintWorkflowJobBackgroundSession::Start untuk sistem cetak untuk mulai menembakkan peristiwa yang terkait dengan berbagai titik injeksi.
Mencetak UI pekerjaan alur kerja
<Extensions>
<printsupport:Extension Category="windows.printSupportJobUI"
EntryPoint="PsaSample.PrintSupportJobUISample"/>
</Extensions>
Ini adalah kontrak UI yang dapat diluncurkan dari kontrak latar belakang Alur Kerja Dukungan Cetak, atau ketika pengguna memilih notifikasi kesalahan pekerjaan cetak. Sewaktu aktivasi, PrintWorkflowJobActivatedEventArgs disediakan, yang memiliki objek PrintWorkflowJobUISession. Menggunakan PrintWorkflowJobUISession, aplikasi foreground harus mendaftar untuk event PdlDataAvailable jika ingin mengakses data PDL. Jika aplikasi latar depan ingin menampilkan pesan kesalahan kustom untuk kesalahan apa pun yang dapat terjadi selama proses, aplikasi tersebut harus mendaftarkan diri untuk event JobNotification. Setelah event terdaftar, aplikasi harus memanggil fungsi PrintWorkflowJobUISession::Start agar sistem cetak mulai mengaktifkan event.
Melewati perenderan sistem
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();
}
}
}
}
Peristiwa modifikasi PDL
Diagram urutan untuk peristiwa modifikasi PDL:
Kode sampel C# untuk Print Support Job Monitor membaca dan menulis konten pekerjaan cetak:
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();
}
}
}
Meluncurkan UI dari latar belakang alur kerja
Kode sampel C# untuk meluncurkan UI Pekerjaan Dukungan Cetak dari kontrak kejadian permintaan modifikasi PSA PDL:
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();
}
}
Aktivasi UI pekerjaan alur kerja untuk peristiwa PDLDataAvailable
Diagram urutan untuk aktivasi UI pekerjaan cetak untuk peristiwa PdlDataAvailable:
Kode sampel C# untuk kontrak aktivasi UI pekerjaan PSA:
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);
}
}
}
}
Dapatkan atribut pekerjaan printer
Kode sampel C# untuk mendapatkan atribut pekerjaan untuk pekerjaan cetak:
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();
}
}
}
Mengatur atribut pekerjaan printer
Kode sampel C#, berlanjut dari bagian Dapatkan atribut pekerjaan printer di atas, menunjukkan cara mengatur atribut pekerjaan:
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);
}
}
Beberapa printer IPP tidak mendukung mengambil/mengatur atribut pekerjaan setelah pekerjaan dibuat. Untuk printer tersebut, PrintJob memiliki properti JobId yang diatur ke "0" dan GetJobAttributes/SetJobAttributes akan segera gagal dengan pengecualian.
Menyediakan akses file penyimpanan ke konten PDL
Beberapa format PDL seperti PDF memerlukan aliran lengkap agar tersedia untuk mulai diproses. Untuk itu, metode baru bernama GetContentFileAsync disediakan pada kelas PrintWorkflowPdlSourceContent yang mengembalikan StorageFile konten sumber.
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);
}
}
}
}
}
Konversi PDL XPS ke PDF
Kode sampel C# memperlihatkan konversi PDL XPS ke 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();
}
Peristiwa pemberitahuan pekerjaan
Diagram urutan untuk peristiwa pemberitahuan pekerjaan:
Kode sampel C#, melanjutkan dari aktivasi UI pekerjaan pada alur kerja untuk PDLDataAvailable bagian acara sebelumnya, untuk menampilkan kesalahan pada notifikasi pekerjaan:
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;
}
}
}
}
Membuat tugas dengan atribut awal tugas
Saat ini, beberapa printer IPP tidak mendukung operasi set-attribute. Fungsi
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
}
}
Pemrosesan XPS berurutan
Kode sampel C++/WinRT untuk memproses XPS secara berurutan sebelum penyelesaian spooling.
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()));
}
}
}
Menampilkan pelokalan nama dan integrasi API Passthrough PDL
Penting
Bagian ini menjelaskan fungsionalitas PSA yang tersedia mulai dari Windows 11, versi 22H2.
Dalam skenario ini, PSA menyesuaikan Kemampuan Perangkat Cetak (PDC) dan menyediakan Sumber Daya Perangkat Cetak (PDR) untuk pelokalan string.
PSA juga mengatur jenis konten API Passthrough PDL yang didukung (format PDL). Jika PSA tidak mengikuti acara atau tidak memanggil SetSupportedPdlPassthroughContentTypes secara eksplisit, PDL Passthrough dinonaktifkan untuk printer yang terhubung dengan aplikasi PSA ini.
// 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);
}
}
Dukungan fitur tingkat halaman dan atribut operasi
Penting
Bagian ini menjelaskan fungsionalitas PSA yang tersedia mulai dari Windows 11, versi 22H2.
Skenario dukungan fitur tingkat halaman dan atribut operasi dikelompokkan karena ditangani dengan membuat perubahan di tempat yang sama dalam kode sampel.
Dukungan fitur tingkat Halaman: Dalam skenario ini, aplikasi PSA menentukan atribut tingkat halaman, yang seharusnya tidak ditimpa oleh atribut IPP yang diurai dari PrintTicket.
Koleksi terpisah untuk dukungan atribut operasi (pencetakan PIN): Dalam skenario ini, aplikasi PSA menentukan atribut operasi IPP kustom (misalnya, PIN).
Kode sampel C# berikut menunjukkan perubahan yang diperlukan untuk dukungan fitur Tingkat Halaman dan koleksi terpisah untuk atribut operasi skenario.
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();
}
}
Meningkatkan dialog cetak dengan menggunakan PSA
Penting
Bagian ini menjelaskan fungsionalitas PSA yang tersedia mulai dari Windows 11, versi 22H2.
Dalam skenario ini, menggunakan dialog cetak dengan integrasi PSA memungkinkan tindakan berikut:
Dapatkan pemberitahuan ketika pilihan diubah dalam MPD ke printer yang dihubungkan dengan PSA
Perlihatkan satu AdaptiveCard dengan dukungan tindakan openUrl
Perlihatkan fitur dan parameter kustom pada dialog cetak
Ubah PrintTicket, sehingga mengubah pilihan untuk opsi fitur yang diperlihatkan dalam dialog cetak
Dapatkan Windows.ApplicationModel.AppInfo dari aplikasi pencetakan untuk membuka dialog pencetakan.
Sampel C# berikut mengilustrasikan penyempurnaan dialog cetak ini:
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""
}}");
}
Konversi PDL dengan bendera pemrosesan berbasis host
Penting
Bagian ini menjelaskan fungsionalitas PSA yang tersedia mulai dari Windows 11, versi 22H2.
API konversi PDL saat ini, PrintWorkflowPdlConverter.ConvertPdlAsync, melakukan pemrosesan berbasis host secara default. Ini berarti bahwa komputer host/pencetakan melakukan rotasi, urutan halaman, dan sebagainya, sehingga printer tidak perlu melakukan operasi ini. Namun, IHV printer mungkin menginginkan konversi PDL tanpa pemrosesan berbasis host karena printer mereka dapat melakukan ini dengan lebih baik. Fungsi ConvertPdlAsync mengambil flag pemrosesan berbasis host untuk memenuhi persyaratan ini. PSA dapat melewati semua pemrosesan berbasis host atau operasi pemrosesan berbasis host tertentu menggunakan bendera ini.
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
}
Mengatur kebijakan pembaruan Kemampuan Perangkat Cetak (PDC)
Penting
Bagian ini menjelaskan fungsionalitas PSA yang tersedia mulai dari Windows 11, versi 22H2.
Produsen Perangkat Keras Independen (IHV) mungkin memiliki persyaratan yang berbeda tentang kapan Kemampuan Perangkat Cetak (PDC) perlu diperbarui. Untuk memenuhi persyaratan ini, PrintSupportPrintDeviceCapabilitiesUpdatePolicy dapat mengatur kebijakan pembaruan untuk PDC. PSA dapat mengatur kebijakan pembaruan PDC berdasarkan waktu atau jumlah pekerjaan cetak menggunakan API ini.
Mengatur kebijakan pembaruan PDC berdasarkan jumlah pekerjaan
// 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);
}
}
Mengatur kebijakan pembaruan PDC berdasarkan 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);
}
}
Panduan desain aplikasi dukungan cetak umum (PSA)
Saat merancang aplikasi dukungan cetak, penting untuk menyertakan aspek-aspek ini dalam desain:
Kontrak latar depan dan latar belakang harus ditandai sebagai mendukung beberapa instans, misalnya, SupportsMultipleInstance harus ada dalam manifes paket. Ini untuk memastikan bahwa masa pakai kontrak dapat dikelola dengan andal untuk beberapa pekerjaan simultan.
Anggap meluncurkan antarmuka pengguna untuk modifikasi PDL sebagai langkah yang opsional. Lakukan upaya terbaik untuk menyelesaikan pekerjaan cetak dengan sukses meskipun peluncuran UI tidak diizinkan. Tugas cetak hanya boleh dibatalkan jika tidak ada cara untuk menyelesaikannya dengan sukses tanpa input pengguna selama modifikasi PDL. Pertimbangkan untuk mengirim PDL yang tidak dimodifikasi dalam kasus seperti itu.
Ketika meluncurkan UI untuk modifikasi PDL, pastikan untuk memanggil IsUILaunchEnabled terlebih dahulu sebelum memanggil LaunchAndCompleteUIAsync. Ini untuk memastikan bahwa skenario yang tidak dapat menampilkan UI pada saat ini terus mencetak dengan benar. Skenario ini dapat berada di perangkat tanpa kepala atau perangkat yang saat ini dalam mode kios atau tidak mengganggu mode.
Artikel terkait
Akhir paket layanan untuk driver printer pihak ketiga pada Windows
spesifikasi Internet Printing Protocol (IPP)
Asosiasi Aplikasi Pendukung Cetak