none
WPFでの印刷機能の実装について RRS feed

  • 質問

  • 下記の環境で開発を行っています。
    OS   Windows Vista
    言語 C#、.Net Framework  3.5

    現在、印刷機能の調査、実装を行っており、下記の手順で行うように指示されています。

    ① 印刷対象の画面をXAMLで作成(Microsoft  Expression Blend2を使用)

    ② ①で作成したXAMLをXPSファイルに変換

    ③ ②で作成したXPSファイルを印刷(具体的な印刷方法は未確定)

    現在②の段階の処理で、躓いており、XAMLのデータファイルをXPSファイルに変換する方法が全くわかりません。

    Web上では日本語のページが見つからず、英語で書かれたページは見つけたのですが、英語自体が殆ど理解できない上に、C#での開発自体が始めてのため、解読できませんでした。

    参考となるような日本語でのサイト・書籍等をご存知ないでしょうか?

    また、上記の機能を実装したご経験がございましたら、サンプルコードと日本語での説明を頂けたら幸いです。

    何卒、よろしくお願いします。

    2009年9月8日 9:18

回答

  • ご質問①については、FixedDocumentにこだわる必要はありません。
    XPSファイルデータを印刷したいのでしたら、documentの型を、FixedDocumentからXpsDocumentに変更して下さい。

    (先日の例ではFixedDocumentを使いましたが、他の型でも印刷は可能です。説明が足りず申し訳ありません。
    なお、他の型を使う場合はコードの手直しが必要になる場合があります。)

    XpsDocumentオブジェクトは、XamlReaderを使わなくても生成できます。
    これを印刷するときは、XpsDocumentからFixedDocumentSequenceを取り出して、Writeメソッドに渡します。

    例えば、先日の例Bを書き直すと、次のようになります。

            public void PrintFromXPS()
            {
                string xpspath = @"C:\Users\Public\Documents\xpsdocument.xps";
                XpsDocument document = new XpsDocument(xpspath, FileAccess.Read);
                
                LocalPrintServer server = new LocalPrintServer();
                PrintQueue queue = server.GetPrintQueue("出力先のプリンタ"); //プリンタ名を指定して下さい。
    
                XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue);
                //指定したプリンタで印刷されます。
                writer.Write(document.GetFixedDocumentSequence());
                document.Close();
            }
    

    XPSファイルを印刷する場合は、パス(上の例でのxpspath)を直接Writeメソッドに渡すこともできます。
    その場合は、documentが不要になります。


    ご質問②につきましては、例えば、印刷用紙サイズ、印刷の向き、印刷枚数などをPrintTicketを使って設定できます。
    デフォルト印刷設定から変更したい場合に用います。

    もっとも、WriteメソッドではPrintTicketは必須ではありませんので、変更がなければ省略してもよいと思います。
    設定が必要かどうか、またどのような設定が必要かは、使うプリンタや印刷内容に応じてご自身でご判断下さい。

    (参考)
    PrintTicket プロパティ
    http://msdn.microsoft.com/ja-jp/library/system.printing.printticket_properties.aspx

    • 回答としてマーク nobuhara 2009年9月16日 0:11
    2009年9月14日 7:06

すべての返信

  • こちらのページで「XamlFileToXps」の解説があります。
    但し、2006年1月ですのでサンプルが古い可能性があります。
    http://www.microsoft.com/japan/msdn/msdnmag/issues/06/01/XMLPaperSpecification/default.aspx
    えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
    2009年9月8日 9:40
  • WordからXPSに変換する方をお勧めします。
    http://office.microsoft.com/ja-jp/word/HA101675271041.aspx

    えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
    2009年9月8日 9:55
  • 早速のご回答ありがとうございます。

    上記の回答を併せて確認しました。

    基本的な質問なのですが、WordからXPSに変換する方法とは、一度、システムで吐き出したデータをWordに書き込こんだのち、Wordを開いてXPS形式に変換を行うということでしょうか?

    または、Word形式のテキストデータの方が、C#からの自動変換が容易なのでしょうか?

    仕様として、一回のボタン押下処理のアクションからデータ変換を行い、自動でプリンターが起動し、対象のドキュメントを印刷するところまで行わなければなりません。

    また、XamlFileToXpsの方は、コードの解析にもう少し、時間がかかりそうです。

    2009年9月8日 12:03
  • >Word形式のテキストデータの方が、C#からの自動変換が容易なのでしょうか?

    >① 印刷対象の画面をXAMLで作成(Microsoft  Expression Blend2を使用)
    >② ①で作成したXAMLをXPSファイルに変換
    >③ ②で作成したXPSファイルを印刷(具体的な印刷方法は未確定)

    ① 印刷対象の画面をWordで作成
    ② ①で作成したWordファイルをXPS形式で保存
    ③ ②で作成したXPSファイルを印刷 XpsDocumentWriter を使う(XPS ドキュメントの印刷サンプルとか参照

    の手順のほうが簡単ではないかと思ったからです。


    えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
    2009年9月8日 12:24
  • 次の方法などはいかがでしょうか?
    (A・Bは、別のプリンタを指定すれば、直接印刷することもできます。)

    A PrintDialogを使う
            public void Print()
            {
                FixedDocument document = new FixedDocument();
    
                PrintDialog dialog = new PrintDialog();
    
                //印刷ダイアログが表示されるので、プリンタを「Microsoft XPS Document Writer」にします。
                //他の印刷の設定もできます。
                bool? result = dialog.ShowDialog();
    
                if (result.HasValue && result.Value)
                {
                    dialog.PrintDocument(document.DocumentPaginator, "");
                }
            }
    

    B XpsDocumentWriterにPrintQueueを渡して使う
            public void Print()
            {
                FixedDocument document = new FixedDocument();
    
                LocalPrintServer server = new LocalPrintServer();
                PrintQueue queue = server.GetPrintQueue("Microsoft XPS Document Writer");
    
                XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue);
                //XPSドキュメントの出力先を尋ねるダイアログが表示されます。
                writer.Write(document);
            }

    C XpsDocumentWriterを直接使う
            public void Print()
            {
                FixedDocument document = new FixedDocument();
    
                string xpspath = @"C:\Users\Public\Documents\xpsdocument.xps";
                XpsDocument xpsdoc = new XpsDocument(xpspath, FileAccess.Write);
    
                XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsdoc);
                //xpspathで指定したパスに出力されます。
                writer.Write(document);
                xpsdoc.Close();
            }


    それぞれ、documentをお望みのものに入れ替えて下さい。
    XAMLを使うなら、XmlReaderを作成して、XamlReaderクラスのLoadメソッドに渡すとよいと思います。

    B・Cで印刷の設定をしたい場合は、必要なPrintTicketを作成して、Writeメソッドに渡すことができます。


    (参考)
    WPF 印刷の概要
    http://msdn.microsoft.com/ja-jp/library/ms742418.aspx
    2009年9月10日 6:45
  • Alfred360さんご回答ありがとうございます。

    現在、印刷対象のXAMLファイルを変換対象のデータ項目と置き換え処理後に、XPSファイルに変換するところまで成功しました。

    しかし、その後の印刷処理がうまくいかず、APIを読み込んでいるのですが、説明が難しくなかなか理解できません。

    申し訳ないのですが、追加で以下の質問させていただいてもよろしいでしょうか?

    ①FixedDocumentオブジェクトに印刷対象のXAMLデータ(XPSファイルデータ)を渡すには、どのようにコードを書けばよろしいでしょうか?
    (XamlReader.Loadメソッドの戻り値をFixedDocumentオブジェクトに渡そうとすると、型変換ができず、コンパイルエラーになっていしまいます。)

    ②印刷を行う場合にPrintTicketオブジェクトをWriteメソッドに渡すことは、理解できたのですが、PrintTicketオブジェクトにはどのような設定が必要でしょうか?

    以上です。

    何卒、宜しくお願いします。
    2009年9月14日 2:18
  • ご質問①については、FixedDocumentにこだわる必要はありません。
    XPSファイルデータを印刷したいのでしたら、documentの型を、FixedDocumentからXpsDocumentに変更して下さい。

    (先日の例ではFixedDocumentを使いましたが、他の型でも印刷は可能です。説明が足りず申し訳ありません。
    なお、他の型を使う場合はコードの手直しが必要になる場合があります。)

    XpsDocumentオブジェクトは、XamlReaderを使わなくても生成できます。
    これを印刷するときは、XpsDocumentからFixedDocumentSequenceを取り出して、Writeメソッドに渡します。

    例えば、先日の例Bを書き直すと、次のようになります。

            public void PrintFromXPS()
            {
                string xpspath = @"C:\Users\Public\Documents\xpsdocument.xps";
                XpsDocument document = new XpsDocument(xpspath, FileAccess.Read);
                
                LocalPrintServer server = new LocalPrintServer();
                PrintQueue queue = server.GetPrintQueue("出力先のプリンタ"); //プリンタ名を指定して下さい。
    
                XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue);
                //指定したプリンタで印刷されます。
                writer.Write(document.GetFixedDocumentSequence());
                document.Close();
            }
    

    XPSファイルを印刷する場合は、パス(上の例でのxpspath)を直接Writeメソッドに渡すこともできます。
    その場合は、documentが不要になります。


    ご質問②につきましては、例えば、印刷用紙サイズ、印刷の向き、印刷枚数などをPrintTicketを使って設定できます。
    デフォルト印刷設定から変更したい場合に用います。

    もっとも、WriteメソッドではPrintTicketは必須ではありませんので、変更がなければ省略してもよいと思います。
    設定が必要かどうか、またどのような設定が必要かは、使うプリンタや印刷内容に応じてご自身でご判断下さい。

    (参考)
    PrintTicket プロパティ
    http://msdn.microsoft.com/ja-jp/library/system.printing.printticket_properties.aspx

    • 回答としてマーク nobuhara 2009年9月16日 0:11
    2009年9月14日 7:06
  • いろいろと苦労しましたが何とか印刷処理の実装に成功しました。

    あとは、PrintTicketの設定だけで済みそうです。

    大変ありがとうございました。

    2009年9月15日 12:01