C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


(過去ログ 100 を表示中)
■59541 / )  下付文字を含んだ文字列の表示、印刷について。(再)
□投稿者/ mine (26回)-(2011/05/31(Tue) 07:52:18)

分類:[.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

返信 編集キー/


管理者用

- Child Tree -