トップ回答者
PDFsharpで日本語が表示できない

質問
回答
-
色々いじくってみましたがPDFSharpだとフォントがまともに扱えなさそうなので、PDFプリンタであるMicrosoft Print To PDFで印刷して、ファイルに出力をさせた方が楽かもしれない
Imports System Imports System.Collections.Generic Imports System.Linq Imports System.Drawing.Imaging Imports System.Drawing.Printing Imports System.IO Imports Microsoft.Ink Public Class Form1 Sub New() InitializeComponent() End Sub Private Sub PrintButton1_Click(sender As Object, e As EventArgs) Handles PrintButton1.Click Dim pdfPrinterName As String = PrinterSettings.InstalledPrinters.OfType(Of String)().FirstOrDefault(Function(s) s.Equals("Microsoft Print to PDF", StringComparison.OrdinalIgnoreCase)) If String.IsNullOrWhiteSpace(pdfPrinterName) Then MessageBox.Show("Microsoft Print to PDFが見つかりませんでした") Exit Sub End If Dim doc As New PrintDocument() doc.PrintController = New System.Drawing.Printing.StandardPrintController() doc.PrinterSettings.PrinterName = pdfPrinterName doc.PrinterSettings.PrintToFile = True 'ファイルに出力するように doc.PrinterSettings.PrintFileName = DateTime.Now.ToString("yyyyMMddHHmmss") & ".pdf" AddHandler doc.PrintPage, AddressOf OnPrintPage doc.Print() End Sub ''' <summary>ページに印刷する内容を描画</summary> Private Sub OnPrintPage(s As Object, e As PrintPageEventArgs) Dim offsetX As Integer = 10 Dim offsetY As Integer = 10 For Each tabPage As TabPage In Me.TabControl1.TabPages If tabPage.Width = 0 OrElse tabPage.Height = 0 Then Continue For End If e.Graphics.ResetClip() e.Graphics.DrawRectangle(Pens.Black, offsetX, offsetY, tabPage.Width, tabPage.Height) For Each pbox As PictureBox In tabPage.Controls.OfType(Of PictureBox) If pbox.GetType() = GetType(PictureBox) Then PrintImage(e, offsetX, offsetY, tabPage, pbox) ElseIf TypeOf pbox Is InkPicture Then 'InkPictureはPictureBoxを継承している PrintImage(e, offsetX, offsetY, tabPage, pbox) Else 'PictureBoxを継承している何か End If Next e.Graphics.ResetClip() Dim lcid = System.Globalization.CultureInfo.GetCultureInfo("ja-jp").LCID Dim ff As FontFamily = FontFamily.Families.FirstOrDefault(Function(f) f.GetName(lcid) = "MS ゴシック") Dim font As Font = New Font(ff, 20, FontStyle.Regular) e.Graphics.DrawString("ページ" + tabPage.Text, font, Brushes.Red, New PointF(tabPage.Width + 10, offsetY)) offsetY += tabPage.Height If offsetY >= e.PageBounds.Height Then Exit For End If Next e.HasMorePages = False End Sub Private Sub PrintImage(e As PrintPageEventArgs, offsetX As Double, offsetY As Double, tabPage As TabPage, pbox As PictureBox) Dim img As Image = pbox.Image If img IsNot Nothing Then '画像が指定してあるなら画像を印刷 PrintImage(e, tabPage, offsetX, offsetY, pbox, pbox.Image, pbox.SizeMode) End If If TypeOf pbox Is InkPicture Then 'InkPictureの場合 Dim ip As InkPicture = CType(pbox, InkPicture) If ip.Ink.Strokes.Count > 0 Then 'PictureBoxのImageの上に重ね描きされるストロークを画像に Dim gifData As Byte() = ip.Ink.Save(PersistenceFormat.Gif, CompressionMode.NoCompression) Dim ms As New System.IO.MemoryStream(gifData) Dim gif = System.Drawing.Image.FromStream(ms) 'PictureBoxの大きさのBitmapにストロークを描画しなおし Dim bmp = New Bitmap(pbox.Width, pbox.Height, PixelFormat.Format32bppArgb) Using g As Graphics = Graphics.FromImage(bmp) Dim bound = ip.Ink.GetBoundingBox() g.DrawImage(gif, New PointF(bound.X / 25.4, bound.Y / 25.4)) End Using 'ストローク画像を印刷させる PrintImage(e, tabPage, offsetX, offsetY, pbox, bmp, PictureBoxSizeMode.Normal) End If End If End Sub Private Sub PrintImage(e As PrintPageEventArgs, tabPage As TabPage, offsetX As Double, offsetY As Double, pbox As PictureBox, img As Image, sizeMode As PictureBoxSizeMode) If pbox.Width = 0 OrElse pbox.Height = 0 OrElse img Is Nothing OrElse img.Width = 0 OrElse img.Height = 0 Then Exit Sub End If Dim rectClip As Rectangle '用紙上の描画可能な範囲 Dim rectPrint As Rectangle 'Imageを描画する範囲 Dim rectImage As Rectangle = New Rectangle(0, 0, img.Width, img.Height) 'Imageから切り出す範囲 rectPrint = New Rectangle(pbox.Left, pbox.Top, pbox.Width, pbox.Height) rectClip = New Rectangle(0, 0, tabPage.Width, tabPage.Height) rectClip.Intersect(rectPrint) 'PictureBoxのモードによって異なる表示され方を変換 Select Case sizeMode Case PictureBoxSizeMode.AutoSize rectPrint = New Rectangle(pbox.Left, pbox.Top, img.Width, img.Height) Case PictureBoxSizeMode.Normal rectPrint = New Rectangle(pbox.Left, pbox.Top, img.Width, img.Height) Case PictureBoxSizeMode.StretchImage rectPrint = New Rectangle(pbox.Left, pbox.Top, pbox.Width, pbox.Height) Case PictureBoxSizeMode.CenterImage rectPrint = New Rectangle(pbox.Left + pbox.Width / 2 - img.Width / 2, pbox.Top + pbox.Height / 2 - img.Height / 2, img.Width, img.Height) Case PictureBoxSizeMode.Zoom Dim centerX As Single = pbox.Left + pbox.Width / 2 Dim centerY As Single = pbox.Top + pbox.Height / 2 Dim scale As Single If (img.Height / img.Width) < (pbox.Height / pbox.Width) Then scale = pbox.Width / img.Width Else scale = pbox.Height / img.Height End If rectPrint = New Rectangle(centerX - img.Width * scale, centerY - img.Height * scale, img.Width * scale, img.Height * scale) End Select rectClip.Offset(offsetX, offsetY) rectPrint.Offset(offsetX, offsetY) e.Graphics.SetClip(rectClip) e.Graphics.DrawImage(img, rectPrint, rectImage, GraphicsUnit.Pixel) End Sub End Class
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク 9638masa 2023年4月1日 4:51
すべての返信
-
色々いじくってみましたがPDFSharpだとフォントがまともに扱えなさそうなので、PDFプリンタであるMicrosoft Print To PDFで印刷して、ファイルに出力をさせた方が楽かもしれない
Imports System Imports System.Collections.Generic Imports System.Linq Imports System.Drawing.Imaging Imports System.Drawing.Printing Imports System.IO Imports Microsoft.Ink Public Class Form1 Sub New() InitializeComponent() End Sub Private Sub PrintButton1_Click(sender As Object, e As EventArgs) Handles PrintButton1.Click Dim pdfPrinterName As String = PrinterSettings.InstalledPrinters.OfType(Of String)().FirstOrDefault(Function(s) s.Equals("Microsoft Print to PDF", StringComparison.OrdinalIgnoreCase)) If String.IsNullOrWhiteSpace(pdfPrinterName) Then MessageBox.Show("Microsoft Print to PDFが見つかりませんでした") Exit Sub End If Dim doc As New PrintDocument() doc.PrintController = New System.Drawing.Printing.StandardPrintController() doc.PrinterSettings.PrinterName = pdfPrinterName doc.PrinterSettings.PrintToFile = True 'ファイルに出力するように doc.PrinterSettings.PrintFileName = DateTime.Now.ToString("yyyyMMddHHmmss") & ".pdf" AddHandler doc.PrintPage, AddressOf OnPrintPage doc.Print() End Sub ''' <summary>ページに印刷する内容を描画</summary> Private Sub OnPrintPage(s As Object, e As PrintPageEventArgs) Dim offsetX As Integer = 10 Dim offsetY As Integer = 10 For Each tabPage As TabPage In Me.TabControl1.TabPages If tabPage.Width = 0 OrElse tabPage.Height = 0 Then Continue For End If e.Graphics.ResetClip() e.Graphics.DrawRectangle(Pens.Black, offsetX, offsetY, tabPage.Width, tabPage.Height) For Each pbox As PictureBox In tabPage.Controls.OfType(Of PictureBox) If pbox.GetType() = GetType(PictureBox) Then PrintImage(e, offsetX, offsetY, tabPage, pbox) ElseIf TypeOf pbox Is InkPicture Then 'InkPictureはPictureBoxを継承している PrintImage(e, offsetX, offsetY, tabPage, pbox) Else 'PictureBoxを継承している何か End If Next e.Graphics.ResetClip() Dim lcid = System.Globalization.CultureInfo.GetCultureInfo("ja-jp").LCID Dim ff As FontFamily = FontFamily.Families.FirstOrDefault(Function(f) f.GetName(lcid) = "MS ゴシック") Dim font As Font = New Font(ff, 20, FontStyle.Regular) e.Graphics.DrawString("ページ" + tabPage.Text, font, Brushes.Red, New PointF(tabPage.Width + 10, offsetY)) offsetY += tabPage.Height If offsetY >= e.PageBounds.Height Then Exit For End If Next e.HasMorePages = False End Sub Private Sub PrintImage(e As PrintPageEventArgs, offsetX As Double, offsetY As Double, tabPage As TabPage, pbox As PictureBox) Dim img As Image = pbox.Image If img IsNot Nothing Then '画像が指定してあるなら画像を印刷 PrintImage(e, tabPage, offsetX, offsetY, pbox, pbox.Image, pbox.SizeMode) End If If TypeOf pbox Is InkPicture Then 'InkPictureの場合 Dim ip As InkPicture = CType(pbox, InkPicture) If ip.Ink.Strokes.Count > 0 Then 'PictureBoxのImageの上に重ね描きされるストロークを画像に Dim gifData As Byte() = ip.Ink.Save(PersistenceFormat.Gif, CompressionMode.NoCompression) Dim ms As New System.IO.MemoryStream(gifData) Dim gif = System.Drawing.Image.FromStream(ms) 'PictureBoxの大きさのBitmapにストロークを描画しなおし Dim bmp = New Bitmap(pbox.Width, pbox.Height, PixelFormat.Format32bppArgb) Using g As Graphics = Graphics.FromImage(bmp) Dim bound = ip.Ink.GetBoundingBox() g.DrawImage(gif, New PointF(bound.X / 25.4, bound.Y / 25.4)) End Using 'ストローク画像を印刷させる PrintImage(e, tabPage, offsetX, offsetY, pbox, bmp, PictureBoxSizeMode.Normal) End If End If End Sub Private Sub PrintImage(e As PrintPageEventArgs, tabPage As TabPage, offsetX As Double, offsetY As Double, pbox As PictureBox, img As Image, sizeMode As PictureBoxSizeMode) If pbox.Width = 0 OrElse pbox.Height = 0 OrElse img Is Nothing OrElse img.Width = 0 OrElse img.Height = 0 Then Exit Sub End If Dim rectClip As Rectangle '用紙上の描画可能な範囲 Dim rectPrint As Rectangle 'Imageを描画する範囲 Dim rectImage As Rectangle = New Rectangle(0, 0, img.Width, img.Height) 'Imageから切り出す範囲 rectPrint = New Rectangle(pbox.Left, pbox.Top, pbox.Width, pbox.Height) rectClip = New Rectangle(0, 0, tabPage.Width, tabPage.Height) rectClip.Intersect(rectPrint) 'PictureBoxのモードによって異なる表示され方を変換 Select Case sizeMode Case PictureBoxSizeMode.AutoSize rectPrint = New Rectangle(pbox.Left, pbox.Top, img.Width, img.Height) Case PictureBoxSizeMode.Normal rectPrint = New Rectangle(pbox.Left, pbox.Top, img.Width, img.Height) Case PictureBoxSizeMode.StretchImage rectPrint = New Rectangle(pbox.Left, pbox.Top, pbox.Width, pbox.Height) Case PictureBoxSizeMode.CenterImage rectPrint = New Rectangle(pbox.Left + pbox.Width / 2 - img.Width / 2, pbox.Top + pbox.Height / 2 - img.Height / 2, img.Width, img.Height) Case PictureBoxSizeMode.Zoom Dim centerX As Single = pbox.Left + pbox.Width / 2 Dim centerY As Single = pbox.Top + pbox.Height / 2 Dim scale As Single If (img.Height / img.Width) < (pbox.Height / pbox.Width) Then scale = pbox.Width / img.Width Else scale = pbox.Height / img.Height End If rectPrint = New Rectangle(centerX - img.Width * scale, centerY - img.Height * scale, img.Width * scale, img.Height * scale) End Select rectClip.Offset(offsetX, offsetY) rectPrint.Offset(offsetX, offsetY) e.Graphics.SetClip(rectClip) e.Graphics.DrawImage(img, rectPrint, rectImage, GraphicsUnit.Pixel) End Sub End Class
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク 9638masa 2023年4月1日 4:51