アプリからの印刷Print from your app

重要な APIImportant APIs

ユニバーサル Windows アプリからドキュメントを印刷する方法について説明します。Learn how to print documents from a Universal Windows app. また、このトピックでは特定のページを印刷する方法も示します。This topic also shows how to print specific pages. 印刷プレビュー UI の高度な変更については、「印刷プレビュー UI のカスタマイズ」を参照してください。For more advanced changes to the print preview UI, see Customize the print preview UI.

ヒント

 このトピックの例のほとんどは、印刷のサンプルに基づいています。 Most of the examples in this topic are based on the print sample. 完全なコードを確認するには、GitHub の Windows-universal-samples リポジトリからユニバーサル Windows プラットフォーム (UWP) 印刷サンプルをダウンロードしてください。To see the full code, download the Universal Windows Platform (UWP) print sample from the Windows-universal-samples repo on GitHub.

印刷の登録Register for printing

アプリに印刷機能を追加する最初の手順は、印刷コントラクトへの登録です。The first step to add printing to your app is to register for the Print contract. アプリは、ユーザーによる印刷を可能にするすべての画面でこの処理を行う必要があります。Your app must do this on every screen from which you want your user to be able to print. ユーザーに表示される画面のみ、印刷登録を行うことができます。Only the screen that is displayed to the user can be registered for printing. アプリの画面を印刷登録した場合は、画面終了時に印刷登録を解除する必要があります。If one screen of your app has registered for printing, it must unregister for printing when it exits. 別の画面で置き換えられる場合は、その画面が開いたときに画面を新しい印刷コントラクトに登録する必要があります。If it is replaced by another screen, the next screen must register for a new Print contract when it opens.

ヒント

 アプリでは、複数のページからの印刷をサポートする必要がある場合は、一般的なヘルパー クラスにこのプリントのコードを配置し、アプリ ページを再利用できます。 If you need to support printing from more than one page in your app, you can put this print code in a common helper class and have your app pages reuse it. この方法の例については、UWP 印刷サンプルに挙げられている PrintHelper クラスをご覧ください。For an example of how to do this, see the PrintHelper class in the UWP print sample.

まず、PrintManagerPrintDocument を宣言します。First, declare the PrintManager and PrintDocument. 他の Windows 印刷機能をサポートするタイプと共に、PrintManager タイプが Windows.Graphics.Printing 名前空間内に指定されています。The PrintManager type is in the Windows.Graphics.Printing namespace along with types to support other Windows printing functionality. XAML コンテンツの印刷準備をサポートする他のタイプと共に、PrintDocument タイプが Windows.UI.Xaml.Printing 名前空間内に指定されています。The PrintDocument type is in the Windows.UI.Xaml.Printing namespace along with other types that support preparing XAML content for printing. 次の using ステートメントまたは Imports ステートメントをページに追加することで、印刷コードを簡単に記述できます。You can make it easier to write your printing code by adding the following using or Imports statements to your page.

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

PrintDocument クラスはアプリと PrintManager 間の多くの対話を処理しますが、独自のコールバックがいくつか公開されます。The PrintDocument class is used to handle much of the interaction between the app and the PrintManager, but it exposes several callbacks of its own. 登録中に PrintManagerPrintDocument のインスタンスを作成し、それらの印刷イベントのハンドラーを登録します。During registration, create instances of PrintManager and PrintDocument and register handlers for their printing events.

UWP 印刷サンプルでは、登録は RegisterForPrinting メソッドによって実行されます。In the UWP print sample, registration is performed by the RegisterForPrinting method.

public virtual void RegisterForPrinting()
{
   printDocument = new PrintDocument();
   printDocumentSource = printDocument.DocumentSource;
   printDocument.Paginate += CreatePrintPreviewPages;
   printDocument.GetPreviewPage += GetPrintPreviewPage;
   printDocument.AddPages += AddPrintPages;

   PrintManager printMan = PrintManager.GetForCurrentView();
   printMan.PrintTaskRequested += PrintTaskRequested;
}

ユーザーが印刷のサポートされているページに移動すると、OnNavigatedTo メソッド内で登録を開始します。When the user goes to a page that supports printing, it initiates the registration within the OnNavigatedTo method.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
   // Initialize common helper class and register for printing
   printHelper = new PrintHelper(this);
   printHelper.RegisterForPrinting();

   // Initialize print content for this scenario
   printHelper.PreparePrintContent(new PageToPrint());

   // Tell the user how to print
   MainPage.Current.NotifyUser("Print contract registered with customization, use the Print button to print.", NotifyType.StatusMessage);
}

ユーザーがページから離れた時点で、印刷イベント ハンドラーを切り離します。When the user leaves the page, disconnect the printing event handlers. 複数ページ アプリが存在し、印刷を切断しないと、ユーザーがページからいったん移動してそのページに戻ってきたときに例外がスローされます。If you have a multiple-page app and don't disconnect printing, an exception is thrown when the user leaves the page and then comes back to it.

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
   if (printHelper != null)
   {
         printHelper.UnregisterForPrinting();
   }
}

印刷ボタンの作成Create a print button

アプリの画面の任意の場所に印刷ボタンを追加します。Add a print button to your app's screen where you'd like it to appear. 印刷するコンテンツの妨げにならないようにします。Make sure that it doesn't interfere with the content that you want to print.

<Button x:Name="InvokePrintingButton" Content="Print" Click="OnPrintButtonClick"/>

次に、クリック イベントを処理するイベント ハンドラーをアプリのコードに追加します。Next, add an event handler to your app's code to handle the click event. ShowPrintUIAsync メソッドを使用してアプリからの印刷を開始します。Use the ShowPrintUIAsync method to start printing from your app. ShowPrintUIAsync は適切な印刷ウィンドウを表示する非同期メソッドです。ShowPrintUIAsync is an asynchronous method that displays the appropriate printing window. 印刷をサポートするデバイス上でアプリが実行されていることを確認する (およびサポートされていないケースに対処する) ために、先に IsSupported メソッドを呼び出すことをお勧めします。We recommend calling the IsSupported method first in order to check that the app is being run on a device that supports printing (and handle the case in which it is not). その時点でなんらかの理由で印刷を実行できない場合は、ShowPrintUIAsync は例外をスローします。If printing can't be performed at that time for any other reason, ShowPrintUIAsync will throw an exception. 印刷を続行できない場合は、これらの例外をキャッチして、ユーザーに知らせることをお勧めします。We recommend catching these exceptions and letting the user know when printing can't proceed.

async private void OnPrintButtonClick(object sender, RoutedEventArgs e)
{
    if (Windows.Graphics.Printing.PrintManager.IsSupported())
    {
        try
        {
            // Show print UI
            await Windows.Graphics.Printing.PrintManager.ShowPrintUIAsync();

        }
        catch
        {
            // Printing cannot proceed at this time
            ContentDialog noPrintingDialog = new ContentDialog()
            {
                Title = "Printing error",
                Content = "\nSorry, printing can' t proceed at this time.", PrimaryButtonText = "OK"
            };
            await noPrintingDialog.ShowAsync();
        }
    }
    else
    {
        // Printing is not supported on this device
        ContentDialog noPrintingDialog = new ContentDialog()
        {
            Title = "Printing not supported",
            Content = "\nSorry, printing is not supported on this device.",PrimaryButtonText = "OK"
        };
        await noPrintingDialog.ShowAsync();
    }
}

この例では、ボタン クリックのイベント ハンドラーに印刷ウィンドウが表示されます。In this example, a print window is displayed in the event handler for a button click. メソッドによって例外がスローされる場合 (その時点で印刷を実行することができないため)、ContentDialog コントロールによってその状況がユーザーに通知されます。If the method throws an exception (because printing can't be performed at that time), a ContentDialog control informs the user of the situation.

アプリのコンテンツの書式設定Format your app's content

ShowPrintUIAsync が呼び出されると、PrintTaskRequested イベントが発生します。When ShowPrintUIAsync is called, the PrintTaskRequested event is raised. この手順に示す PrintTaskRequested イベント ハンドラーは、PrintTaskRequest.CreatePrintTask メソッドを呼び出して PrintTask を作成し、印刷ページのタイトルと PrintTaskSourceRequestedHandler デリゲートの名前を渡します。The PrintTaskRequested event handler shown in this step creates a PrintTask by calling the PrintTaskRequest.CreatePrintTask method and passes the title for the print page and the name of a PrintTaskSourceRequestedHandler delegate. この例では、PrintTaskSourceRequestedHandler がインラインで定義されています。Notice that in this example, the PrintTaskSourceRequestedHandler is defined inline. PrintTaskSourceRequestedHandler は、印刷用の書式付きコンテンツを用意します (後述)。The PrintTaskSourceRequestedHandler provides the formatted content for printing and is described later.

この例では、エラーを捕捉するために完了ハンドラーも定義されています。In this example, a completion handler is also defined to catch errors. エラー発生の有無をユーザーに知らせ、考えられる解決策を提供することが可能になるため、完了イベントを処理することをお勧めします。It's a good idea to handle completion events because then your app can let the user know if an error occurred and provide possible solutions. 同様に、完了イベントを使うと、印刷ジョブが正常に終了した後でユーザーが実行する手順を提示することができます。Likewise, your app could use the completion event to indicate subsequent steps for the user to take after the print job is successful.

protected virtual void PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs e)
{
   PrintTask printTask = null;
   printTask = e.Request.CreatePrintTask("C# Printing SDK Sample", sourceRequested =>
   {
         // Print Task event handler is invoked when the print job is completed.
         printTask.Completed += async (s, args) =>
         {
            // Notify the user when the print operation fails.
            if (args.Completion == PrintTaskCompletion.Failed)
            {
               await scenarioPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
               {
                     MainPage.Current.NotifyUser("Failed to print.", NotifyType.ErrorMessage);
               });
            }
         };

         sourceRequested.SetSource(printDocumentSource);
   });
}

印刷タスクが作られた後、PrintManagerPaginate イベントを発生させることによって、印刷プレビュー UI に表示するために印刷ページのコレクションを要求します。After the print task is created, the PrintManager requests a collection of print pages to show in the print preview UI by raising the Paginate event. これは、IPrintPreviewPageCollection インターフェイスの Paginate メソッドに対応します。This corresponds with the Paginate method of the IPrintPreviewPageCollection interface. 登録時に作成したイベント ハンドラーは、この時点で呼び出されます。The event handler you created during registration will be called at this time.

重要

 ユーザーの変更は、設定を印刷する場合ページ設定のイベント ハンドラーがコンテンツをリフローすることができるようにもう一度呼び出されます。 If the user changes print settings, the paginate event handler will be called again to allow you to reflow the content. 優良なユーザー エクスペリエンスのため、マイクロソフトではコンテンツを再配置する前に設定を確認し、ページ付けされたコンテンツの不必要な再初期化を避けることをお勧めします。For the best user experience, we recommend checking the settings before you reflow the content and avoid reinitializing the paginated content when it's not necessary.

Paginate イベント ハンドラー (UWP 印刷サンプル内の CreatePrintPreviewPages メソッド) で、印刷プレビュー UI に表示されてプリンターに送信されるページを作ります。In the Paginate event handler (the CreatePrintPreviewPages method in the UWP print sample), create the pages to show in the print preview UI and to send to the printer. アプリのコンテンツの印刷準備のために使うコードは、アプリと印刷するコンテンツに固有です。The code you use to prepare your app's content for printing is specific to your app and the content you print. コンテンツを印刷用に書式設定する方法については、UWP 印刷サンプルのソース コードを参照してください。Refer to the UWP print sample source code to see how it formats its content for printing.

protected virtual void CreatePrintPreviewPages(object sender, PaginateEventArgs e)
{
   // Clear the cache of preview pages
   printPreviewPages.Clear();

   // Clear the print canvas of preview pages
   PrintCanvas.Children.Clear();

   // This variable keeps track of the last RichTextBlockOverflow element that was added to a page which will be printed
   RichTextBlockOverflow lastRTBOOnPage;

   // Get the PrintTaskOptions
   PrintTaskOptions printingOptions = ((PrintTaskOptions)e.PrintTaskOptions);

   // Get the page description to deterimine how big the page is
   PrintPageDescription pageDescription = printingOptions.GetPageDescription(0);

   // We know there is at least one page to be printed. passing null as the first parameter to
   // AddOnePrintPreviewPage tells the function to add the first page.
   lastRTBOOnPage = AddOnePrintPreviewPage(null, pageDescription);

   // We know there are more pages to be added as long as the last RichTextBoxOverflow added to a print preview
   // page has extra content
   while (lastRTBOOnPage.HasOverflowContent && lastRTBOOnPage.Visibility == Windows.UI.Xaml.Visibility.Visible)
   {
         lastRTBOOnPage = AddOnePrintPreviewPage(lastRTBOOnPage, pageDescription);
   }

   if (PreviewPagesCreated != null)
   {
         PreviewPagesCreated.Invoke(printPreviewPages, null);
   }

   PrintDocument printDoc = (PrintDocument)sender;

   // Report the number of preview pages created
   printDoc.SetPreviewPageCount(printPreviewPages.Count, PreviewPageCountType.Intermediate);
}

特定のページが印刷プレビュー ウィンドウに表示されると、PrintManager によって GetPreviewPage イベントが生成されます。When a particular page is to be shown in the print preview window, the PrintManager raises the GetPreviewPage event. これは、IPrintPreviewPageCollection インターフェイスの MakePage メソッドに対応します。This corresponds with the MakePage method of the IPrintPreviewPageCollection interface. 登録時に作成したイベント ハンドラーは、この時点で呼び出されます。The event handler you created during registration will be called at this time.

GetPreviewPage イベント ハンドラー (UWP 印刷サンプル内の GetPrintPreviewPage メソッド) で、適切なページを印刷ドキュメントに設定します。In the GetPreviewPage event handler (the GetPrintPreviewPage method in the UWP print sample), set the appropriate page on the print document.

protected virtual void GetPrintPreviewPage(object sender, GetPreviewPageEventArgs e)
{
   PrintDocument printDoc = (PrintDocument)sender;
   printDoc.SetPreviewPage(e.PageNumber, printPreviewPages[e.PageNumber - 1]);
}

最後に、ユーザーが印刷ボタンをクリックすると、PrintManager によって IDocumentPageSource インターフェイスの MakeDocument メソッドが呼び出され、プリンターに送信するページの最終コレクションが要求されます。Finally, once the user clicks the print button, the PrintManager requests the final collection of pages to send to the printer by calling the MakeDocument method of the IDocumentPageSource interface. XAML では、これによって AddPages イベントが生成されます。In XAML, this raises the AddPages event. 登録時に作成したイベント ハンドラーは、この時点で呼び出されます。The event handler you created during registration will be called at this time.

AddPages イベント ハンドラー (UWP 印刷サンプル内の AddPrintPages メソッド) で、ページ コレクションから、プリンターに送られる PrintDocument オブジェクトにページを追加します。In the AddPages event handler (the AddPrintPages method in the UWP print sample), add pages from the page collection to the PrintDocument object to be sent to the printer. 印刷する特定ページまたはページ範囲がユーザーによって指定される場合は、プリンターに実際に送られるページだけを追加するためにその情報をここで使います。If a user specifies particular pages or a range of pages to print, you use that information here to add only the pages that will actually be sent to the printer.

protected virtual void AddPrintPages(object sender, AddPagesEventArgs e)
{
   // Loop over all of the preview pages and add each one to  add each page to be printied
   for (int i = 0; i < printPreviewPages.Count; i++)
   {
         // We should have all pages ready at this point...
         printDocument.AddPage(printPreviewPages[i]);
   }

   PrintDocument printDoc = (PrintDocument)sender;

   // Indicate that all of the print pages have been provided
   printDoc.AddPagesComplete();
}

印刷オプションの準備Prepare print options

次に、印刷オプションを準備します。Next prepare print options. たとえば、このセクションでは特定のページの印刷を許可するためにページ範囲オプションを設定する方法について説明します。As an example, this section will describe how to set the page range option to allow printing of specific pages. 詳細なオプションについては、「印刷プレビュー UI のカスタマイズ」を参照してください。For more advanced options, see Customize the print preview UI.

この手順では、新しい印刷オプションを作成し、オプションがサポートする値の一覧を定義して、印刷プレビュー UI にオプションを追加します。This step creates a new print option, defines a list of values that the option supports, and then adds the option to the print preview UI. ページ範囲オプションでは次の設定を指定できます。The page range option has these settings:

オプション名Option name アクションAction
すべての印刷Print all ドキュメントのすべてのページを印刷します。Print all pages in the document.
選択したを印刷します。Print Selection ユーザーが選んだ内容のみを印刷します。Print only the content the user selected.
印刷範囲Print Range ユーザーが印刷するページを入力できる編集コントロールを表示します。Display an edit control into which the user can enter the pages to print.

まず、PrintTaskRequested イベント ハンドラーを変更し、PrintTaskOptionDetails オブジェクトを取得するコードを追加します。First, modify the PrintTaskRequested event handler to add the code to get a PrintTaskOptionDetails object.

PrintTaskOptionDetails printDetailedOptions = PrintTaskOptionDetails.GetFromPrintTaskOptions(printTask.Options);

印刷プレビュー UI に表示されるオプションの一覧をクリアし、ユーザーがアプリから印刷する場合に表示するオプションを追加します。Clear the list of options that are shown in the print preview UI and add the options that you want to display when the user wants to print from the app.

注意

 ウィンドウの上部に表示する最初のオプションの追加と同じ順序で印刷プレビュー UI で、オプションが表示されます。 The options appear in the print preview UI in the same order they are appended, with the first option shown at the top of the window.

IList<string> displayedOptions = printDetailedOptions.DisplayedOptions;

displayedOptions.Clear();
displayedOptions.Add(Windows.Graphics.Printing.StandardPrintTaskOptions.Copies);
displayedOptions.Add(Windows.Graphics.Printing.StandardPrintTaskOptions.Orientation);
displayedOptions.Add(Windows.Graphics.Printing.StandardPrintTaskOptions.ColorMode);

新しい印刷オプションを作成し、オプションの値の一覧を初期化します。Create the new print option and initialize the list of option values.

// Create a new list option
PrintCustomItemListOptionDetails pageFormat = printDetailedOptions.CreateItemListOption("PageRange", "Page Range");
pageFormat.AddItem("PrintAll", "Print all");
pageFormat.AddItem("PrintSelection", "Print Selection");
pageFormat.AddItem("PrintRange", "Print Range");

カスタム印刷オプションを追加し、イベント ハンドラーを割り当てます。Add your custom print option and assign the event handler. カスタム オプションは最後に追加されるため、オプションの一覧の最下部に表示されます。The custom option is appended last so that it appears at the bottom of the list of options. ただし、カスタム オプションは一覧のどこにでも配置可能です。必ずしもカスタム印刷オプションを最後に追加する必要はありません。But you can put it anywhere in the list, custom print options don't need to be added last.

// Add the custom option to the option list
displayedOptions.Add("PageRange");

// Create new edit option
PrintCustomTextOptionDetails pageRangeEdit = printDetailedOptions.CreateTextOption("PageRangeEdit", "Range");

// Register the handler for the option change event
printDetailedOptions.OptionChanged += printDetailedOptions_OptionChanged;

CreateTextOption メソッドによって [範囲] ボックスが作成されます。The CreateTextOption method creates the Range text box. これは、ユーザーが [印刷範囲] オプションを選んだときに印刷対象となるページを入力する場所です。This is where the user enters the specific pages they want to print when they select the Print Range option.

印刷オプションの変更の処理Handle print option changes

OptionChanged イベント ハンドラーは主に次の 2 つを実行します。The OptionChanged event handler does two things. まず、ユーザーが選んだページ範囲オプションに応じて、ページ範囲のテキスト編集フィールドの表示/非表示を切り替えます。First, it shows and hides the text edit field for the page range depending on the page range option that the user selected. そして、ページ範囲ボックスに入力されたテキストをテストして、ドキュメントの有効ページ範囲であるかどうかを確認します。Second, it tests the text entered into the page range text box to make sure that it represents a valid page range for the document.

この例は、UWP 印刷サンプルによる変更イベントの処理方法を示します。This example shows how the UWP print sample handles change events.

async void printDetailedOptions_OptionChanged(PrintTaskOptionDetails sender, PrintTaskOptionChangedEventArgs args)
{
   if (args.OptionId == null)
   {
         return;
   }

   string optionId = args.OptionId.ToString();

   // Handle change in Page Range Option
   if (optionId == "PageRange")
   {
         IPrintOptionDetails pageRange = sender.Options[optionId];
         string pageRangeValue = pageRange.Value.ToString();

         selectionMode = false;

         switch (pageRangeValue)
         {
            case "PrintRange":
               // Add PageRangeEdit custom option to the option list
               sender.DisplayedOptions.Add("PageRangeEdit");
               pageRangeEditVisible = true;
               await scenarioPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
               {
                     ShowContent(null);
               });
               break;
            case "PrintSelection":
               await scenarioPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
               {
                     Scenario4PageRange page = (Scenario4PageRange)scenarioPage;
                     PageToPrint pageContent = (PageToPrint)page.PrintFrame.Content;
                     ShowContent(pageContent.TextContentBlock.SelectedText);
               });
               RemovePageRangeEdit(sender);
               break;
            default:
               await scenarioPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
               {
                     ShowContent(null);
               });
               RemovePageRangeEdit(sender);
               break;
         }

         Refresh();
   }
   else if (optionId == "PageRangeEdit")
   {
         IPrintOptionDetails pageRange = sender.Options[optionId];
         // Expected range format (p1,p2...)*, (p3-p9)* ...
         if (!Regex.IsMatch(pageRange.Value.ToString(), @"^\s*\d+\s*(\-\s*\d+\s*)?(\,\s*\d+\s*(\-\s*\d+\s*)?)*$"))
         {
            pageRange.ErrorText = "Invalid Page Range (eg: 1-3, 5)";
         }
         else
         {
            pageRange.ErrorText = string.Empty;
            try
            {
               GetPagesInRange(pageRange.Value.ToString());
               Refresh();
            }
            catch (InvalidPageException ipex)
            {
               pageRange.ErrorText = ipex.Message;
            }
         }
   }
}

ヒント

 参照してください、GetPagesInRangeメソッドで、 UWP 印刷サンプルページを解析する方法の詳細については、ユーザーを範囲に対しては、範囲のテキスト ボックスに入力します。 See the GetPagesInRange method in the UWP print sample for details on how to parse the page range the user enters in the Range text box.

選んだページのプレビューPreview selected pages

アプリのコンテンツ印刷用の書式設定は、アプリの特性とコンテンツによって異なります。How you format your app's content for printing depends on the nature of your app and its content. UWP 印刷サンプルでは、印刷ヘルパー クラスを使ってそのコンテンツの書式を印刷用に設定しています。The UWP print sample uses a print helper class to format its content for printing.

ページのサブセットを印刷するとき、印刷プレビューでコンテンツを表示する方法はいくつかあります。When printing a subset of the pages, there are several ways to show the content in the print preview. 指定されたページ範囲をどのような方法で印刷プレビューに表示するかに関係なく、印刷出力には、選ばれたページだけが含まれている必要があります。Regardless of the method you chose to show the page range in the print preview, the printed output must contain only the selected pages.

  • ページ範囲が指定されているかどうかに関係なく印刷プレビューにすべてのページを表示し、実際にどのページを印刷するかはユーザーの判断に委ねます。Show all the pages in the print preview whether a page range is specified or not, leaving the user to know which pages will actually be printed.
  • ユーザーがページ範囲で選んだページだけを印刷プレビューに表示し、ページ範囲が変更されるたびに、表示を最新の情報に更新します。Show only the pages selected by the user's page range in the print preview, updating the display whenever the user changes the page range.
  • すべてのページを印刷プレビューに表示します。ただし、ユーザーが選んだページ範囲に含まれていないページは灰色で表示されます。Show all the pages in print preview, but grey out the pages that are not in page range selected by the user.