|
分類:[.NET 全般]
以前に同じ内容の質問をさせて頂きましたところ多くの方から有益なご指導を頂き表示については全く問題なくできるようになったのですが、
Previewや印刷をさせると下付文字の位置がずれてしまうのです。
Form1にtempPic, PictureBox1, cmdHyouzi1, cmdPreview, cmdPint, PritPreviewDialog1, PrintDocument1を貼り付けcmdHyouzi,をClickすると
PictureBox1に文字列が表示され、cmdPreview,をClickするとPreviewが、cmdPint,をClickすると印刷が行はれるようにしています。
全Codeを次に記載しましたがなぜPictureBox1への表示とPreview、印刷とで狂いがでるのでしょうか?
何方か是非お教え下さい。 よろしくお願い申し上げます。
Module Module1
Public Structure SpecTxt
Public Cont As String '制御文字
Public Str As String '文字列
Public StartX As Integer 'startX位置
Public StartY As Integer 'startY位置
Public Length As Integer 'EndX位置
Public Offset As Integer '下付き文字などの位置修正用
Public Width As Integer '文字列の印字長さ
Public Height As Integer '文字列の印字高さ
Public Font As Font
End Structure
Public S() As SpecTxt
Public CuX As Integer '文字列の表示位置X
Public CuY As Integer '文字列の表示位置X
End Module
Public Class Form1
Dim flgShow As Boolean = False
Dim Txt As String = "!s腐食代(外側)を除いた外径 = D!uo!s − 2 × α!uo"
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
CuX = 50
CuY = 20
End Sub
Private Function FontEm(ByVal FFont As Font) As Single
FontEm = FFont.Size * 96 / 72
End Function
' Function StrWidth
' strのFFontで表示した場合のWidthを返す。
Private Function StrWidth(ByVal str As String, ByVal FFont As Font) As Integer
Dim tg As Graphics = tempPic.CreateGraphics()
Dim sf As New StringFormat
Dim stringRegions As Region()
'tempPic.Visible = False
Dim gt As Graphics = tempPic.CreateGraphics
'文字列を描画する
tg.DrawString(str, FFont, Brushes.Black, 0, 0, sf)
Dim characterRanges(0) As CharacterRange
characterRanges(0) = New CharacterRange(0, str.Length)
sf.SetMeasurableCharacterRanges(characterRanges)
'文字列のレイアウト四角形を指定する
Dim layoutRect As New RectangleF(0, 0, 3000, 100)
'文字列に外接するRegion配列を取得する()
stringRegions = tg.MeasureCharacterRanges(str, FFont, layoutRect, sf)
'取得した文字列の大きさを使って四角を描画する()
Dim rect(0) As RectangleF
rect(0) = stringRegions(0).GetBounds(tg)
tg.DrawRectangle(Pens.Blue, Rectangle.Round(rect(0)))
Debug.Print(Rectangle.Round(rect(0)).Size.Width)
'Return Rectangle.Round(rect(0)).Size.Width
Return CInt(Rectangle.Round(rect(0)).Size.Width * 1.05)
End Function
' Function Str
' Txtを"!"で分割しそれぞれの文字列のPropertyをS()として返す。
' S()の次元はRegionMaxである。
Private Function Str(ByVal Txt As String, ByRef RegionMax As Integer) As SpecTxt()
'計測する文字の範囲を指定する
Dim ContCountMax As Integer '"!"の数
'Dim RegionMax As Integer 'Regionの最大数
Dim i As Integer
Dim StrTwCont() As String
'Txtを制御文字列"!"で分割しStrTwContにいれる。
'Splitでは最初の"!"より前の文字列がStrTwCont(0)に入るがこれは常に""なので要注意
StrTwCont = Txt.Split(CChar("!"))
ContCountMax = UBound(StrTwCont)
RegionMax = ContCountMax - 1
ReDim S(RegionMax)
'分割様文字はCCharでCharcterに変換しておかないとErrorとな
For i = 0 To RegionMax
S(i).Cont = Mid(StrTwCont(i + 1), 1, 1)
S(i).Str = Mid(StrTwCont(i + 1), 2, StrTwCont(i + 1).Length - 1)
'S(i).StartX = 1
S(i).Length = StrTwCont(i + 1).Length
Select Case S(i).Cont
Case "s"
S(i).Font = fontReg
S(i).Offset = 0
Case "t"
S(i).Font = fontSuffix
'S(i).Offset = -15
'S(i).Offset = -8
S(i).Offset = -FontEm(fontReg) * 0.6
Case "u"
S(i).Font = fontSuffix
'S(i).Offset = 17
'S(i).Offset = 14
S(i).Offset = FontEm(fontReg) * 0.6
End Select
Next
Return S
End Function
'************************************************************
' DrawFormula
' PictureBox1,PrintDocument1への描画コード
'************************************************************
Private Sub DrawFormula(ByVal Txt As String, ByVal CuX As Integer, ByVal CuY As Integer, ByVal g As Graphics)
Dim RegionMax As Integer 'Regionの最大数
Dim i As Integer
Dim sf As New StringFormat
'Txtを制御文字列"!"で分割しSにいれる。
S = Str(Txt, RegionMax)
Dim gt As Graphics = tempPic.CreateGraphics
Dim stringRegions As Region()
Dim rect(0) As RectangleF
ReDim StartX(RegionMax)
For i = 0 To RegionMax
'各文字列の表示幅を求める
gt.DrawString(S(i).Str, S(i).Font, Brushes.Black, 0, i * 20, sf)
Dim characterRanges(0) As CharacterRange
characterRanges(0) = New CharacterRange(0, S(i).Str.Length)
sf.SetMeasurableCharacterRanges(characterRanges)
'文字列のレイアウト四角形を指定する
Dim layoutRect As New RectangleF(0, i * 20, 3000, 100)
'文字列に外接するRegion配列を取得する()
stringRegions = gt.MeasureCharacterRanges(S(i).Str, S(i).Font, layoutRect, sf)
'取得した文字列の大きさを使って四角を描画する()
rect(0) = stringRegions(0).GetBounds(g)
gt.DrawRectangle(Pens.Blue, Rectangle.Round(rect(0)))
'Debug.Print(Rectangle.Round(rect(0)).Size.Width)
S(i).Width = Rectangle.Round(rect(0)).Size.Width
'各文字列の表示start位置を求める
If i = 0 Then
S(0).StartX = CuX
Else
S(i).StartX = S(i - 1).StartX + S(i - 1).Width
Debug.Print("S(" & i & ").StartX) = " & "S(" & i - 1 & ").StartX" & " + S(" & i - 1 & ").Width = " & _
S(i - 1).StartX & " + " & S(i - 1).Width & " = " & S(i - 1).StartX + S(i - 1).Width)
End If
'各文字列の表示
g.DrawString(S(i).Str, S(i).Font, Brushes.Black, S(i).StartX, CuY + S(i).Offset, sf)
Next
End Sub
' PictureBox1への描画
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) _
Handles PictureBox1.Paint
If flgShow = True Then
Call DrawFormula(Txt, CuX, CuY, e.Graphics)
End If
End Sub
Private Sub PrintDocument1_printpage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
If flgShow = True Then
Call DrawFormula(Txt, CuX, CuY, e.Graphics) '(e.Graphics)とすることが必要、(e)ではErrorとなる。
End If
End Sub
Private Sub cmdHyouzi_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdHyouzi.Click
flgShow = True
PictureBox1.Invalidate()
End Sub
Private Sub cmdPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPreview.Click
Dim RectWorking As Rectangle
RectWorking = Screen.PrimaryScreen.WorkingArea
Debug.Print("RectWorking.Width, height = " & RectWorking.Width & ", " & RectWorking.Height)
PrintPreviewDialog1.Width = 750
PrintPreviewDialog1.Height = 900
PrintPreviewDialog1.Top = 0
PrintPreviewDialog1.Left = CInt((RectWorking.Width - PrintPreviewDialog1.Width) / 2)
PrintPreviewDialog1.Document = PrintDocument1
PrintPreviewDialog1.ShowDialog()
End Sub
Private Sub cmdPicPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPicPrint.Click
Call PrintDocument1.Print()
End Sub
End Class
|