UWP デバイス アプリで印刷ジョブを管理する方法
Windows 8.1 では、プリンター用の UWP デバイス アプリで印刷ジョブを管理できます。 このトピックでは、C# バージョンの印刷ジョブの管理とプリンター メンテナンスのサンプルを使用して、印刷ジョブのビューを作成し、それらのジョブを監視し、必要に応じてジョブを取り消す方法について説明します。 UWP デバイス アプリ全般の詳細については、「UWP デバイス アプリの概要」を参照してください。
C# バージョンの印刷ジョブの管理とプリンター メンテナンスのサンプルでは、DeviceAppForPrinters2 プロジェクトの DeviceMaintenance.xaml.cs ファイルを使用したプリンター メンテナンスを示します。 Bidi を操作するために、このサンプルでは PrinterExtensionLibrary プロジェクトのプリンター拡張機能ライブラリを使用します。 プリンター拡張機能ライブラリは、v4 印刷ドライバーのプリンター拡張機能インターフェイスにアクセスするための便利な方法を提供します。 詳細については、「プリンター拡張機能ライブラリの概要」を参照してください。
このトピックに示すコード例は、C# バージョンの印刷ジョブの管理とプリンター メンテナンスのサンプルに基づいています。 このサンプルは、JavaScript と C++ でも使用できます。 C++ は COM に直接アクセスできるため、C++ バージョンのサンプルにはコード ライブラリ プロジェクトが含まれていないことにご注意ください。 サンプルをダウンロードして、最新バージョンのコードを確認してください。
印刷ジョブの管理
Windows 8.1 では、印刷ジョブの管理に使用できる v4 プリンター ドライバーに新しいプリンター拡張機能インターフェイス (IPrinterQueue2、IPrinterQueueView、IPrinterQueueViewEvent、IPrintJob、IPrintJobCollection) が導入されています。 これらのインターフェイスにより、印刷ジョブの監視と取り消しが可能になります。 詳細については、「印刷ジョブの管理 (v4 プリンター ドライバー)」を参照してください。
C# アプリと JavaScript アプリでは、COM API を直接操作できません。 C# または JavaScript の UWP デバイス アプリを作成する場合は、(このトピックに示されているように) プリンター拡張機能ライブラリを使用してこれらのインターフェイスにアクセスします。
前提条件
開始する前に、以下の操作を行います。
v4 プリンター ドライバーを使用してプリンターがインストールされていることを確認します。 詳しくは、「v4 プリンター ドライバーの開発」をご覧ください。
開発マシンを設定します。 ツールのダウンロードと開発者アカウントの作成については、「概要」を参照してください。
ストアにアプリを関連付けます。 詳細については、「UWP デバイス アプリを作成する」を参照してください。
プリンターをアプリに関連付けるプリンターのデバイス メタデータを作成します。 詳細については、「デバイス メタデータを作成する」を参照してください。
アプリのメイン ページの UI を構築します。 すべての UWP デバイス アプリは [開始] から起動でき、全画面表示で表示されます。 開始エクスペリエンスを使用すると、デバイスの固有のブランドと機能に一致する方法で製品またはサービスを強調できます。 使用できる UI コントロールの種類に特別な制限はありません。 全画面表示エクスペリエンスの設計を開始するには、Microsoft Store 設計原則を参照してください。
C# または JavaScript を使用してアプリを作成する場合は、PrinterExtensionLibrary プロジェクトを UWP デバイス アプリ ソリューションに追加します。 このプロジェクトは、印刷ジョブの管理とプリンター メンテナンスのサンプルにあります。
C++ は COM に直接アクセスできるため、C++ アプリには、COM ベースのプリンター デバイス コンテキストを操作するための別のライブラリは必要ありません。
手順 1: プリンターを検索する
アプリで印刷ジョブを管理する前に、まず印刷ジョブを持つプリンターを見つける必要があります。 これを行うために、印刷ジョブの管理とプリンター メンテナンスのサンプルには、(PrinterEnumeration
PrinterEnumeration.cs ファイル内に) という名前の便利なクラスが含まれています。 このクラスは、デバイス メタデータを使用してアプリに関連付けられているすべてのプリンターを見つけて、各プリンターの名前とデバイス ID を含む PrinterInfo
オブジェクトの一覧を返します。
この例は、EnumeratePrinters_Click
PrintJobManagement.xaml.cs ファイル内の メソッドを示します。 このサンプルが PrinterEnumeration
クラスを使用して、関連付けられているプリンターの一覧を取得する方法を示します。
private async void EnumeratePrinters_Click(object sender, RoutedEventArgs e)
{
try
{
rootPage.NotifyUser("Enumerating printers. Please wait", NotifyType.StatusMessage);
// Retrieve the running app's package family name, and enumerate associated printers.
string currentPackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;
// Enumerate associated printers.
PrinterEnumeration pe = new PrinterEnumeration(currentPackageFamilyName);
List<PrinterInfo> associatedPrinters = await pe.EnumeratePrintersAsync();
// Update the data binding source on the combo box that displays the list of printers.
PrinterComboBox.ItemsSource = associatedPrinters;
if (associatedPrinters.Count > 0)
{
PrinterComboBox.SelectedIndex = 0;
rootPage.NotifyUser(associatedPrinters.Count + " printers enumerated", NotifyType.StatusMessage);
}
else
{
rootPage.NotifyUser(DisplayStrings.NoPrintersEnumerated, NotifyType.ErrorMessage);
}
}
catch (Exception exception)
{
rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
}
}
PrinterEnumeration
クラスと PrinterInfo
クラスの詳細については、PrinterEnumeration.cs ファイルを参照してください。
手順 2: プリンター キューを取得する
管理する印刷ジョブを持つプリンターを特定したら、 インターフェイス (PrinterExtensionLibraryIPrinterQueueView
プロジェクトの PrinterExtensionTypes.cs ファイルで定義) に基づくオブジェクトを使用して、印刷ジョブのビューを作成します。 印刷ジョブの管理とプリンター メンテナンスのサンプルでは、このオブジェクトは currentPrinterQueueView
という名前が付けられ、プリンターの選択が変更されるたびに再作成されます。
Printer_SelectionChanged
メソッドでは、サンプルは最初に PrinterInfo
オブジェクトを使用して、context
という名前のプリンター拡張機能コンテキスト オブジェクトを作成します。 次に、GetPrinterQueueView
で context
メソッドを使用して currentPrinterQueueView
オブジェクトを作成します。 最後に、currentPrinterQueueView
の OnChanged
イベントを処理するイベント ハンドラーが追加されます。
この例は、Printer_SelectionChanged
PrintJobManagement.xaml.cs ファイル内の メソッドを示します。 これは、IPrinterQueueView
に基づいてプリンター キュー ビュー オブジェクトを作成する方法を示します。
private void Printer_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
// Remove the current printer queue view (if any) before displaying the new view.
if (currentPrinterQueueView != null)
{
currentPrinterQueueView.OnChanged -= OnPrinterQueueViewChanged;
currentPrinterQueueView = null;
}
// Retrieve a COM IPrinterExtensionContext object, using the static WinRT factory.
// Then instantiate one "PrinterExtensionContext" object that allows operations on the COM object.
PrinterInfo queue = (PrinterInfo)PrinterComboBox.SelectedItem;
Object comContext = Windows.Devices.Printers.Extensions.PrintExtensionContext.FromDeviceId(queue.DeviceId);
PrinterExtensionContext context = new PrinterExtensionContext(comContext);
// Display the printer queue view.
const int FirstPrintJobEnumerated = 0;
const int LastPrintJobEnumerated = 10;
currentPrinterQueueView = context.Queue.GetPrinterQueueView(FirstPrintJobEnumerated, LastPrintJobEnumerated);
currentPrinterQueueView.OnChanged += OnPrinterQueueViewChanged;
}
catch (Exception exception)
{
rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
}
}
また、印刷ジョブのビューが変更されるたびに、イベント ハンドラーは OnPrinterQueueViewChanged
メソッドを呼び出します。 このメソッドにより、PrintJobListBox
は IPrintJob
オブジェクトの IEnumerable コレクションに再バインドされます。 コレクションは、PrinterQueueViewEventArgs
PrinterExtensionTypes.cs ファイルで定義されている オブジェクトを介してメソッドに渡されます。
この例は、OnPrinterQueueViewChanged
PrintJobManagement.xaml.cs ファイル内の メソッドを示します。
private async void OnPrinterQueueViewChanged(object sender, PrinterQueueViewEventArgs e)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
// Update the data binding on the ListBox that displays print jobs.
PrintJobListBox.ItemsSource = e.Collection;
if (PrintJobListBox.Items.Count > 0)
{
// If there are print jobs in the current view, mark the first job as selected.
PrintJobListBox.SelectedIndex = 0;
}
});
}
手順 3: 印刷ジョブの状態を表示する
PrintJobListBox
は IPrintJob
オブジェクトのコレクションにバインドされているため、ジョブの状態の表示はかなり簡単です。 選択した印刷ジョブが IPrintJob
オブジェクトとしてキャストされ、そのオブジェクトのプロパティを使用して PrintJobDetails
TextBox を埋めます。
印刷ジョブの管理とプリンター メンテナンスのサンプルでは、異なる印刷ジョブが選択されるたびに印刷ジョブの状態が表示されます。 この更新は、PrintJob_SelectionChanged
メソッドで管理されます。
この例は、PrintJob_SelectionChanged
PrintJobManagement.xaml.cs ファイル内の メソッドを示します。 IPrintJob
オブジェクトに基づいて印刷ジョブの状態を表示する方法を示します。
private void PrintJob_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
// Display details of the selected print job.
IPrintJob job = (IPrintJob)PrintJobListBox.SelectedItem;
if (job != null)
{
PrintJobDetails.Text =
"Details of print job: " + job.Name + "\r\n" +
"Pages printed: " + job.PrintedPages + "/" + job.TotalPages + "\r\n" +
"Submission time: " + job.SubmissionTime + "\r\n" +
"Job status: " + DisplayablePrintJobStatus.ToString(job.Status);
}
else
{
PrintJobDetails.Text = "Please select a print job";
}
}
catch (Exception exception)
{
rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
}
}
印刷ジョブの状態の説明を表示するために、PrintJob_SelectionChanged
メソッドでは、printJobStatusDisplayNames
という名前の付いた静的ディクショナリを使用して、わかりやすいテキスト形式でジョブの状態の説明を表示できるようにします。
この例は、DisplayablePrintJobStatus
PrintJobManagement.xaml.cs ファイル内の クラスを示します。 このクラスには、PrintJob_SelectionChanged
で使用される静的メンバーが含まれています。
internal class DisplayablePrintJobStatus
{
/// <summary>
/// Converts the PrintJobStatus bit fields to a display string.
/// </summary>
internal static string ToString(PrintJobStatus printJobStatus)
{
StringBuilder statusString = new StringBuilder();
// Iterate through each of the PrintJobStatus bits that are set and convert it to a display string.
foreach (var printJobStatusDisplayName in printJobStatusDisplayNames)
{
if ((printJobStatusDisplayName.Key & printJobStatus) != 0)
{
statusString.Append(printJobStatusDisplayName.Value);
}
}
int stringlen = statusString.Length;
if (stringlen > 0)
{
// Trim the trailing comma from the string.
return statusString.ToString(0, stringlen - 1);
}
else
{
// If no print job status field was set, display "Not available".
return "Not available";
}
}
/// <summary>
/// Static constructor that initializes the display name for the PrintJobStatus field.
/// </summary>
static DisplayablePrintJobStatus()
{
printJobStatusDisplayNames = new Dictionary<PrintJobStatus, string>();
printJobStatusDisplayNames.Add(PrintJobStatus.Paused, "Paused,");
printJobStatusDisplayNames.Add(PrintJobStatus.Error, "Error,");
printJobStatusDisplayNames.Add(PrintJobStatus.Deleting, "Deleting,");
printJobStatusDisplayNames.Add(PrintJobStatus.Spooling, "Spooling,");
printJobStatusDisplayNames.Add(PrintJobStatus.Printing, "Printing,");
printJobStatusDisplayNames.Add(PrintJobStatus.Offline, "Offline,");
printJobStatusDisplayNames.Add(PrintJobStatus.PaperOut, "Out of paper,");
printJobStatusDisplayNames.Add(PrintJobStatus.Printed, "Printed,");
printJobStatusDisplayNames.Add(PrintJobStatus.Deleted, "Deleted,");
printJobStatusDisplayNames.Add(PrintJobStatus.BlockedDeviceQueue, "Blocked device queue,");
printJobStatusDisplayNames.Add(PrintJobStatus.UserIntervention, "User intervention required,");
printJobStatusDisplayNames.Add(PrintJobStatus.Restarted, "Restarted,");
printJobStatusDisplayNames.Add(PrintJobStatus.Complete, "Complete,");
printJobStatusDisplayNames.Add(PrintJobStatus.Retained, "Retained,");
}
/// <summary>
/// Private constructor to prevent default instantiation.
/// </summary>
private DisplayablePrintJobStatus() { }
/// <summary>
/// Contains the mapping between PrintJobStatus fields and display strings.
/// </summary>
private static Dictionary<PrintJobStatus, string> printJobStatusDisplayNames;
}
手順 4: 印刷ジョブを取り消す
印刷ジョブの状態を表示する場合と同様、IPrintJob
オブジェクトがある場合は印刷ジョブの取り消しがかなり簡単です。 IPrintJob
クラスでは、対応する印刷ジョブの取り消しを開始する RequestCancel
メソッドが使えます。 これは、サンプルの CancelPrintJob_Click
メソッドに示されています。
この例は、CancelPrintJob_Click
PrintJobManagement.xaml.cs ファイル内の メソッドを示します。
private void CancelPrintJob_Click(object sender, RoutedEventArgs e)
{
try
{
IPrintJob job = (IPrintJob)PrintJobListBox.SelectedItem;
job.RequestCancel();
}
catch (Exception exception)
{
rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
}
}
テスト
UWP デバイス アプリはテストする前に、デバイス メタデータを使用してプリンターにリンクする必要があります。
デバイス アプリ情報をプリンターに追加するには、プリンターのデバイス メタデータ パッケージのコピーが必要です。 デバイス メタデータがない場合は、「UWP デバイス アプリのデバイス メタデータを作成する」トピックの説明に従い、デバイス メタデータ作成ウィザードを使用して作成できます。
デバイス メタデータ作成ウィザードを使用するには、このトピックの手順を完了する前に、Microsoft Visual Studio Professional、Microsoft Visual Studio Ultimate、またはスタンドアロン SDK for Windows 8.1 をインストールする必要があります。 Microsoft Visual Studio Express for Windows をインストールすると、ウィザードを含まないバージョンの SDK がインストールされます。
次の手順に沿ってアプリを作成し、デバイス メタデータをインストールします。
テスト署名を有効にします。
DeviceMetadataWizard.exe をダブルクリックして、%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 からデバイス メタデータ作成ウィザードを開始します。
[ツール] メニューの [テスト署名を有効にする] を選択します。
コンピューターを再起動します
ソリューション (.sln) ファイルを開いてソリューションを構築します。 サンプルが読み込まれた後、F7 キーを押すか、上部のメニューから [Build] -> [ソリューションの構築] に移動します。
プリンターを切断してアンインストールします。 この手順は、次回デバイスが検出されたときに Windows が更新されたデバイス メタデータを読み取るために必要です。
デバイス メタデータを編集して保存します。 デバイス アプリをデバイスにリンクするには、デバイス アプリをデバイスに関連付ける必要があります。
デバイス メタデータをまだ作成していない場合は、「UWP デバイス アプリのデバイス メタデータを作成する」を参照してください。
デバイス メタデータ作成ウィザードをまだ開いていない場合は、DeviceMetadataWizard.exe をダブルクリックして、%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 からウィザードを開始します。
[デバイス メタデータの編集] をクリックします。 これにより、既存のデバイス メタデータ パッケージを編集できます。
[開く] ダイアログ ボックスで、UWP デバイス アプリに関連付けられているデバイス メタデータ パッケージを見つけます。 (devicemetadata-ms ファイル拡張子が付いています)
[UWP デバイス アプリ情報の指定] ページで、[UWP デバイス アプリ] ボックスに Microsoft Store アプリ情報を入力します。 [UWP アプリ マニフェスト ファイルのインポート] をクリックすると、[パッケージ名]、[発行元名]、[UWP アプリ ID] が自動的に入力されます。
アプリでプリンター通知を登録する場合は、[通知ハンドラー] ボックスを入力します。 [イベント ID] に、印刷イベント ハンドラーの名前を入力します。 [イベント アセット] に、そのコードが駐在するファイルの名前を入力します。
完了したら、[完了] ページが表示されるまで [次へ] をクリックします。
[デバイス メタデータ パッケージの確認] ページで、すべての設定が正しいことを確認し、[ローカル コンピューターのメタデータ ストアにデバイス メタデータ パッケージをコピーする] チェック ボックスを選択します。 [保存] をクリックします。
デバイスが接続されている場合は、プリンターを再接続して、Windows が更新されたデバイス メタデータを読み取れるようにします。