概要
ユーザーからの要望で今年追加した機能。Formのスクリーンショットを取得する機能と組み合わせ、アプリのButtonクリックでスクリーンショットからプリントアウトまでを行っている。
- 自分でスクリーンショット取得からプリントアウトまで操作するのは手間である(または方法がわからない)
- 業務上、画面の状態をプリントアウトして回覧しないといけない
というのが要望の理由であった。
ソースコード
Imports System.Drawing.Printing
''' <summary>
''' プリントクラス
''' </summary>
Public Class Print
''' <summary>
''' A4サイズ横のピクセル数(100dpi)
''' </summary>
Private Const A4_PIXEL_W_100DPI As Integer = 826
''' <summary>
''' A4サイズ縦のピクセル数(100dpi)
''' </summary>
Private Const A4_PIXEL_H_100DPI As Integer = 1169
''' <summary>
''' A4サイズ
''' </summary>
Private ReadOnly A4 As New PaperSize("A4", A4_PIXEL_W_100DPI, A4_PIXEL_H_100DPI)
''' <summary>
''' 余白の割合
''' </summary>
''' <remarks>
''' 印刷時に端が見切れないように余白を設ける
''' 長辺の長さに対し、指定の割合だけ四方につける
''' </remarks>
Private Const MARGIN_RATE As Double = 0.025
''' <summary>
''' プリントするページ
''' </summary>
Private page As Bitmap = Nothing
''' <summary>
''' 横向きに印刷するかどうか True:横向きにする False:しない
''' </summary>
Private landscape As Boolean
''' <summary>
''' プリントイベント
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub pd_PrintPage(sender As Object, e As System.Drawing.Printing.PrintPageEventArgs)
' プリントする画像
Dim printBmp As Bitmap = New Bitmap(page, page.Width, page.Height)
' 縦横比は元のまま、印刷サイズに収まるようプリントする画像を拡大縮小する
Dim printRect As Rectangle = AdjustImageRectangle(A4, landscape, printBmp.Size)
e.Graphics.DrawImage(printBmp, printRect)
' プリントする画像を解放する
printBmp.Dispose()
End Sub
''' <summary>
''' プリント実行
''' </summary>
''' <param name="bitmap">プリントする画像</param>
Public Sub Execute(ByVal bitmap As Bitmap)
' プリントする画像
page = bitmap
' PrintDocumentオブジェクト作成
Dim printDocument As PrintDocument = New PrintDocument()
' PrintPageイベントハンドラ追加
AddHandler printDocument.PrintPage, AddressOf pd_PrintPage
' 横向きにする
landscape = True
printDocument.DefaultPageSettings.Landscape = landscape
' 出力サイズはA4のみ
printDocument.DefaultPageSettings.PaperSize = A4
' A4横サイズに縦横比を維持したまま画像が収まるサイズを計算する
' PrintControllerプロパティをStandardPrintControllerに
printDocument.PrintController = New System.Drawing.Printing.StandardPrintController
' PrintDialogクラスの作成
Dim printDialog As PrintDialog = New PrintDialog()
' PrintDocumentを指定
printDialog.Document = printDocument
' ダイアログを表示
If printDialog.ShowDialog() = DialogResult.OK Then
' OKボタン選択時に印刷
printDocument.Print()
End If
End Sub
''' <summary>
''' 画像サイズを調整する
''' </summary>
''' <param name="paperSize">用紙サイズ</param>
''' <param name="landScape">True:横向きが有効 False:無効</param>
''' <param name="size">画像サイズ</param>
''' <returns></returns>
''' <remarks>
''' 縦横比を維持したまま用紙に収まるよう拡大縮小する
''' 印刷時に端が切れることを考慮し、端に余白を設ける
''' </remarks>
Private Function AdjustImageRectangle(ByVal paperSize As PaperSize, ByVal landScape As Boolean, ByVal size As Size) As Rectangle
' 用紙のピクセル数
Dim paperWidth As Double
Dim paperHeight As Double
' 端に設ける余白のピクセル数
Dim margin As Double = 0.0
If landScape = False Then
' 縦向きの場合
paperWidth = CDbl(paperSize.Width)
paperHeight = CDbl(paperSize.Height)
margin = paperHeight * MARGIN_RATE
Else
' 横向きの場合
paperWidth = CDbl(paperSize.Height)
paperHeight = CDbl(paperSize.Width)
margin = paperWidth * MARGIN_RATE
End If
' 幅を基準にサイズを計算する
Dim rate As Double = paperWidth / CDbl(size.Width)
Dim destWidth As Double = paperWidth
Dim destHeight As Double = CDbl(size.Height) * rate
' 幅を基準に計算して高さ方向が収まらない場合、高さを基準にサイズを計算し直す
If paperHeight < destHeight Then
rate = paperHeight / CDbl(size.Height)
destWidth = CDbl(size.Width) * rate
destHeight = paperHeight
End If
' 描画開始オフセット
Dim offsetX As Double = (paperWidth - destWidth) / 2.0
Dim offsetY As Double = (paperHeight - destHeight) / 2.0
Return New Rectangle(CInt(offsetX) + margin, CInt(offsetY) + margin, CInt(destWidth) - margin * 2.0, CInt(destHeight) - margin * 2.0)
End Function
End Class
余談
プリントアウトしたものが回覧され、それをカメラ撮影し生成AIでテキスト化しているユーザーがいると後日発覚。最初にテキスト形式のエクスポート機能を用意すればよかった。