WPFでの印刷の基本(4) DrawingContext を用いた印刷 

WPFでの印刷では`UIElement`の派生クラスをもちいて行うのが基本(?)ですが、`DrawingContext`を利用することで、従来のGDIを利用した描画ライクな手法で印刷を行うことができます。

## DrawingContext を用いた印刷のサンプル

[前回](http://qiita.com/hugo-sb/items/a713c2c230a4ade2c13c)とほぼ同様のイメージを印刷するサンプル。

```csharp
// FormattedText の生成
private FormattedText CreateFormatedText(string s, double width, TextAlignment align)
{
    FormattedText fmtText = new FormattedText(
        s,
        System.Globalization.CultureInfo.CurrentCulture,
        System.Windows.FlowDirection.LeftToRight,
        new Typeface("ＭＳ Ｐゴシック"),
        24.0d,Brushes.Black);
    fmtText.MaxTextWidth = width;
    fmtText.TextAlignment = align;
    return fmtText;
}

// ページの描画
private void DrawPage(DrawingContext dc)
{
    // Lineの描画
    for (int i = 0; i < 10; i++)
    {
        Pen pen = new Pen(Brushes.Black, 1.0d + (i * 0.5d));
        dc.DrawLine(pen, new Point(100.0d, 100.0d + (i * 10.0d)), 
                         new Point(200.0d, 100.0d + (i * 10.0d)));
    }

    // 矩形の描画
    dc.DrawRectangle(Brushes.Blue, new Pen(Brushes.Black, 1.0d), 
                                   new Rect(250.0d, 100.0d, 100.0d, 100.0d));

    // 円の描画
    dc.DrawEllipse(Brushes.Green, new Pen(Brushes.Black, 1.0d), 
                                  new Point(450.0d, 150.0d), 50.0d, 50.0d);

    // ジオメトリの描画
    StreamGeometry sg1 = new StreamGeometry();
    using (StreamGeometryContext ctx = sg1.Open())
    {
        ctx.BeginFigure(new Point(600.0d, 100.0d), true, true);
        ctx.LineTo(new Point(650.0d, 180.0d), true, true);
        ctx.LineTo(new Point(550.0d, 180.0d), true, true);
    }
    sg1.Freeze();
    dc.DrawGeometry(Brushes.Red, new Pen(Brushes.Black, 2.0d), sg1);

    StreamGeometry sg2 = new StreamGeometry();
    using (StreamGeometryContext ctx = sg2.Open())
    {
        ctx.BeginFigure(new Point(550.0d, 120.0d), true, true);
        ctx.LineTo(new Point(650.0d, 120.0d), true, true);
        ctx.LineTo(new Point(600.0d, 200.0d), true, true);
    }
    sg2.Freeze();
    dc.DrawGeometry(Brushes.Yellow, new Pen(Brushes.Black, 2.0d), sg2);

    // イメージの描画
    Uri imageUri = new Uri("file://c:/temp/CAT.JPG");
    dc.DrawImage(new BitmapImage(imageUri), new Rect(100.0d, 250.0d, 100.0d, 100.0d));

    // テキストの描画
    dc.DrawRectangle(null, new Pen(Brushes.Black, 1.0d), new Rect(99.0d, 399.0d, 502.0d, 102.0d));

    FormattedText fmtTextL = CreateFormatedText("左寄せ文字列", 500.0d, TextAlignment.Left);
    dc.DrawText(fmtTextL, new Point(100.0d, 400.0d + (30.0d - fmtTextL.Height) / 2.0d));

    FormattedText fmtTextC = CreateFormatedText("中央寄せ文字列", 500.0d, TextAlignment.Center);
    dc.DrawText(fmtTextC, new Point(100.0d, 430.0d + (30.0d - fmtTextC.Height) / 2.0d));

    FormattedText fmtTextR = CreateFormatedText("右寄せ文字列", 500.0d, TextAlignment.Right);
    dc.DrawText(fmtTextR, new Point(100.0d, 460.0d + (30.0d - fmtTextR.Height) / 2.0d));
}

// 印刷処理
private void PrintPage()
{
    // 各種オブジェクトの生成と取得
    LocalPrintServer lps = new LocalPrintServer();
    PrintQueue queue = lps.DefaultPrintQueue;
    XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue);

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

    // VisualsToXpsDocumentの生成
    VisualsToXpsDocument v2xps = writer.CreateVisualsCollator() as VisualsToXpsDocument;
    v2xps.BeginBatchWrite();
    try
    {
        ContainerVisual container = new ContainerVisual();
        DrawingVisual dv = new DrawingVisual();
        using (DrawingContext dc = dv.RenderOpen())
        {
            DrawPage(dc);
        }
        container.Children.Add(dv);
        v2xps.Write(container, ticket);
    }
    finally
    {
        v2xps.EndBatchWrite();
    }
}
```

印刷処理は、`VisualsToXpsDocument.BeginBatchWrite()`から、`VisualsToXpsDocument.EndBatchWrite()`の間で行う必要があります。

印刷はページ単位で、`VisualsToXpsDocument.Write()`を呼び出すたびに改ページが発生します。