none
Windows.Formsのコントロールを印刷(プレビュー)したい RRS feed

  • 質問

  • いつもお世話になっております。

    XPSを使用し、WPFのWindowに配置したWindows.Formsのコントロールを印刷(プレビュー)したいのですが
    プレビュー時に何も表示されません。


    Wikipediaによると以下の記述がありました。
    「WPFのUI上に配置されたWin32あるいはWindows FormsによるレガシーなUIコントロールの描画に対しては、GPUアクセラレーションが効かない(GDI/GDI+によって描画される)ので注意が必要である。」


    仕様的に無理なのでしょうか・・・・?


    このような場合、皆さんはどうされていますか?

                //こちらは何も表示されない
                //System.Windows.Forms.TextBox txt1 = new System.Windows.Forms.TextBox();
    
                //こちらはOK
                System.Windows.Controls.TextBox txt1 = new System.Windows.Controls.TextBox();
    
                txt1.Width = 100;
                txt1.Height = 100;
    
    
                txt1.Text = "ハロー";
    
                //System.Windows.Forms.Integration.WindowsFormsHost wf = new System.Windows.Forms.Integration.WindowsFormsHost();
                //wf.Child = txt1;
                //printCanvas.Children.Add(wf);
    
                printCanvas.Children.Add(txt1);

    2012年11月6日 1:03

回答

  • まず前提として、こちらのサイトに書いてあるように、WindowsFormsHostの描画はVisualBrush等で取ることができません。

    http://blog.motdotnet.com/?day=20070227

    おそらくVisualBrushからDrawingVisualを生成して、FixedDocumentに格納してDocumentViewerでプレビューしようとされているのだと思いますが、その方法だと上記の制約に阻まれます。

    で、どうするかというとXPSドキュメントを経由すれば良いのですが、どう頑張っても一回XPSファイルを出力しなければなりません(とりあえず私には無理でした・・・orz)。

    こんな感じです。

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                System.Windows.Forms.TextBox txt1 = new System.Windows.Forms.TextBox();
    
                txt1.Width = 150;
                txt1.Height = 50;
    
                txt1.Text = "ハロー";
    
                System.Windows.Forms.Integration.WindowsFormsHost wf = new System.Windows.Forms.Integration.WindowsFormsHost { Height = 50, Width = 150 };
                wf.Child = txt1;
                printCanvas.Children.Add(wf);
    
                using (Package package = Package.Open(@"c:\WUTemp\test.xps", FileMode.Create))
                {
                    using (XpsDocument document = new XpsDocument(package))
                    {
                        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(document);
                        writer.Write(printCanvas);
                    }
                }
    
                using (XpsDocument document = new XpsDocument(@"c:\WUTemp\test.xps", FileAccess.Read))
                {
                    documentViewer.Document = document.GetFixedDocumentSequence();
                }
            }
    

    ほんとはMemoryStreamに出力して再取込できればスマートだったんですが、どう頑張ってもGetFixedDocumentSequenceでエラーになるという・・・

    • 編集済み みっと 2012年11月6日 8:06
    • 回答としてマーク sumi_sumi 2012年11月7日 2:47
    2012年11月6日 8:04

すべての返信

  • 試してませんが、ハードウェアアクセラレータを無効にしてみてはいかがでしょうか?

    System.Windows.Media.RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly


    ひらぽん http://d.hatena.ne.jp/hilapon/

    2012年11月6日 2:13
    モデレータ
  • ひらぽんさま

    有難う御座います。

    早速試させていただきましたが現象変わらずでした。

    2012年11月6日 4:52
  • 私の方で試してみましたが、ちゃんと印刷されましたよ。よって、

    「WPFのUI上に配置されたWin32あるいはWindows FormsによるレガシーなUIコントロールの描画に対しては、GPUアクセラレーションが効かない(GDI/GDI+によって描画される)ので注意が必要である。」

    は関係ないようです。

    ちなみに印刷はうまく行っていて、プレビューのみダメなのでしょうか? もし、そうであればどのようにプレビューされているのでしょうか?
    PrintCanvasを印刷プレビューする方法を調べてみたのですが、わかりませんでした。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年11月6日 7:06
    モデレータ
  • まず前提として、こちらのサイトに書いてあるように、WindowsFormsHostの描画はVisualBrush等で取ることができません。

    http://blog.motdotnet.com/?day=20070227

    おそらくVisualBrushからDrawingVisualを生成して、FixedDocumentに格納してDocumentViewerでプレビューしようとされているのだと思いますが、その方法だと上記の制約に阻まれます。

    で、どうするかというとXPSドキュメントを経由すれば良いのですが、どう頑張っても一回XPSファイルを出力しなければなりません(とりあえず私には無理でした・・・orz)。

    こんな感じです。

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                System.Windows.Forms.TextBox txt1 = new System.Windows.Forms.TextBox();
    
                txt1.Width = 150;
                txt1.Height = 50;
    
                txt1.Text = "ハロー";
    
                System.Windows.Forms.Integration.WindowsFormsHost wf = new System.Windows.Forms.Integration.WindowsFormsHost { Height = 50, Width = 150 };
                wf.Child = txt1;
                printCanvas.Children.Add(wf);
    
                using (Package package = Package.Open(@"c:\WUTemp\test.xps", FileMode.Create))
                {
                    using (XpsDocument document = new XpsDocument(package))
                    {
                        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(document);
                        writer.Write(printCanvas);
                    }
                }
    
                using (XpsDocument document = new XpsDocument(@"c:\WUTemp\test.xps", FileAccess.Read))
                {
                    documentViewer.Document = document.GetFixedDocumentSequence();
                }
            }
    

    ほんとはMemoryStreamに出力して再取込できればスマートだったんですが、どう頑張ってもGetFixedDocumentSequenceでエラーになるという・・・

    • 編集済み みっと 2012年11月6日 8:06
    • 回答としてマーク sumi_sumi 2012年11月7日 2:47
    2012年11月6日 8:04
  • trapemiya さま

    有難う御座います。

    FixedDocumentに格納してDocumentViewerでプレビューしようとしておりました。

    2012年11月7日 2:46
  • みっとさま

    有難う御座います。

    ご指摘の通り、FixedDocumentに格納しておりました。

    分かりやすい解説、ならびにサンプルソース有難う御座います。

    おかげで実現出来ました。

    本当に有難う御座いました。

    2012年11月7日 2:47