印刷設定をカスタマイズする方法 (UWPデバイス アプリ)

Windows 8.1 では、UWP デバイス アプリを使用すると、プリンターの製造元は印刷の詳細設定を表示するポップアップをカスタマイズできます。 このトピックでは、印刷の詳細設定ポップアップについて説明し、C# バージョンの印刷設定と印刷通知のサンプルで、既定のポップアップをカスタム ポップアップに置き換える方法について説明します。 UWP デバイス アプリ全般の詳細については、「UWP デバイス アプリの概要」を参照してください。

C# バージョンの印刷設定と印刷通知のサンプルでは、Preferences.xaml ページを使用して、印刷の詳細設定用のカスタム ポップアップの UI を示します。 印刷ヘルパー クラスを使用して、デバイス コンテキスト (IPrinterExtensionContext) を作成し、デバイス クエリを実行します。 PrinterHelperClass.cs ファイルは DeviceAppForPrintersLibrary プロジェクト内にあり、PrinterExtensionLibrary プロジェクトで定義されている API を使用します。 プリンター拡張機能ライブラリは、v4 印刷ドライバーのプリンター拡張機能インターフェイスにアクセスするための便利な方法を提供します。 詳細については、「プリンター拡張機能ライブラリの概要」を参照してください。

Note

このトピックに示すコード例は、C# バージョンの印刷設定と印刷通知のサンプルに基づいています。 このサンプルは、JavaScript と C++ でも使用できます。 C++ は COM に直接アクセスできるため、C++ バージョンのサンプルにはコード ライブラリ プロジェクトが含まれていないことにご注意ください。 サンプルをダウンロードして、最新バージョンのコードを確認してください。

印刷の詳細設定

印刷の詳細設定エクスペリエンスは、ユーザーが [印刷] ウィンドウで提供されていない印刷設定を選択する場合にプリンターで利用できる機能です。 [印刷] ウィンドウの [その他の設定] からアクセスできます。 全画面表示エクスペリエンスではありませんが、ポップアップ内に表示されます。このポップアップは、軽量でコンテキストに沿ったユーザー インターフェースを表示するためのコントロールで、ユーザーがその外側をクリックまたはタップすると非表示になります。

このエクスペリエンスを使用すると、文書ページに透かしを適用する機能、安全な印刷オプションや画像の強化オプションを提供する機能など、プリンターの差別化された機能を強調できます。

プリンターに UWP デバイス アプリがインストールされていない場合、Windows では既定の印刷設定エクスペリエンスが提供されます。 UWP デバイス アプリがプリンター用にインストールされていることと、そのアプリが windows.printTaskSettings 拡張機能にオプトインされていることを Windows が検出すると、アプリは Windows で提供される既定のエクスペリエンスに取って代わります。

印刷の詳細設定のポップアップを呼び出すには:

  1. 印刷をサポートする UWP アプリを開きます

  2. 画面の右側でスワイプして (または Windows ロゴ キー + C を使用して) チャームにアクセスします

  3. [デバイス] チャームをタップします

  4. [印刷] をタップします

  5. [プリンター] をタップします

  6. [印刷] ウィンドウが開きます

  7. [印刷] ウィンドウの [その他の設定] をクリックします

  8. 印刷の詳細設定のポップアップが開きます

    • 既定のポップアップは、プリンター用の UWP デバイス アプリがインストールされていない場合に表示されます

    • プリンター用の UWP デバイス アプリがインストールされていると、カスタム ポップアップが表示されます

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

前提条件

開始する前に、以下の操作を行います。

  1. v4 プリンター ドライバーを使用してプリンターがインストールされていることを確認します。 詳しくは、「v4 プリンター ドライバーの開発」をご覧ください。

  2. 開発マシンを設定します。 ツールのダウンロードと開発者アカウントの作成については、「概要」を参照してください。

  3. ストアにアプリを関連付けます。 詳細については、「UWP デバイス アプリを作成する」を参照してください。

  4. プリンターをアプリに関連付けるプリンターのデバイス メタデータを作成します。 詳細については、「デバイス メタデータを作成する」を参照してください。

  5. アプリのメイン ページの UI を構築します。 すべての UWP デバイス アプリは [開始] から起動でき、全画面表示で表示されます。 開始エクスペリエンスを使用すると、デバイスの固有のブランドと機能に一致する方法で製品またはサービスを強調できます。 使用できる UI コントロールの種類に特別な制限はありません。 全画面表示エクスペリエンスの設計を開始するには、Microsoft Store 設計原則を参照してください。

  6. C# または JavaScript を使用してアプリを作成する場合は、PrinterExtensionLibrary プロジェクトと DeviceAppForPrintersLibrary プロジェクトを UWP デバイス アプリ ソリューションに追加します。 これらの各プロジェクトは、印刷設定と印刷通知のサンプルで確認できます。

Note

C++ は COM に直接アクセスできるため、C++ アプリには、COM ベースのプリンター デバイス コンテキストを操作するための別のライブラリは必要ありません。

手順 1: 拡張機能を登録する

Windows に、アプリが印刷の詳細設定用のカスタム ポップアップを提供できることを認識させるには、印刷タスク設定拡張機能を登録する必要があります。 この拡張機能は Extension 要素内で宣言され、Category 属性は windows.printTaskSettings の値に設定されます。 C# と C++ のサンプルでは、Executable 属性は $targetnametoken$.exe に設定され、EntryPoint 属性は DeviceAppForPrinters.App に設定されます。

印刷タスク設定拡張機能は、Microsoft Visual Studio のマニフェスト デザイナーの [宣言] タブに追加できます。 XML (テキスト) エディターを使用して、アプリ パッケージ マニフェストの XML を手動で編集することもできます。 オプションを編集するには、ソリューション エクスプローラーで、Package.appxmanifest ファイルを右クリックします。

この例は、アプリ パッケージ マニフェスト ファイル ExtensionPackage.appxmanifest に表示される、 要素内の印刷タスク設定拡張機能を示します。

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
  <Identity Name="Microsoft.SDKSamples.DeviceAppForPrinters.CS" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="1.0.0.0" />
  <Properties>
    <DisplayName>Device App For Printers C# sample</DisplayName>
    <PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
    <Logo>Assets\storeLogo-sdk.png</Logo>
  </Properties>
  <Prerequisites>
    <OSMinVersion>6.3.0</OSMinVersion>
    <OSMaxVersionTested>6.3.0</OSMaxVersionTested>
  </Prerequisites>
  <Resources>
    <Resource Language="x-generate" />
  </Resources>
  <Applications>
    <Application Id="DeviceAppForPrinters" Executable="$targetnametoken$.exe" EntryPoint="DeviceAppForPrinters.App">
      <VisualElements DisplayName="Device App For Printers C# sample" Logo="Assets\squareTile-sdk.png" SmallLogo="Assets\smallTile-sdk.png" Description="DeviceAppForPrinters C# sample" ForegroundText="light" BackgroundColor="#00b2f0" ToastCapable="true">
<DefaultTile ShowName="allLogos" ShortName="App4PrinterCS" WideLogo="Assets\tile-sdk.png" />
<SplashScreen Image="Assets\splash-sdk.png" BackgroundColor="#00b2f0" />
      </VisualElements>
      <Extensions>
<Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTask.PrintBackgroundTask">
  <BackgroundTasks>
    <Task Type="systemEvent" />
  </BackgroundTasks>
</Extension>
<Extension Category="windows.printTaskSettings" Executable="$targetnametoken$.exe" EntryPoint="DeviceAppForPrinters.App" />
      </Extensions>
    </Application>
  </Applications>
</Package>

手順 2: UI を構築する

アプリを作成する前に、デザイナーとマーケティング チームと協力してユーザー エクスペリエンスを設計する必要があります。 ユーザー エクスペリエンスは、会社のブランドの側面を投影し、ユーザーとのつながりを構築するのに役立つものにする必要があります。

デザインのガイドライン

カスタム ポップアップを設計する前に、UWP アプリのポップアップ ガイドラインを確認することが重要です。 このガイドラインは、他の UWP アプリと一貫性のある直感的なエクスペリエンスをポップアップで提供できるようにするのに役立ちます。

アプリのメイン ページについては、Windows 8.1 で複数のアプリをさまざまなサイズで 1 つのモニターに表示できることを念頭に置いてください。 画面サイズ、ウィンドウ サイズ、向きの間でアプリをスムーズにリフローする方法の詳細については、次のガイドラインを参照してください。

ポップアップのディメンション

詳細な印刷設定を表示するポップアップは、幅 646 ピクセル、高さ 768 ピクセル以上です (実際の高さは、ユーザーの画面の解像度によって異なります)。 ポップアップのタイトル領域の [戻る] ボタンは、Windows によって提供されます。 "アプリ タイトル" テキストは、アプリ マニフェストのアプリ タイトルです。 タイトル領域の高さは 80 ピクセルで、カスタム ポップアップの表示可能領域は 688 ピクセルになります。

flyout dimensions for advanced printer settings.

Note

カスタム ポップアップの高さが 688 ピクセルを超える場合、ユーザーはスライドまたはスクロールすると、表示可能領域の上または下にあるポップアップの部分を表示できます。

アプリ タイトルの色とアイコンの定義

カスタム ポップアップのタイトル、背景色、テキストの色、小さなロゴは、アプリ パッケージ マニフェスト ファイルの VisualElements 要素から取得されます。

この例は、アプリ パッケージ マニフェスト ファイル (VisualElementsPackage.appxmanifest) に、 要素で定義されているタイトルとアイコンを示します。

      <VisualElements DisplayName="Device App For Printers C# sample" Logo="Assets\squareTile-sdk.png" SmallLogo="Assets\smallTile-sdk.png" Description="DeviceAppForPrinters C# sample" ForegroundText="light" BackgroundColor="#00b2f0" ToastCapable="true">
        <DefaultTile ShowName="allLogos" ShortName="App4PrinterCS" WideLogo="Assets\tile-sdk.png" />
        <SplashScreen Image="Assets\splash-sdk.png" BackgroundColor="#00b2f0" />
      </VisualElements>

ベスト プラクティス

  • 同じ外観を保ちます。 フォント、色、コントロールなどの要素を含め、カスタム ポップアップを開始エクスペリエンス (アプリのメイン ページ) のデザインに合わせます。 アプリは、どこから呼び出すかに関係なく、ユーザーになじみのあるものにする必要があります。

  • 操作をシンプルに保ちます。 時間のかかる操作や複雑な操作を避けます。 ほとんどの場合、プリンターのセットアップ、状態の表示、インクの注文、トラブルシューティングなどのアクションは、開始エクスペリエンス内で行うのが最適です。

  • ナビゲーションを最小限に抑えます。 ユーザーがカスタム ポップアップ内の複数のページを行ったり来たりしないようにします。 代わりに、情報漏洩のプログレッシブ コントロール、ドロップダウン、インライン エラー メッセージなど、垂直スクロールまたはインライン コントロールを使用します。

  • 簡易非表示ポップアップは使用しないでください。 印刷エクスペリエンスでは、簡易非表示ポップアップが既に使用されています。 カスタム ポップアップに別の簡易非表示要素を含めると、ユーザーが混乱する可能性があります。

  • ユーザーを印刷エクスペリエンスから遠ざけるリンクを無効にします。 ユーザーがコンテンツを印刷しているときは、印刷コンテキスト内にとどまるようにするための対策を講じる必要があります。 たとえば、アプリの他の領域 (ホーム ページやインクの購入ページなど) につながるリンクがアプリにある場合は、ユーザーが印刷の詳細設定エクスペリエンスを誤って終了しないように、そうしたリンクを無効にする必要があります。

手順 3: アクティブ化を処理する

アプリで印刷タスク設定拡張機能を宣言している場合は、OnActivated メソッドを実装してアプリのアクティブ化イベントを処理する必要があります。 アプリのアクティブ化では、アプリの起動時にどのページを起動するかをアプリが選択できます。 印刷タスク設定拡張機能を宣言したアプリの場合、Windows は、アクティブ化されたイベント引数 Windows.ApplicationModel.Activation.IActivatedEventArgs で印刷タスク拡張機能コンテキストを渡します。

UWP デバイス アプリは、イベント引数の プロパティが Windows.ApplicationModel.Activation.ActivationKind.printTaskSettings と等しい場合に、アクティブ化が (誰かが [印刷設定] ダイアログで [その他のオプション]kind をタップしただけの) 印刷の詳細設定を対象としていることを確認できます。

Note

場合によっては、起動直後にユーザーがアプリを閉じると、アクティブ化ハンドラー内で例外がスローされることがあります。 これを回避するには、アクティブ化ハンドラーが効率的に完了し、リソースを大量消費する処理を行わないようにしてください。

この例は、OnActivatedConstants.cs ファイルに表示される、 メソッド内のアクティブ化イベント ハンドラーを示します。 その後、イベント引数は、Windows.ApplicationModel.Activation.PrintTaskSettingsActivatedEventArgs としてキャストされます。 サンプルでは、このコードが Constants.cs ファイルに含まれていますが、実際には、App.xaml.cs ファイルでも定義されている App クラスの一部です。

partial class App : Application
{
    protected override void OnActivated(IActivatedEventArgs args)
    {
        if (args.Kind == ActivationKind.PrintTaskSettings)
        {
            Frame rootFrame = new Frame();
            if (null == Window.Current.Content)
            {
                rootFrame.Navigate(typeof(MainPage));
                Window.Current.Content = rootFrame;
            }
            Window.Current.Activate();

            MainPage mainPage = (MainPage)rootFrame.Content;

            // Load advanced printer preferences scenario
            mainPage.LoadAdvancedPrintSettingsContext((PrintTaskSettingsActivatedEventArgs)args);
        }
    }
}

手順 4: 設定を表示する

LoadAdvancedPrintSettingsContext メソッドが呼び出されると、印刷タスク構成コンテキストが MainPage クラスの変数に割り当てられます。 これにより、カスタム ポップアップは起動時に印刷設定にアクセスできるようになります。

LoadAdvancedPrintSettingsContext メソッドに渡されるイベント引数は、プリンターをアクセスして制御するためのプロパティを公開します。

  • args.configuration プロパティは、Windows.Devices.Printers.Extensions.PrintTaskConfiguration 型のオブジェクトを提供します。 このオブジェクトは、印刷タスク拡張機能コンテキストへのアクセスを提供し、印刷チケットを更新するイベント ハンドラーを追加することもできます。
  • args.configuration.printerExtensionContext プロパティは、Windows.Devices.Printers.Extensions.PrinterExtensionContext 型のオブジェクトを提供します。 このオブジェクトは、印刷スキーマ、PrintTicket、および印刷キュー情報の PrinterExtensionLibrary インターフェイスへのポインターです。 インターフェイスが公開されていない場合は null になります。 詳細については、「プリンター拡張機能ライブラリの概要」を参照してください。

この例は、LoadAdvancedPrintSettingsContextConstants.cs ファイルに表示される メソッドを示します。

public PrintTaskConfiguration Config;
public Object Context;

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

カスタム ポップアップ ページの Preferences.xaml.cs では、rootPage という名前のクラスが MainPage クラスへのポインターとして機能し、印刷タスク拡張コンテキストとプリンター デバイス コンテキストにポップアップからアクセスできるようにしています。

この例は、PreferencesPreferences.xaml.cs ファイルから、 クラスの部分のポインターを示します。 完全なコードを表示するには、印刷設定と印刷通知のサンプルをダウンロードします。

public sealed partial class Preferences : SDKTemplate.Common.LayoutAwarePage
{
    // A pointer back to the main page.  
    MainPage rootPage = MainPage.Current;

    // To listen for save requests.
    PrintTaskConfiguration configuration;

    // To create the printer device context.
    Object printerExtensionContext;
    PrintHelperClass printHelper;

    // The features in this sample were chosen because they're available on a wide range of printer drivers.
    private string[] features = { "PageOrientation", "PageOutputColor", "PageMediaSize", "PageMediaType" };
    private string[] selections = { null, null, null, null };

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

Preferences.xaml.cs のページ コンストラクターが呼び出されると、印刷タスク拡張コンテキスト用のオブジェクト (PrintTaskConfiguration という名前の configuration オブジェクト) とプリンター デバイス コンテキスト用のオブジェクト (PrintHelperClass という名前の printHelper オブジェクト) が作成されます。

これらのオブジェクトが作成されると、TextBlock と ComboBox を読み込むために、DisplaySettings メソッドでプリンター デバイス コンテキストが使用されます。 JavaScript とは異なり、選択の変更はアプリの残りの部分と同じスレッドでは発生しないことにご注意ください。 後で使用できるように、ユーザー選択のローカル キャッシュを維持する必要があります。

この例は、DisplaySettingsPreferences.xaml.cs ファイル内のカスタム ポップアップ ページ コンストラクターの と、その他のヘルパー メソッドを示します。

public Preferences()
{
    this.InitializeComponent();

    configuration = rootPage.Config;
    printerExtensionContext = rootPage.Context;
    printHelper = new PrintHelperClass(printerExtensionContext);

    // Disable scenario navigation by hiding the scenario list UI elements
    ((UIElement)rootPage.FindName("Scenarios")).Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    ((UIElement)rootPage.FindName("ScenarioListLabel")).Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    ((UIElement)rootPage.FindName("DescriptionText")).Visibility = Windows.UI.Xaml.Visibility.Collapsed;

    DisplaySettings();
}


private void DisplaySettings(bool constraints=false)
{
    PrintOptions.Visibility = Windows.UI.Xaml.Visibility.Visible;
    WaitPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;

    // Fill in the drop-down select controls for some common printing features.
    TextBlock[] featureLabels = { PageOrientationLabel, PageOutputColorLabel, PageMediaSizeLabel, PageMediaTypeLabel };
    ComboBox[] featureBoxes = { PageOrientationBox, PageOutputColorBox, PageMediaSizeBox, PageMediaTypeBox };

    for (int i = 0; i < features.Length; i++)
    {
        // Only display a feature if it exists
        featureLabels[i].Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        featureBoxes[i].Visibility = Windows.UI.Xaml.Visibility.Collapsed;

        string feature = features[i];

        // Check whether the currently selected printer's capabilities include this feature.
        if (!printHelper.FeatureExists(feature))
        {
            continue;
        }

        // Fill in the labels so that they display the display name of each feature.
        featureLabels[i].Text = printHelper.GetFeatureDisplayName(feature);
        string[] index = printHelper.GetOptionInfo(feature, "Index");
        string[] displayName = printHelper.GetOptionInfo(feature, "DisplayName");
        string selectedOption = printHelper.GetSelectedOptionIndex(feature);

        // Unless specified, do not get constraints
        bool[] constrainedList = constraints ? printHelper.GetOptionConstraints(feature) : new bool[index.Length];

        // Populate the combo box with the options for the current feature.
        PopulateBox(featureBoxes[i], index, displayName, selectedOption, constrainedList);
        selections[i] = selectedOption;

        // Every time the selection for a feature changes, we update our local cached set of selections.
        featureBoxes[i].SelectionChanged += OnFeatureOptionsChanged;

        // Show existing features
        featureLabels[i].Visibility = Windows.UI.Xaml.Visibility.Visible;
        featureBoxes[i].Visibility = Windows.UI.Xaml.Visibility.Visible;
    }
}

void PopulateBox(ComboBox box, string[] index, string[] displayName, string selectedOption, bool[] constrainedList)
{
    // Clear the combobox of any options from previous UI refresh before repopulating it.
    box.SelectionChanged -= OnFeatureOptionsChanged;
    box.Items.Clear();
    // There should be only one displayName for each possible option.
    if (index.Length == displayName.Length)
    {
        for (int i = 0; i < index.Length; i++)
        {
            // Create a new DisplayItem so the user will see the friendly displayName instead of the index.
            ComboBoxItem newItem = new ComboBoxItem();
            newItem.Content = displayName[i];
            newItem.DataContext = index[i];
            newItem.Foreground = constrainedList[i] ? new SolidColorBrush(Colors.Red) : new SolidColorBrush(Colors.Black);
            box.Items.Add(newItem);

            // Display current selected option as selected in the combo box.
            if (selectedOption == index[i])
            {
                box.SelectedIndex = i;
                box.Foreground = newItem.Foreground;
            }
        }
    }
}

private void OnFeatureOptionsChanged(object sender, SelectionChangedEventArgs args)
{
    ComboBox comboBox = sender as ComboBox;

    for (int i = 0; i < features.Length; i++)
    {
        if (features[i] + "Box" == comboBox.Name)
        {
            selections[i] = (comboBox.SelectedItem as ComboBoxItem).DataContext as string;
        }
    }
}

手順 5: 設定を保存する

ユーザーが印刷の詳細設定の設定を終えたら、ユーザーが [印刷] ウィンドウに戻る前に、Microsoft Store デバイス アプリで変更を保存する必要があります。 そのためには、ユーザーが (カスタム ポップアップ ページから) [戻る] ボタンをタップしたときに、アプリはリッスンする必要があります。 その際、印刷タスク拡張コンテキスト (SaveRequested オブジェクト) の configuration イベントがトリガーされます。

この例は、SaveRequestedPreferences.xaml.csOnNavigatedTo ファイル内にあり、カスタム ポップアップの イベント ハンドラーに追加される、 のイベント リスナーを示します。 SaveRequested イベントがトリガーされると、OnSaveRequested メソッドが呼び出されます (そのメソッドは Preferences.xaml.cs ファイル内にあります)。

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (null == configuration)
    {
        rootPage.NotifyUser("Configuration arguments cannot be null", NotifyType.ErrorMessage);
        return;
    }

    // Add an event listener for saverequested (the back button of the flyout is pressed).
    configuration.SaveRequested += OnSaveRequested;
}

OnSaveRequested メソッドでは、アプリは最初に printHelper オブジェクトを使用して、プリンター拡張機能コンテキストの各機能に対して現在選択されているオプションを設定します。 次に、Save メソッドに引数として渡される request オブジェクトの OnSaveRequested メソッドを呼び出します。 Windows.Devices.Printers.Extensions.PrintTaskConfigurationSaveRequest クラスの Save メソッドは、プリンター拡張コンテキストを使用して印刷チケットを検証し、印刷タスクの構成を保存します。

重要

印刷チケットが何らかの形で無効な場合、Save メソッドはアプリで処理する必要がある例外をスローします。 アプリが例外を処理しない場合、フローは停止され、ユーザーはポップアップを簡易非表示にして、その印刷フローを再起動する必要があります。

この例は、OnSaveRequestedPreferences.xaml.cs ファイル内の メソッドを示します。 SaveRequested イベントは UI スレッドで発生しないため、Windows.UI.Core.CoreDispatcher を使用して UI スレッドにメッセージを投稿し、チケットの検証中と保存中に適切なメッセージを表示する必要があります。

async private void OnSaveRequested(object sender, PrintTaskConfigurationSaveRequestedEventArgs args)
{
    if (null == printHelper || null == printerExtensionContext || null == args)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser("onSaveRequested: args, printHelper, and context cannot be null", NotifyType.ErrorMessage);
        });
        return;
    }

    // Get the request object, which has the save method that allows saving updated print settings.
    PrintTaskConfigurationSaveRequest request = args.Request;

    if (null == request)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser("onSaveRequested: request cannot be null", NotifyType.ErrorMessage);
        });
        return;
    }

    PrintTaskConfigurationSaveRequestedDeferral deferral = request.GetDeferral();

    // Two separate messages are dispatched to:
    // 1) put up a popup panel,
    // 2) set the each options to the print ticket and attempt to save it,
    // 3) tear down the popup panel if the print ticket could not be saved.
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        PrintOptions.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        WaitPanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
    });

    // Go through all the feature select elements, look up the selected
    // option name, and update the context
    // for each feature
    for (var i = 0; i < features.Length; i++)
    {
        // Set the feature's selected option in the context's print ticket.
        // The printerExtensionContext object is updated with each iteration of this loop
        printHelper.SetFeatureOption(features[i], selections[i]);
    }

    bool ticketSaved;
    try
    {
        // This save request will throw an exception if ticket validation fails.
        // When the exception is thrown, the app flyout will remain.
        // If you want the flyout to remain regardless of outcome, you can call
        // request.Cancel(). This should be used sparingly, however, as it could
        // disrupt the entire the print flow and will force the user to
        // light dismiss to restart the entire experience.
        request.Save(printerExtensionContext);

        if (configuration != null)
        {
            configuration.SaveRequested -= OnSaveRequested;
        }
        ticketSaved = true;
    }
    catch (Exception exp)
    {
        // Check if the HResult from the exception is from an invalid ticket, otherwise rethrow the exception
        if (exp.HResult.Equals(unchecked((int)0x8007000D))) // E_INVALID_DATA
        {
            ticketSaved = false;
        }
        else
        {
            throw;
        }
    }

    // If ticket isn't saved, refresh UI and notify user
    if (!ticketSaved)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser("Failed to save the print ticket", NotifyType.ErrorMessage);
            DisplaySettings(true);
        });
    }
    deferral.Complete();
}

ユーザーによる入力を必要とするオプションの保存

印刷設定と印刷通知のサンプルは、ほとんどの印刷オプションをカバーする、定義された機能の設定方法を示します。 ただし、一部のオプションでは、ユーザー指定の値を取得するにはカスタム UI が必要です。 たとえば、アプリで印刷の詳細設定を使用してカスタム ページ サイズを指定した場合、ユーザー指定の値を保存するには、次の手順を実行します。

  1. アプリのアクティブ化の間に印刷チケットを取得します。 印刷設定のアプリのアクティブ化については、「手順 3: アクティブ化を処理する」で既に説明しています。

  2. ページ サイズ オプションが指定されているかどうかを確認します。 C# または JS アプリでは、印刷ヘルパー クラスでこのオプションを確認できます。 C++ アプリでは、IPrintSchemaOption で QueryInterface を呼び出して IPrintSchemaPageMediaSizeOption を取得します。

    この例は、ページ サイズ オプションが指定されているかどうかを確認する印刷ヘルパー クラスのメソッドを示します。

    public bool ShouldShowCustomUI(string index)
    {
        if (null != index)
        {
            string feature = "PageMediaSize";
            int i = int.Parse(index);
            IPrintSchemaOption selectedOption = GetCachedFeatureOptions(feature)[i];
            if (selectedOption.Name.Equals("CustomMediaSize", StringComparison.CurrentCulture)
                || selectedOption.Name.Equals("PSCustomMediaSize", StringComparison.CurrentCulture))
            {
                return true;
            }
        }
        return false;
    }
    
  3. カスタム ポップアップでは、ページの高さと幅をユーザーに尋ねるカスタム UI を表示し、IPrintSchemaPageMediaSizeOption からユーザー指定の高さと幅を取得します。

    この例は、ページの高さと幅をユーザーに尋ねるカスタム ポップアップのメソッドを示します。

    private void ShowCustomPageMediaSizeUI(string index, bool keepValue)
    {
        //Hide custom media size UI unless needed
        if (IsCustomSizeSelected(index))
        {
           if (keepValue && (!customWidth.Equals("")) && (!customHeight.Equals("")))
           {
                        CustomWidthBox.Text = customWidth;
                        CustomHeightBox.Text = customHeight;
           }
           else
           {
              // Use a helper function from the WinRT helper component
              CustomWidthBox.Text = printHelper.GetCustomWidth(index);
              CustomHeightBox.Text = printHelper.GetCustomHeight(index);
           }
           CustomUIPanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
           CustomWidthBox.KeyDown += OnCustomValueEntered;
           CustomHeightBox.KeyDown += OnCustomValueEntered;
        }
        else
        {
           CustomUIPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
           CustomWidthBox.KeyDown -= OnCustomValueEntered;
           CustomHeightBox.KeyDown -= OnCustomValueEntered;
        }
    }
    
  4. ユーザー指定の値で IPrintSchemaPageMediaSizeOption オブジェクトを更新し、高さと幅がユーザー指定の値と一致することを確認します。

    この例は、プリンター ヘルパー クラスの IPrintSchemaPageMediaSizeOption オブジェクトを更新するためのヘルパー メソッドです。 カスタム ポップアップ内の OnSaveRequested ハンドラーは、カスタム ページ サイズ オプションが要求されたと判断すると、この関数を呼び出します。

    public void SetCustomMediaSizeDimensions(string width, string height)
    {
      if ((null == width) && (null == height) && (null == Capabilities))
      {
                    return;
      }
      try
      {
                    CheckSizeValidity(width, height);
      }
      catch (FormatException e)
      {
                    throw new ArgumentException(e.Message);
      }
      catch (OverflowException e)
      {
                    throw new ArgumentException(e.Message);
      }
    
      // The context is retrieved during app activation.
      IPrintSchemaTicket ticket = context.Ticket;
    
      //
      // Input XML as Stream
      //
      XElement ticketRootXElement = null;
      using (Stream ticketReadStream = ticket.GetReadStream())
      {
         ticketRootXElement = XElement.Load(ticketReadStream);
      }
    
      XNamespace psfNs = PrintSchemaConstants.FrameworkNamespaceUri;
      XNamespace pskNs = PrintSchemaConstants.KeywordsNamespaceUri;
      string pskPrefix = ticketRootXElement.GetPrefixOfNamespace(pskNs);
    
      // Modify the MediaSizeHeight and MediaSizeWidth
      IEnumerable<XElement> parameterInitCollection =
        from c in ticketRootXElement.Elements(psfNs + "ParameterInit")
    
      select c;
    
      foreach (XElement parameterInit in parameterInitCollection)
      {
        if (0 == String.Compare((string)parameterInit.Attribute("name"), pskPrefix + ":PageMediaSizePSWidth"))
        {
          IEnumerable<XElement> valueCollection = from c in parameterInit.Elements(psfNs + "Value")
          select c;
          valueCollection.ElementAt(0).Value = width;
        }
    
         else if (0 == String.Compare((string)parameterInit.Attribute("name"), pskPrefix + ":PageMediaSizePSHeight"))
        {
          IEnumerable<XElement> valueCollection = from c in parameterInit.Elements(psfNs + "Value")
          select c;
          valueCollection.ElementAt(0).Value = height;
         }
      }
    
      //
      // Write XLinq changes back to DOM
      //
       using (Stream ticketWriteStream = ticket.GetWriteStream())
       {
         ticketRootXElement.Save(ticketWriteStream);
       }
    }
    

テスト

UWP デバイス アプリはテストする前に、デバイス メタデータを使用してプリンターにリンクする必要があります。

  • デバイス アプリ情報をプリンターに追加するには、プリンターのデバイス メタデータ パッケージのコピーが必要です。 デバイス メタデータがない場合は、「UWP デバイス アプリのデバイス メタデータを作成する」トピックの説明に従い、デバイス メタデータ作成ウィザードを使用して作成できます。

    Note

    デバイス メタデータ作成ウィザードを使用するには、このトピックの手順を完了する前に、Microsoft Visual Studio Professional、Microsoft Visual Studio Ultimate、またはスタンドアロン SDK for Windows 8.1 をインストールする必要があります。 Microsoft Visual Studio Express for Windows をインストールすると、ウィザードを含まないバージョンの SDK がインストールされます。

次の手順に沿ってアプリを作成し、デバイス メタデータをインストールします。

  1. テスト署名を有効にします。

    1. DeviceMetadataWizard.exe をダブルクリックして、%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 からデバイス メタデータ作成ウィザードを開始します。

    2. [ツール] メニューの [テスト署名を有効にする] を選択します。

  2. コンピューターを再起動します

  3. ソリューション (.sln) ファイルを開いてソリューションを構築します。 サンプルが読み込まれた後、F7 キーを押すか、上部のメニューから [Build] -> [ソリューションの構築] に移動します。

  4. プリンターを切断してアンインストールします。 この手順は、次回デバイスが検出されたときに Windows が更新されたデバイス メタデータを読み取るために必要です。

  5. デバイス メタデータを編集して保存します。 デバイス アプリをデバイスにリンクするには、デバイス アプリをデバイスに関連付ける必要があります

    Note

    デバイス メタデータをまだ作成していない場合は、「UWP デバイス アプリのデバイス メタデータを作成する」を参照してください。

    1. デバイス メタデータ作成ウィザードをまだ開いていない場合は、DeviceMetadataWizard.exe をダブルクリックして、%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 からウィザードを開始します。

    2. [デバイス メタデータの編集] をクリックします。 これにより、既存のデバイス メタデータ パッケージを編集できます。

    3. [開く] ダイアログ ボックスで、UWP デバイス アプリに関連付けられているデバイス メタデータ パッケージを見つけます。 (devicemetadata-ms ファイル拡張子が付いています)

    4. [UWP デバイス アプリ情報の指定] ページで、[UWP デバイス アプリ] ボックスに Microsoft Store アプリ情報を入力します。 [UWP アプリ マニフェスト ファイルのインポート] をクリックすると、[パッケージ名][発行元名][UWP アプリ ID] が自動的に入力されます。

    5. アプリでプリンター通知を登録する場合は、[通知ハンドラー] ボックスを入力します。 [イベント ID] に、印刷イベント ハンドラーの名前を入力します。 [イベント アセット] に、そのコードが駐在するファイルの名前を入力します。

    6. 完了したら、[完了] ページが表示されるまで [次へ] をクリックします。

    7. [デバイス メタデータ パッケージの確認] ページで、すべての設定が正しいことを確認し、[ローカル コンピューターのメタデータ ストアにデバイス メタデータ パッケージをコピーする] チェック ボックスを選択します。 [保存] をクリックします。

  6. デバイスが接続されている場合は、プリンターを再接続して、Windows が更新されたデバイス メタデータを読み取れるようにします。

トラブルシューティング

問題: 印刷の詳細設定で、カスタム ポップアップではなく、既定のポップアップが表示される

印刷の詳細設定のポップアップに、アプリが実装するカスタム ポップアップではなく、既定のポップアップが表示される場合は...

  • 考えられる原因: テスト署名が有効になっていません。 有効にする方法については、このトピックの「デバッグ」セクションを参照してください。

  • 考えられる原因: アプリが適切なパッケージ ファミリ名でクエリを実行していません。 コードでパッケージ ファミリ名を確認してください。 Visual Studio で package.appxmanifest を開き、クエリを実行するパッケージ ファミリ名が 、"パッケージ ファミリ名" フィールドの [パッケージ] タブにある名前と一致していることを確認してください。

  • 考えられる原因: デバイス メタデータがパッケージ ファミリ名に関連付けられていません。 デバイス メタデータ作成ウィザードを使用してデバイス メタデータを開き、パッケージ ファミリ名を確認してください。 DeviceMetadataWizard.exe をダブルクリックして、%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 からウィザードを開始します。

問題: アプリがポップアップで起動され、すぐに非表示になる

印刷の詳細設定のカスタム ポップアップが起動直後に消える場合は...

  • 考えられる原因: Windows 8 では、ポップアップ内で UWP アプリがデバッガーの影響で非表示になるという既知の問題があります。 アクティブ化が機能することがわかっている場合は、デバッグをオフにします。 印刷チケットの保存をデバッグする必要がある場合は、アクティブ化の後でデバッガーをアタッチします。

v4 印刷ドライバーの開発

プリンター拡張機能インターフェイス (v4 プリンター ドライバー)

双方向通信

UWP アプリの概要

UWP デバイス アプリを作成する (ステップ バイ ステップ ガイド)

UWP デバイス アプリのデバイス メタデータを作成する (ステップ バイ ステップ ガイド)