2011-10-28 38 views
6

WPFコントロールを印刷する方法を検索し、いくつかの解決策を見つけました。アスペクト比を維持しながら、印刷されたコントロールを印刷ページに合わせる必要があります(私のコントロールは四角です;スドクグリッド)。WPFページに合わせて印刷

ページに合わせてサイズを変更して位置を変更するソリューションが見つかりました。それはうまくいきますが、それは私のウィンドウにコントロールを置き換えます。ここ

は、私は、印刷およびスケーリングのために使用するコードは次のとおりです。

 //get selected printer capabilities 
      System.Printing.PrintCapabilities capabilities = dialog.PrintQueue.GetPrintCapabilities(dialog.PrintTicket); 
     //get scale of the print wrt to screen of WPF visual 
     double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth/mrizka.ActualWidth, capabilities.PageImageableArea.ExtentHeight/mrizka.ActualHeight); 

     //Transform the Visual to scale 
     mrizka.LayoutTransform = new ScaleTransform(scale, scale); 

     //get the size of the printer page 
     Size sz = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight); 

     //update the layout of the visual to the printer page size. 
     mrizka.Measure(sz); 
     mrizka.Arrange(new Rect(new Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz)); 

     dialog.PrintVisual(mrizka, mrizka.getID().ToString()); 

私はこの解決するために、2つのaproachesを試してみました:

  1. クローン私のコントロールをして、クローン化された1、unaffecting元を変換します。 何らかの理由でDidntの仕事が終了しました。提供されたDependencyObjectは、このFreezableのコンテキストではありませんが、奇妙なことにいくつかのケースでのみです。

  2. サイズと位置の変更を元に戻します。 InvalidateArrange()メソッドを呼び出そうとしましたが、printメソッドの最初の呼び出しでのみ動作していました。 2回目の通話中は、動作しませんでした。

どうすればよいですか、ご意見は<ありがとうございます。

答えて

19

私はこの質問がかなり古いことを知っていますが、この問題に対する解決策を自分で探しています。ここに私が現在使っている解決策があります。フレームワーク要素に対して元の変換を保存し、印刷が終了した後に再適用します。

private void Print(Visual v) 
    { 

     System.Windows.FrameworkElement e = v as System.Windows.FrameworkElement ; 
     if (e == null) 
      return; 

     PrintDialog pd = new PrintDialog(); 
     if (pd.ShowDialog() == true) 
     { 
      //store original scale 
      Transform originalScale = e.LayoutTransform; 
      //get selected printer capabilities 
      System.Printing.PrintCapabilities capabilities = pd.PrintQueue.GetPrintCapabilities(pd.PrintTicket); 

      //get scale of the print wrt to screen of WPF visual 
      double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth/e.ActualWidth, capabilities.PageImageableArea.ExtentHeight/
          e.ActualHeight); 

      //Transform the Visual to scale 
      e.LayoutTransform = new ScaleTransform(scale, scale); 

      //get the size of the printer page 
      System.Windows.Size sz = new System.Windows.Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight); 

      //update the layout of the visual to the printer page size. 
      e.Measure(sz); 
      e.Arrange(new System.Windows.Rect(new System.Windows.Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz)); 

      //now print the visual to printer to fit on the one page. 
      pd.PrintVisual(v, "My Print"); 

      //apply the original transform. 
      e.LayoutTransform = originalScale; 
     } 
    } 
+1

System.PrintingおよびReachFrameworkへの参照を追加する必要があります。 – StillLearnin

+0

またSystem.Windows.MediaとSystem.Windows.Controlsを参照しているようです – Jeff

+2

これは私にとってはうまくいかず、LayoutTransformはどんな種類のTransformにも関係なく無視されるようです。 – Lennart

1
private void DrawGrap_Click(object sender, RoutedEventArgs e) 
    { 
     // Visual v = sender as Visual; 
     Visual v = song2Grid as Visual; // the object (it is a DataGrid) that you want to print out, not a window 
     PrintDialog prtDlg = new PrintDialog(); 
     if (prtDlg.ShowDialog() == true) 
     { 
      // because 96 pixels in an inch for WPF window 
      double marginLeft = 96.0 * 0.75; // left margin is 0.75 inches 
      double marginTop = 96.0 * 0.75; // top margin is 0.75 inches 
      double marginRight = 96.0 * 0.75; // right margin is 0.75 inches 
      double marginBottom = 96.0 * 0.75; // bottom margin is 0.75 inches 

      // the following steps do not works for a WPF window 
      FrameworkElement win = v as FrameworkElement; 
      Transform oldLayoutTransform = win.LayoutTransform; 
      Size oldSize = new Size(win.ActualWidth, win.ActualHeight); 

      System.Printing.PrintCapabilities pCapability = prtDlg.PrintQueue.GetPrintCapabilities(prtDlg.PrintTicket); 

      // calculate print area that you want 
      double printWidth = (pCapability.PageImageableArea.ExtentWidth - pCapability.PageImageableArea.OriginWidth) 
           - (marginLeft + marginRight); 
      double printHeight = (pCapability.PageImageableArea.ExtentHeight - pCapability.PageImageableArea.OriginHeight) 
       - (marginTop + marginBottom); 

      // calculate the scale 
      double scale = Math.Min(printWidth/oldSize.Width , printHeight/oldSize.Height); 
      if (scale > 1.0) 
      { 
       // keep the original size and layout if printable area is greater than the object being printed 
       scale = 1.0; 
      } 

      // store the original layouttransform 
      win.LayoutTransform = new ScaleTransform(scale, scale); 

      // new size of the visual 
      Size newSize = new Size(oldSize.Width*scale , oldSize.Height*scale); 
      win.Measure(newSize); 

      // centralize print area 
      double xStartPrint = marginLeft + (printWidth - newSize.Width)/2.0; 
      double yStartPrint = marginTop + (printHeight - newSize.Height)/2.0; 
      win.Arrange(new Rect(new Point(xStartPrint,yStartPrint),newSize)); 

      // print out the visual 
      prtDlg.PrintVisual(win as Visual, "PrintTest"); 

      // resotre the original layouttransform and size on screen 
      win.LayoutTransform = oldLayoutTransform; 
      win.Measure(oldSize); 
      win.Arrange(new Rect(new Point(0,0),oldSize)); 
     } 
    } 

それはuser1018711によって尋ねられた質問への答えでした。 C#とWPFを使用して1つのプリンタページでプリントアウトを行う。ビジュアルを印刷したいときは、たくさんのコントロール(Button、DataGrid、TextBlock、Labelなど)を含む可能性のあるコントロールをコントロールすることができます。ここでは、プリンタにsong2Dridという名前のDataGridを印刷したいが、その内容はプリンタのページサイズ(用紙の幅よりも幅が広い)より大きく、切り詰められている。私はそれらのすべてを見ることができませんでしたので、私はビジュアルを拡大しなければなりませんでしたが、比率を古いものと同じに保ちたいと思っていました。

用紙の余白を左、上、右、下の用紙の両面に0.75インチに設定しました。私はまた、ビジュアルのコンテンツ(song2Grid)を紙に集中させました。だから私は紙の中央に印刷された内容を見ることができた。しかし、ビジュアルがApplication.Current.MainWindowのようなウィンドウであったり、新しいWindow()によってプログラムで作成されたウィンドウであれば、スケーリングされません。つまり、このメソッドはWindowオブジェクトでは機能しません。

また、元の外観を変更して元の画面に戻して印刷する場合は、次のように記述する必要があります。 win.LayoutTransform = oldLayoutTransform; win.Measure(oldSize);アラインメント(新しいRect(新しい点(0,0)、oldSize));

+4

あなたの答えにいくつかの説明を加えてください。コードを表示するだけでは非常に混乱します。 –

+0

[編集](http://stackoverflow.com/posts/36967240/edit)リンクを使用して、この情報を回答に追加してください。そうすれば、人々は探している情報を見つけるためにこれらのコメントをすべて読む必要がなく、答えが大幅に改善されます。 –

+0

ありがとうございます。私はここでかなり新しいです。 –

関連する問題