各種印刷

<B>
<font COLOR="blue" >
・----------------------------------------------------------------------・<BR>
・印刷に関連するコードです。<BR>
・Windowsは96DPI。<a href="https://ascii.jp/elem/000/004/038/4038068/">詳しくはこの辺を参照。</A><BR>
・実務でほぼそのまま使える実用的なコードになっています。<BR>
・----------------------------------------------------------------------・<BR>
</B>

::: note info
・LI == x:name LISTBOX
・必要な参照設定　ReachFramework　System.Printing　system.drawing 
:::

<FONT COLOR="BLUE">

###   1.規定のプリンタの情報表示、登録されているPRN一覧

</FONT>

```c#
// inf102 2023.
using System;
using System.Printing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Xps;
using FontFamily = System.Windows.Media.FontFamily;

public void msg(string st){
    MessageBox.Show (st);
}
        
// 既定のPRNのデータ表示
System.Drawing.Printing.PrintDocument pd=null;

try {
    pd = new System.Drawing.Printing.PrintDocument();
}
catch(Exception ex) {
    msg ("規定のプリンタ設定がされていません.");
    msg (ex.ToString ());
}

L1.Items.Add("既定のPRN.... " + pd.PrinterSettings.PrinterName);

// 登録されているPRN一覧
L1.Items.Add ("登録されているPRNは下記の通りです....");
foreach (string s in System.Drawing.Printing.PrinterSettings.InstalledPrinters){
    L1.Items.Add(s);

}
```

<FONT COLOR="BLUE">

### 2.PRN詳細情報
</FONT>

ダイアログが出るのでPRN選択して印刷ボタン
```c#
private void Button_Click_7(object sender, RoutedEventArgs e) {

    L1.Items.Add("-----------------------------------");

    var printDialog = new PrintDialog();
    var result = printDialog.ShowDialog();

    var queue = printDialog.PrintQueue;
    var writer = PrintQueue.CreateXpsDocumentWriter(queue);
            
    L1.Items.Add ("選択PRN..... " + printDialog.PrintQueue.FullName.ToString());
    // ダイアログで用紙の縦、横取得。　area.ExtentWidth　area.ExtentHeight　でわかる
    var area = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket).PageImageableArea;
            
    L1.Items.Add ("両面印刷.... " + printDialog.PrintTicket.Duplexing.ToString());
    L1.Items.Add ("原稿ｻｲｽﾞ.... " + printDialog.PrintTicket.PageMediaSize.ToString());
           
    // 用紙方向 専用プロパティがあるかも知れないが分からなかったので判定
    if (area.ExtentWidth < area.ExtentHeight) {
        L1.Items.Add ("原稿方向.... 縦方向");
    }
    else L1.Items.Add ("原稿方向.... 横方向");
            
    L1.Items.Add ("使用可能.... 幅(PX)" + area.ExtentWidth.ToString() + " 高" + area.ExtentHeight.ToString());
    L1.Items.Add ("用紙余白.... 幅(PX)" + area.OriginWidth.ToString() + " 高" + area.OriginHeight.ToString());
    L1.Items.Add ("印刷枚数.... " + printDialog.PrintTicket.CopyCount.ToString());
    L1.Items.Add ("余白mm計算方法...A4 幅210mm -> 210/用紙情報(幅PX)=X -> 余白PX*X=余白mm");
    
}
```
出力例
![B - コピー (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/9d7fc766-83b3-a55d-2c2b-212963fea1a5.jpeg)

往復ハガキに設定して印刷ボタンを押すと、用紙がJapanDoubleHagakiPostcardRotated と出て面白いです。


<FONT COLOR="BLUE">

### 3.自身の画面(Grid)を印刷する (アプリ画面のハードコピー)

</FONT>



(自分のアプリ、画面自体を印刷したい場合。該当のGridのx:nameを指定)
WinFormsでやってた事がなかなかできず難儀してたところ、Gridの指定だけでできました。
スケールトランスフォームメソッドで好きなように大きさ可変可能。
```c#
// XAML印刷   G1 == XAML x:name
private void Button_Click_4(object sender, RoutedEventArgs e) {
    
    // 印刷にあたり調整(用紙からはみ出る場合等)
    var tfg = new TransformGroup();
    tfg.Children.Add(new ScaleTransform(0.55,0.55));  // 縮小　拡大  0.55=55%　
    tfg.Children.Add(new TranslateTransform(30, 20)); // 位置
    G1.RenderTransform = tfg;
        
    // 既定のPRN
    PrintDialog printDialog = new PrintDialog();
    printDialog.PrintTicket.PageOrientation=System.Printing.PageOrientation.Landscape;
    printDialog.PrintTicket.PageMediaSize = new System.Printing.PageMediaSize(System.Printing.PageMediaSizeName.ISOA4);
            
            
    if (MessageBox.Show("印刷します..", "印刷機能検証", MessageBoxButton.OKCancel) == MessageBoxResult.OK){

        printDialog.PrintVisual(G1, "WPF_TEST");
    }

    // 元の大きさへ 
    var tfg2 = new TransformGroup();
    tfg2.Children.Add(new ScaleTransform(1.00,1.0));
    tfg2.Children.Add(new TranslateTransform(0, 0));
    G1.RenderTransform = tfg2;
}

//XAML 
    <Grid x:Name="G1" >
        <Grid.RowDefinitions>
            <RowDefinition Height="2"/>
            <RowDefinition Height="37"/>
            <RowDefinition Height="37"/>
            
```

<FONT COLOR="BLUE">

### 4.既定のPRNで片面印刷 

</FONT>

用紙サイズなどはここで個別に指定したものが優先される。
DBから必要データをSELECTしてここに作り混むと院外処方箋や給料明細等が出来る。
業務アプリで一番使用頻度が高いと思われる。
適当にウィンドウ作ってそちらにも同じ印字データを書き込めばプレビュー画面が出来ます。

```c#
private void  Button_Click_1(object sender, RoutedEventArgs e) {

    // 1.通常使用するプリンタ取得
    LocalPrintServer lps = new LocalPrintServer();
    PrintQueue queue = lps.DefaultPrintQueue;
    XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(queue);

    // 2. 用紙の設定 //////////////////////////////
    PrintTicket ticket = queue.DefaultPrintTicket;
    ticket.PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4);
    ticket.PageOrientation = PageOrientation.Portrait;

    // Landscape    	1 イメージ可能領域の内容は、ページ上で標準 (縦) 方向から反時計回りに 90 度回転されます。
    // Portrait	        2 標準方向。
    // ReverseLandscape	3 イメージ可能領域の内容は、ページ上で標準 (縦) 方向から時計回りに 90 度回転されます。
    // ReversePortrait	4 イメージ可能領域の内容は、標準 (縦) 方向に対して逆向き
    /////////////////////////////////////////////
           
    // 3. FixedPage の生成
    FixedPage page = new FixedPage();
    
    // 4. 印字データの書き込み先の生成
    Canvas canvas = new Canvas();
    ///////////////////////////////////////////////////////////////

    TextBlock tb1 = new TextBlock();
    TextBlock tb2 = new TextBlock();
    //////////////////////////////////////////////////////////////
    tb1.Text = "WPF テスト印刷";
    tb1.FontFamily = new FontFamily("ＭＳ Ｐゴシック");
    tb1.FontSize = 46;
    Canvas.SetTop(tb1, 105);
    Canvas.SetLeft(tb1, 150);
    canvas.Children.Add(tb1);
               
    /////////////////////////////////////////////////////////////
    tb2.Text = "試験";
    tb2.FontFamily = new FontFamily("ＭＳ Ｐゴシック");
    tb2.FontSize = 16;
    Canvas.SetTop(tb2, 125);
    Canvas.SetLeft(tb2, 150);
        
    canvas.Children.Add(tb2);
    /////////////////////////////////////////////////////////////

    /* 
    using (Stream ticketstream = File.Create("C:\\A.XML")){
        ticket.SaveTo(ticketstream);
    }
    */
    
    // 5. 印字データをページに追加
    page.Children.Add(canvas);

    // 6. 印刷実行
    if (MessageBox.Show("印刷します..", "WPF_TEST", MessageBoxButton.OKCancel) == MessageBoxResult.OK){
        writer.Write(page, ticket);

    }

}
```

<FONT COLOR="BLUE">

### 5.両面印刷
</FONT>


1.new Canvas()で表裏用のキャンバスを二つ作り、 
2.Children.Add()で印刷物(コントロール等)を追加、new FixedPage()でページを作る。
3.そのページに対して先に作ったキャンパスを追加。
4.new PageContent()でPageContentを作り、それにFixedPageのデータを指定。 
5.new FixedDocument()で印刷データの入れ物を作成してそれに対してPageContentで入れたデータを追加。
6.最後に印刷ダイアログのPrintDocument()メソッドで印刷掛けます。袋とじ、印刷方向等もPRNダイアログの指定に従いPRNドライバがうまくやってくれます。

つまり、両面のデータのまとまり(FixedDocument)を作り一度にプリンタに送ります。そうでないと表面印刷が終わると排出されてしまい裏面の印刷ができません。