none
印刷の(現在)ページ指定方法について RRS feed

  • 質問

  • .NET Framework4.0のC#(WPF)でFixedDocumentを使用して、現在ページを印刷させたいです。(全ページ印刷はできています)

    独自印刷設定ダイアログを使用する場合、各種設定後、その値をPrintDialogクラスの各プロパティに設定することになると思います。

    現在ページの指定は、PageRangeSelectionプロパティにメンバUserPagesを、PageRangeプロパティに現在ページをセットする必要が

    あると思いますが、4.5のメンバCurrentPageのように簡単に指定する方法はないでしょうか?(現在ページの管理をプログラムでせず対応する方法)


    また、一般的な話になりますが、プリンタ種類(XPSや、PDF、一般的なプリンタなど)によって、ページの指定方法は実装してやる必要があるものなのでしょうか?

    よろしくお願いします。


    • 編集済み tenpu 2014年5月13日 4:57
    2014年5月13日 4:46

回答

  • 独自印刷設定ダイアログを使用する場合、各種設定後、その値をPrintDialogクラスの各プロパティに設定することになると思います。

    独自の設定ダイアログがあるならば、PrintDialogに設定せずともPrintTicketとXpsDocumentWriterで印刷は行えます。

    現在ページの指定は、PageRangeSelectionプロパティにメンバUserPagesを、PageRangeプロパティに現在ページをセットする必要があると思いますが、4.5のメンバCurrentPageのように簡単に指定する方法はないでしょうか?(現在ページの管理をプログラムでせず対応する方法)

    DocumentViewerで表示しているFixedDocumentのCurrentPageという意味であれば、DocumentViewerにMasterPageNumberというプロパティがあるので、それをPageRangeに使えばいいです。

    また、一般的な話になりますが、プリンタ種類(XPSや、PDF、一般的なプリンタなど)によって、ページの指定方法は実装してやる必要があるものなのでしょうか?

    設定できるプロパティはプリンタごとに違ったりします。たとえば両面印刷ができるできないとか。(PrintCapabilities参照)
    実際にプリンタの対応状況は実行環境によって異なるので、考慮して設定してやる必要があります。
    ですが、PrintDialogをつかうなら、PrintTicketに設定してくれるので、わざわざ実装する必要はありません。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Xps.Packaging;
    using System.Printing;
    
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            private FixedDocument fixedDocument;
            private DocumentViewer viewer;
            public MainWindow()
            {
                InitializeComponent();
                
                Button button = new Button();
                button.Content = "Print";
                DockPanel.SetDock(button, Dock.Top);
                button.Click += Button_Click;
    
                 viewer = new DocumentViewer();
    
                DockPanel dock = new DockPanel();
                dock.Children.Add(button);
                dock.Children.Add(viewer);
                this.Content = dock;
    
                var document = new XpsDocument(@"C:\sample.xps", System.IO.FileAccess.Read);
                var sequence = document.GetFixedDocumentSequence();
                fixedDocument =sequence.References[0].GetDocument(false);
    
                viewer.Document = sequence;
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                PrintTicket ticket = GetPrintTicketFromPrinter();
                var que = LocalPrintServer.GetDefaultPrintQueue();
    
                System.Windows.Xps.XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(que);
    
                int currentPage = viewer.MasterPageNumber;
    
                FixedDocument fixRangeDocument = CreateRangeDocument(fixedDocument, new PageRange(currentPage, currentPage));
                writer.Write(fixRangeDocument.DocumentPaginator, ticket);
            }
    
            /// <summary>FixedDocumentから指定範囲を抽出したFixedDocumentを作る</summary>
            private FixedDocument CreateRangeDocument(FixedDocument sourceDocument, PageRange range)
            {
                return GetRangeDocument(sourceDocument, Enumerable.Range(range.PageFrom-1,range.PageFrom - range.PageTo  +1));
            }
            /// <summary>FixedDocumentから指定ページを抽出したFixedDocumentを作る</summary>
            private FixedDocument GetRangeDocument(FixedDocument sourceDocument,IEnumerable<int> pageIndexies)
            {
                PrintDialog dlg = new PrintDialog();
                dlg.ShowDialog();
    
                var x=pageIndexies.ToArray();
                FixedDocument docNew = new System.Windows.Documents.FixedDocument();
                System.Windows.Markup.IAddChild pages = (System.Windows.Markup.IAddChild)docNew;
                foreach(int pageIndex in pageIndexies)
                {
                    PageContent pageContent;
                    pageContent = new System.Windows.Documents.PageContent();
                    pageContent.BeginInit();
                    var page = this.fixedDocument.Pages[pageIndex];
                    ((System.Windows.Markup.IUriContext)pageContent).BaseUri = ((System.Windows.Markup.IUriContext)page).BaseUri;
                    pageContent.Source = page.Source; ;
                    pageContent.EndInit();
                    pages.AddChild(pageContent);
                }
                return docNew;
            }
    
            //http://msdn.microsoft.com/ja-jp/library/vstudio/ms573295%28v=vs.100%29.aspxより
            private PrintTicket GetPrintTicketFromPrinter()
            {
                PrintQueue printQueue = null;
    
                LocalPrintServer localPrintServer = new LocalPrintServer();
                PrintQueueCollection localPrinterCollection =
                    localPrintServer.GetPrintQueues();
    
                System.Collections.IEnumerator localPrinterEnumerator =
                    localPrinterCollection.GetEnumerator();
    
                if (localPrinterEnumerator.MoveNext())
                {
                    printQueue = (PrintQueue)localPrinterEnumerator.Current;
                }
                else
                {
                    return null;
                }
    
                PrintTicket printTicket = printQueue.DefaultPrintTicket;
    
                PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();
    
                //if (printCapabilites.CollationCapability.Contains(Collation.Collated))
                //{
                //    printTicket.Collation = Collation.Collated;
                //}
    
                //if (printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge))
                //{
                //    printTicket.Duplexing = Duplexing.TwoSidedLongEdge;
                //}
    
                //if (printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
                //{
                //    printTicket.Stapling = Stapling.StapleDualLeft;
                //}
    
                return printTicket;
            }
        }
    }


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)


    • 編集済み gekkaMVP 2014年5月13日 17:20
    • 回答の候補に設定 星 睦美 2014年5月15日 2:33
    • 回答としてマーク 星 睦美 2014年5月22日 5:17
    2014年5月13日 17:17

すべての返信

  • 独自印刷設定ダイアログを使用する場合、各種設定後、その値をPrintDialogクラスの各プロパティに設定することになると思います。

    独自の設定ダイアログがあるならば、PrintDialogに設定せずともPrintTicketとXpsDocumentWriterで印刷は行えます。

    現在ページの指定は、PageRangeSelectionプロパティにメンバUserPagesを、PageRangeプロパティに現在ページをセットする必要があると思いますが、4.5のメンバCurrentPageのように簡単に指定する方法はないでしょうか?(現在ページの管理をプログラムでせず対応する方法)

    DocumentViewerで表示しているFixedDocumentのCurrentPageという意味であれば、DocumentViewerにMasterPageNumberというプロパティがあるので、それをPageRangeに使えばいいです。

    また、一般的な話になりますが、プリンタ種類(XPSや、PDF、一般的なプリンタなど)によって、ページの指定方法は実装してやる必要があるものなのでしょうか?

    設定できるプロパティはプリンタごとに違ったりします。たとえば両面印刷ができるできないとか。(PrintCapabilities参照)
    実際にプリンタの対応状況は実行環境によって異なるので、考慮して設定してやる必要があります。
    ですが、PrintDialogをつかうなら、PrintTicketに設定してくれるので、わざわざ実装する必要はありません。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Xps.Packaging;
    using System.Printing;
    
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            private FixedDocument fixedDocument;
            private DocumentViewer viewer;
            public MainWindow()
            {
                InitializeComponent();
                
                Button button = new Button();
                button.Content = "Print";
                DockPanel.SetDock(button, Dock.Top);
                button.Click += Button_Click;
    
                 viewer = new DocumentViewer();
    
                DockPanel dock = new DockPanel();
                dock.Children.Add(button);
                dock.Children.Add(viewer);
                this.Content = dock;
    
                var document = new XpsDocument(@"C:\sample.xps", System.IO.FileAccess.Read);
                var sequence = document.GetFixedDocumentSequence();
                fixedDocument =sequence.References[0].GetDocument(false);
    
                viewer.Document = sequence;
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                PrintTicket ticket = GetPrintTicketFromPrinter();
                var que = LocalPrintServer.GetDefaultPrintQueue();
    
                System.Windows.Xps.XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(que);
    
                int currentPage = viewer.MasterPageNumber;
    
                FixedDocument fixRangeDocument = CreateRangeDocument(fixedDocument, new PageRange(currentPage, currentPage));
                writer.Write(fixRangeDocument.DocumentPaginator, ticket);
            }
    
            /// <summary>FixedDocumentから指定範囲を抽出したFixedDocumentを作る</summary>
            private FixedDocument CreateRangeDocument(FixedDocument sourceDocument, PageRange range)
            {
                return GetRangeDocument(sourceDocument, Enumerable.Range(range.PageFrom-1,range.PageFrom - range.PageTo  +1));
            }
            /// <summary>FixedDocumentから指定ページを抽出したFixedDocumentを作る</summary>
            private FixedDocument GetRangeDocument(FixedDocument sourceDocument,IEnumerable<int> pageIndexies)
            {
                PrintDialog dlg = new PrintDialog();
                dlg.ShowDialog();
    
                var x=pageIndexies.ToArray();
                FixedDocument docNew = new System.Windows.Documents.FixedDocument();
                System.Windows.Markup.IAddChild pages = (System.Windows.Markup.IAddChild)docNew;
                foreach(int pageIndex in pageIndexies)
                {
                    PageContent pageContent;
                    pageContent = new System.Windows.Documents.PageContent();
                    pageContent.BeginInit();
                    var page = this.fixedDocument.Pages[pageIndex];
                    ((System.Windows.Markup.IUriContext)pageContent).BaseUri = ((System.Windows.Markup.IUriContext)page).BaseUri;
                    pageContent.Source = page.Source; ;
                    pageContent.EndInit();
                    pages.AddChild(pageContent);
                }
                return docNew;
            }
    
            //http://msdn.microsoft.com/ja-jp/library/vstudio/ms573295%28v=vs.100%29.aspxより
            private PrintTicket GetPrintTicketFromPrinter()
            {
                PrintQueue printQueue = null;
    
                LocalPrintServer localPrintServer = new LocalPrintServer();
                PrintQueueCollection localPrinterCollection =
                    localPrintServer.GetPrintQueues();
    
                System.Collections.IEnumerator localPrinterEnumerator =
                    localPrinterCollection.GetEnumerator();
    
                if (localPrinterEnumerator.MoveNext())
                {
                    printQueue = (PrintQueue)localPrinterEnumerator.Current;
                }
                else
                {
                    return null;
                }
    
                PrintTicket printTicket = printQueue.DefaultPrintTicket;
    
                PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();
    
                //if (printCapabilites.CollationCapability.Contains(Collation.Collated))
                //{
                //    printTicket.Collation = Collation.Collated;
                //}
    
                //if (printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge))
                //{
                //    printTicket.Duplexing = Duplexing.TwoSidedLongEdge;
                //}
    
                //if (printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
                //{
                //    printTicket.Stapling = Stapling.StapleDualLeft;
                //}
    
                return printTicket;
            }
        }
    }


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)


    • 編集済み gekkaMVP 2014年5月13日 17:20
    • 回答の候補に設定 星 睦美 2014年5月15日 2:33
    • 回答としてマーク 星 睦美 2014年5月22日 5:17
    2014年5月13日 17:17
  • フォーラム オペレーターの星 睦美です。
    gekka さん、いつも回答ありがとうございます。

    tenpu さん、参考になる回答だと思いますので今回は私から[回答としてマーク] させていただきました。
    (もし疑問な点がありましたら、[回答としてのマークの解除]をして返信できます。)
    投稿者からの[回答としてマーク] が回答者のはげみになりますので、次回役立つ回答がありましたらtenpu さんから[回答としてマーク] いただけると嬉しいです。

    では、これからもMSDN フォーラムをよろしくお願いします。


    フォーラム オペレーター 星 睦美 - MSDN Community Support

    2014年5月22日 5:23
  • また、一般的な話になりますが、プリンタ種類(XPSや、PDF、一般的なプリンタなど)によって、ページの指定方法は実装してやる必要があるものなのでしょうか?

     質問の内容からして、ここで言う「ページの指定方法」は、「ページ番号の指定方法」のことだと思います。
     プリンタは、それぞれのドキュメント データのどこからが1ページ目で、どこからが2ページ目かわかりません。つまり、word 文書の「1ページ目」を表す符号と、Excel 文書の「1ページ目」を表す符号は異なっていると考えられます。なので、ドキュメント データを認識出るもの、つまりアプリケーションが「ページ」という概念を与えてやらなければならないと思いますが、いかがでしょうか。


    Jitta@わんくま同盟

    2014年5月22日 12:32