セージ の メモ書き

メモこそ命の恩人だ

WPF の 印刷処理 してみる

XpsDocumentWriter クラス

XpsDocumentWriter クラス (System.Windows.Xps) | Microsoft Docs

PrintQueue.CreateXpsDocumentWriter メソッド (System.Printing) | Microsoft Docs

  • 指定オブジェクトを XPS ドキュメントにして印刷キューにセットする。

    https://soseiji-memo.hatenablog.com/entry/xps

  • 下記形式のオブジェクトを扱える。

    • FixedPage
    • FixedDocument
  • PrintQueue クラスの CreateXpsDocumentWriter メソッドにより、XpsDocumentWriter を生成できる。

  • 参照の追加より、下記2つを追加する必要がある。

    • ReachFramework
    • System.Printing

こんな感じ。

// FixedPage 用
public void Print(FixedPage fixedPage)
{
    // 印刷キューの取得(既定のプリンター)
    using (var localPrintServer = new LocalPrintServer())
    using (var printQueue = localPrintServer.DefaultPrintQueue)
    {
        // 印刷ジョブの作成
        var printTicket = printQueue.DefaultPrintTicket;
        printTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4);
        printTicket.PageOrientation = PageOrientation.Portrait;

        // XpsDocumentWriter の生成
        var xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);

        // 印刷実行(XPS以外でも印刷可)
        xpsDocumentWriter.Write(fixedPage, printTicket);
    }
}
// FixedDocument 用
public void Print(FixedDocument fixedDocument)
{
    // 印刷キューの取得(既定のプリンター)
    using (var localPrintServer = new LocalPrintServer())
    using (var printQueue = localPrintServer.DefaultPrintQueue)
    {
        // 印刷ジョブの作成
        var printTicket = printQueue.DefaultPrintTicket;
        printTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4);
        printTicket.PageOrientation = PageOrientation.Portrait;

        // XpsDocumentWriter の生成
        var xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);

        // 印刷実行(XPS以外でも印刷可)
        xpsDocumentWriter.Write(fixedDocument, printTicket);
    }
}

WPF の印刷処理

Documents - WPF | Microsoft Docs

  • FixedPage / FixedDocument により印刷を行う。
    • 固定ドキュメント。UIElement の配置情報が記録されてる。
    • WYSIWYG である。( ディスプレイで見た内容と同じサイズの結果が得られる。)

単一ページの印刷 -> FixedPage クラス

FixedPage クラス (System.Windows.Documents) | Microsoft Docs

using System.Windows.Documents;
using System.Windows.Markup;
// このコントロールを印刷してみる。( A4 )
var printData = new PrintUserControl()
{
    Width = 794,
    Height= 1123,
    DataContext = this
};

// FixedPage に上記コントロールを登録する。
var fixedPage = new FixedPage();
fixedPage.Children.Add(printData);

// 印刷開始
Print(fixedPage);

// 既定のプリンターで印刷できたことを確認。

複数ページの印刷 -> FixedDocument クラス

FixedDocument クラス (System.Windows.Documents) | Microsoft Docs

  • 複数の FiexedPage オブジェクトを管理できる。
  • これにより、複数ページの印刷が行える。

印刷データの構成はこんな感じ。

f:id:soseiji-memo:20190303173452p:plain

ソースはこんな感じ。

// このコントロールを印刷する。
var printData = new PrintUserControl();

// FixedPage に上記コントロールを登録する。
var fixedPage = new FixedPage();
fixedPage.Children.Add(printData);

// PageContent に FixedPage を登録する。
var pageContent = new PageContent();
((IAddChild)pageContent).AddChild(fixedPage);
                
// FixedDocument を作成し、
// FixedDocument の PageContentCollection に 1ページ目の PageContent を登録する。
var fixedDocument = new FixedDocument();
fixedDocument.Pages.Add(pageContent);

// 印刷開始
Print(fixedDocument);

複数ページ印刷してみる。

var printData = new PrintUserControl();
var fixedPage = new FixedPage();
fixedPage.Children.Add(printData);
var pageContent = new PageContent();
((IAddChild)pageContent).AddChild(fixedPage);

// 20ページ分でのデータを生成する。
var fixedDocument = new FixedDocument();
foreach (var item in Enumerable.Range(1,20))
{
    fixedDocument.Pages.Add(pageContent);
}

// 印刷開始
Print(fixedDocument);

// 20ページのデータが生成されたことを確認。

バインディング時の注意点

  • バインディングする場合、ユーザーコントロールを更新する必要がある。
  • Datagridの自動列幅調整(*指定の調整)をする場合、「更新2」の内容も必要。
    適用しない場合、Datagridの幅が詰まって表示されてしまう。(Datagridの不具合???)
// 更新1(効果:UI描画更新、バインディング反映、InteractionRequest使用)
userControl.Measure(userControl.RenderSize);
userControl.Arrange(new Rect(new Point(0, 0), userControl.RenderSize));
userControl.UpdateLayout();
// 更新2(効果:Datagridの自動列幅調整)
var currentDispatcher = Dispatcher.CurrentDispatcher;
void dummy() { }
currentDispatcher.Invoke(dummy, DispatcherPriority.Loaded);


以上😃