2011/05/31(Tue) 22:55:00 編集(投稿者)
2011/05/31(Tue) 22:52:11 編集(投稿者)
いじってみました。コンボボックスを追加しPageUnitの選択を出来るようにしました。変化を確認してみて下さい。
worldは選ぶとエラーになります。inchはCX,CYを小さくしないと表示されないでしょう。Dispayの時の画面、プリンタの判断は
簡単な方法が分からなかったのでDpi値が150より小さければ画面としました。
tempPicへの描画は変になっているかもしれません。
Public Class Form1
Private Structure SpecTxt
Public Cont As String '制御文字
Public Str As String '文字列
Public StartX As Single 'startX位置
Public StartY As Single 'startY位置
Public Length As Single 'EndX位置
Public Offset As Single '下付き文字などの位置修正用
Public Width As Single '文字列の印字長さ
Public Height As Single '文字列の印字高さ
Public Font As Font
End Structure
Private S() As SpecTxt
Public CuX As Single '文字列の表示位置X
Public CuY As Single '文字列の表示位置X
Private flgShow As Boolean = False
Private Txt As String = "!s腐食代(外側)を除いた外径 = D!uo!s − 2 × α!uo"
Private fntReg As Font
Private fntSuffix As Font
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
fntReg = Label1.Font
fntSuffix = Label2.Font
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
CuX = 50.0!
CuY = 20.0!
ComboBox1.DataSource = [Enum].GetValues(GetType(GraphicsUnit))
End Sub
Private Function FontEm(ByVal FFont As Font, ByVal g As Graphics) As Single
Select Case g.PageUnit
Case GraphicsUnit.Display
If g.DpiX < 150 Then
FontEm = FFont.Size * g.DpiY / 72
Else
FontEm = FFont.Size * 100 / 72
End If
Case GraphicsUnit.Pixel
FontEm = FFont.Size * g.DpiY / 72
Case GraphicsUnit.Point
FontEm = FFont.Size
Case GraphicsUnit.Inch
FontEm = FFont.Size / 72
Case GraphicsUnit.Document
FontEm = FFont.Size * 300 / 72
Case GraphicsUnit.Millimeter
FontEm = FFont.Size / 72 * 25.4!
Case Else
FontEm = FFont.Size * g.DpiY / 72
End Select
End Function
' Function Str
' Txtを"!"で分割しそれぞれの文字列のPropertyをS()として返す。
' S()の次元はRegionMaxである。
Private Function Str(ByVal Txt As String, ByRef RegionMax As Integer, ByVal g As Graphics) 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 = fntReg
S(i).Offset = 0
Case "t"
S(i).Font = fntSuffix
'S(i).Offset = -15
'S(i).Offset = -8
S(i).Offset = -FontEm(fntReg, g) * 0.6
Case "u"
S(i).Font = fntSuffix
'S(i).Offset = 17
'S(i).Offset = 14
S(i).Offset = FontEm(fntReg, g) * 0.6
End Select
Next
Return S
End Function
'************************************************************
' DrawFormula
' PictureBox1,PrintDocument1への描画コード
'************************************************************
Private Sub DrawFormula(ByVal Txt As String, ByVal CuX As Single, ByVal CuY As Single, ByVal g As Graphics)
Dim RegionMax As Integer 'Regionの最大数
Dim i As Integer
Dim sf As New StringFormat
'Txtを制御文字列"!"で分割しSにいれる。
S = Str(Txt, RegionMax, g)
Dim gt As Graphics = tempPic.CreateGraphics
Dim stringRegions As Region()
Dim rect(0) As RectangleF
gt.PageUnit = g.PageUnit
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)
stringRegions = g.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 = rect(0).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 Then
e.Graphics.PageUnit = ComboBox1.SelectedValue
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 Then
e.Graphics.PageUnit = ComboBox1.SelectedValue
DrawFormula(Txt, CuX, CuY, e.Graphics) '(e.Graphics)とすることが必要、(e)ではErrorとなる。
End If
e.HasMorePages = False
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
flgShow = True
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
End Class