41章:WPFでの印刷(1) (C#)

    作成2013.04.30

     WPFアプリケーションにおける印刷に関しては、わかりやすい事例が見つかりませんでした。
  1. 参照元情報
     印刷の概要は
    「印刷の概要」にジャンプする
     内容が難解で理解が難しかったため、サンプルコードを参照しました。


  2. WPFでの印刷(1) (C#)
     サンプルコード「WPF Printing Overvie1」を単純化して作成しました。
     ダウンロード後は解凍してから使用してください。
      [WPFでの印刷(1) (C#) ]をダウンロードする。
     解凍すると「41WPF_Printing1」フォルダーがあります。
    注(1)「41WPF_Printing1」フォルダーの「WPF_Printing.sln」ファイルをダブルクリックすると「Express 2012 for Windows Desktop」が起動します。
    注(2)メニューの「ウインド」_「ウインドレイアウトのリセット」で標準に戻ります。
    注(3)「ソリューションエクスプローラ」ウインドウ内の「MainWindow.xaml」をダブルクリックすると「デザイン」と「XAML」が表示されます。
    注(4)メニューの「表示」_「コード」を選択するとコードが表示されます。
    注(5)「WPF_Printing.sln」の動作確認は「デバッグ」_「デバッグ開始」で実行します。デバッグ機能を用いて動作確認を行います。


  3. WPF_Printing.slnの実行
    (1)「Microsoft Visual Basic 2010 Express」のデバッグ機能を使用します。
    (2)「デバッグ」_「デバッグ開始」を選択します。
    (3)空白のMainWindow画面が表示されます。
    (4)Printボタンを押すとプリンター選択画面が表示されます。
    (5)印刷ボタンを押すと印刷が実行されます。
    (6)印刷後は図形が画面に表示されます。
    (7)クローズボックスで終了します。


  4. プロジェクトの構成
    (1)XAMLコードとコードで構成されます。


  5. MainWindow.xamlの全コード
    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
        <Grid x:Name="grid1">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="1. Using DrawingContext" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Margin="0,0,10,0"/>
                <Button Content="Print" Width="100" VerticalAlignment="Center" Click="Print_Click" Margin="0,10"/>
            </StackPanel>
        </Grid>
    </Window>
    


  6. XAMLのポイント
    (1)一般的な記載のみです。


  7. MainWindow.xaml.csの全コード
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    using System.Globalization;
    
    namespace WPF_Printing
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                DataContext = this;
            }
    
            private void Print_Click(object sender, RoutedEventArgs e)
            {
                System.Windows.Controls.PrintDialog printDialog = new System.Windows.Controls.PrintDialog();
                if (printDialog.ShowDialog() == true)
                {
                    DrawingVisual dv = new DrawingVisual();
    
                    var dc = dv.RenderOpen();
                    var rect = new Rect(new System.Windows.Point(20, 20), new System.Windows.Size(350, 240));
                    dc.DrawRoundedRectangle(System.Windows.Media.Brushes.Yellow, new Pen(Brushes.Purple, 2), rect, 20, 20);
    
                    dc.DrawText(new FormattedText("WPF Printing", CultureInfo.CurrentCulture, FlowDirection,
                          new Typeface(new System.Windows.Media.FontFamily("Courier New"), FontStyles.Normal, FontWeights.Bold,
                              FontStretches.Normal), 13, System.Windows.Media.Brushes.Black), new System.Windows.Point(50, 180));
    
                    dc.DrawGeometry(Brushes.Green, new Pen(Brushes.Gray, 2), new RectangleGeometry(new Rect(270, 110, 40, 100)));
    
                    dc.DrawEllipse(Brushes.Red, (System.Windows.Media.Pen)null, new Point(290, 90), 50, 50);
                    dc.DrawEllipse(Brushes.Blue, (System.Windows.Media.Pen)null, new Point(280, 85), 14, 18);
                    dc.DrawEllipse(Brushes.Blue, (System.Windows.Media.Pen)null, new Point(320, 85), 14, 18);
    
                    rect = new Rect(new System.Windows.Point(240, 50), new System.Windows.Size(100, 30));
                    dc.DrawRectangle(System.Windows.Media.Brushes.Black, (System.Windows.Media.Pen)null, rect);
    
                    dc.DrawLine(new Pen(Brushes.Black, 2), new Point(230, 140), new Point(350, 200));
                    dc.Close();
    
                    printDialog.PrintVisual(dv, "Print");
    
                    RenderTargetBitmap bmp = new RenderTargetBitmap(600, 350, 120, 96, PixelFormats.Pbgra32);
                    bmp.Render(dv);
                    Image img = new Image { Width = 100, Height = 100, Source = bmp, Stretch = Stretch.Fill };
    
                    Width = 500;
                    Height = 400;
    
                    var r = new Rectangle { Fill = new ImageBrush(bmp) };
                    r.SetValue(Grid.RowProperty, 1);
                    r.SetValue(Grid.ZIndexProperty, -1);
                    grid1.Children.Add(r);
                }
            }      
        }
    }
    


  8. コードの解説
    (1)using System.Globalization;は CultureInfoクラスを使用するのに必要です。
    (2)DataContext = this;は不要な記載です。
    (3)System.Windows.Controls.PrintDialog printDialog = new System.Windows.Controls.PrintDialog();でプリントダイアログを開きます。
    (4)if (printDialog.ShowDialog() == true)は印刷ボタンを押された場合、以下を実行します。
    (5)DrawingVisual dv = new DrawingVisual();は変数dvをDrawingVisual()型で生成します。
    (6)var dc = dv.RenderOpen();はDrawingVisual にレンダリングするために開きます。
    (7)dc.DrawRoundedRectangleは角丸四角形を描きます。
    (8)dc.DrawTextは文字を描きます。
    (9)dc.DrawGeometryは四角や楕円を描きます。
    (10)dc.Close();でレタリングを終了します。
    (11)printDialog.PrintVisual(dv, "Print");で印刷を実行します。
    (12)RenderTargetBitmap bmp = new RenderTargetBitmap(600, 350, 120, 96, PixelFormats.Pbgra32);以下のコードで図形をビットマップ形式に変換して、grid1に表示します。


    感想:
    (1)WPFの印刷機能は難解でまいりました。さまざまな機能があり、PDFファイルの置き換えとしてXPSファイルを位置づけているようです。
    (2)全てを理解しようとすると、かなり厄介そうですのでサンプルコード「WPF Printing Overvie1」を単純化して作成しました。
    (3)このサンプルでは、XAMLで作成した図形を全く利用していません。しかし、このほうがプログラム的には自由度が高く活用しやすいと思います。
    (4)XAMLで作成した図形の印刷方法については、42章で検討してみたいと思います。







42章:WPFでの印刷(2) (C#)に行く。

トップページに戻る。