WPFでの印刷の基本(1) 単一ページの印刷

Windorws Form に比べてWPFでの印刷はかなり複雑になったという印象。その分融通は効くようになった感じですが慣れるまでがなかなか大変かも。

まず一番シンプルな単一のページを印刷する方法をまとめてみます。

# 単一ページの印刷

まず最初にコードを示します。

デフォルトプリンターにA4縦で左上隅から100x100ピクセルの位置に24ピクセルサイズで「TEST」の文字列を印刷するサンプルです。

コンパイルするためにはWPFアプリケーションのプロジェクトに「System.Printing」と「ReachFramework」の参照設定を加える必要があります。WPFアプリケーションで印刷を行うにはこれらの参照設定が必要になります。

```csharp
// 単一ページの印刷
private void PrintSinglePage()
{
    // 1.各種オブジェクトの生成
    LocalPrintServer lps = new LocalPrintServer();
    PrintQueue queue = lps.DefaultPrintQueue;
    XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue);

    // 2. 用紙サイズの設定
    PrintTicket ticket = queue.DefaultPrintTicket;
    ticket.PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4);
    ticket.PageOrientation = PageOrientation.Portrait;

    // 3. FixedPage の生成
    FixedPage page = new FixedPage();

    // 4. 印字データの作成
    Canvas canvas = new Canvas();
    TextBlock tb = new TextBlock();
    tb.Text = "TEST";
    tb.FontSize = 24;
    Canvas.SetTop(tb, 100);
    Canvas.SetLeft(tb, 100);
    canvas.Children.Add(tb);
    page.Children.Add(canvas);

    // 5. 印刷の実行
    writer.Write(page, ticket);
}
```

## 1. 各種オブジェクトの生成・取得

まず初めに印刷処理を行うための各種オブジェクトの生成と取得を行う必要があります。

まず最初に`LocalPrintServer`のオブジェクトを生成します。読んで字のごとくローカルコンピューターのプリントサーバーを扱うためのクラスでWPFの印刷処理の起点となります。

```csharp
LocalPrintServer lps = new LocalPrintServer();
```

次に`LocalPrintServer`から印刷を行うプリントキューを取得します。デフォルトプリンターのキューは`LocalPrintServer.DefaultPrintQueue`というプロパティから取得することができます。

```csharp
PrintQueue queue = lps.DefaultPrintQueue;
```

キューが取得できたら、さらにそのキューに印刷データを書き込むための`XpsDocumentWriter`クラスのオブジェクトを取得します。これ`PrintQueue`クラスの静的メソッドである`PrintQueue.CreateXpsDocumentWriter`に書き込みを行うキューを渡すことで取得できます。

```csharp
XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue);
```

これで印刷を行うために必要なオブジェクトの生成と取得は完了です。

## 2. 用紙サイズ等の設定を行う

印刷を行う場合、普通はまずどのサイズの用紙に印刷を行うか指定するのが普通でしょう。用紙サイズの設定には`PrintTicket`クラスのオブジェクトを利用します。

`PrintTicket`クラスは用紙サイズや部数など印刷ジョブに関する各種設定を行うためのクラスです。オブジェクトは印刷を行う`PrintQueue`オブジェクトの`PrintQueue.DefaultPrintTicket`プロパティから取得できます。

```csharp
PrintTicket ticket = queue.DefaultPrintTicket;
```

`PrintTicket`オブジェクトを取得したら、用紙の設定を行えます。

用紙のサイズは`PageMediaSize`プロパティに`PageMediaSize`クラスのオブジェクトを指定することで行います。用紙の向きは`PageOrientation`プロパティで指定します。

```csharp
ticket.PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4);
ticket.PageOrientation = PageOrientation.Portrait;
```

## 3. FixedPage オブジェクトの生成

ここまでは印刷の準備で、ここからが印刷処理の本体になります。

WPFの印刷処理では、キューに印刷データを書き込む`XpsDocumentWriter`に直接、印刷を行う文字列だのイメージだのを渡す訳ではなく、印刷を行う文書をまずオブジェクトとして生成し、印刷したい情報をすべて設定して完成させた後、その文章オブジェクトを`XpsDocumentWriter`に渡してまとめてキューに書き込む形式になります。

その`XpsDocumentWriter`に渡す、印刷文書オブジェクトとなるクラスはいくつか用意されているのですが、今回はもっとも単純な単一のページを表す｀FixedPage`クラスを利用します。

`FixedPage`クラスのオブジェクトを生成するには、普通に`new`するだけでOKです。

```csharp
FixedPage page = new FixedPage();
```

## 4.印刷データの作成

生成された`FixedPage`のオブジェクトは一枚の用紙を表すので、そこに印刷したい文字列やイメージなどを指定していきます。

`FixedPage`に印刷する要素を指定するには、その子要素に`UIElement`のオブジェクトを追加していくことで行います。要するに`Window`オブジェクトに様々なコントロールを配置して画面を作成するのと同じ方法で印刷紙面を作成していくことができます。通常XAMLで記述する画面をコードで記述した場合をイメージしてもらうとOKです。

今回は極単純に、左上隅から100x100ピクセルの位置に24ピクセルサイズで「TEST」の文字列を印刷してみます。

```csharp
Canvas canvas = new Canvas();
TextBlock tb = new TextBlock();
tb.Text = "TEST";
tb.FontSize = 24;
Canvas.SetTop(tb, 100);
Canvas.SetLeft(tb, 100);
canvas.Children.Add(tb);
page.Children.Add(canvas);
```

`Canvas`オブジェクトを作成し、`TextBlock`を配置します。

すべての印刷要素の配置が完了したら、`Canvas`オブジェクトを`FixedPage`オブジェクトの`Children`に`Add`します。


## 5.印刷の実行

作成した`FixedPage`オブジェクトを`PrintTicket`オブジェクトと共に`XpsDocumentWriter`の`Write`メソッドに渡してキューに書き込むことで印刷を実行します。

```csharp
writer.Write(page, ticket);
```

問題がなければデフォルトプリンターで印刷が開始される筈です。