GDI+绘制自定义行距的文本(续)
2010-04-22 09:14
309 查看
在上文“GDI+绘制自定义行距的文本的三种方法。”中,介绍了绘制自定义行间距的多行文本的方法。
在第三种的方法中,启用了GdipDrawDriverString这个函数。这个函数可以定义每个字符的位置,这是它的优点。不过它的缺点也比较明显。一是它定义的字符位置是以字符的左下角为基准的,和一般的概念是两样的。二是他对Font要求比较高,据说如果采用的是英文字体,在显示中文时会显示成一个个小方块。
再翻翻GDIP中的其他函数,发现graphics的DrawString的方法都是调用GdipDrawString这个函数。如果我们能跳过graphics直接调用GdipDrawString这个函数,是不是能提高效率呢?我们试试看。
<DllImport("gdiplus.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)> _
Friend Shared Function GdipDrawString(ByVal graphics As IntPtr, _
ByVal textString As String, _
ByVal length As Integer, _
ByVal font As IntPtr, _
ByRef layoutRect As GPRECTF, _
ByVal stringFormat As IntPtr, _
ByVal brush As IntPtr) As Integer
End Function
<StructLayout(LayoutKind.Sequential)> _
Friend Structure GPRECTF
Friend X As Single
Friend Y As Single
Friend Width As Single
Friend Height As Single
Friend Sub New(ByVal x As Single, ByVal y As Single, ByVal width As Single, ByVal height As Single)
Me.X = x
Me.Y = y
Me.Width = width
Me.Height = height
End Sub
Friend Sub New(ByVal rect As RectangleF)
Me.X = rect.X
Me.Y = rect.Y
Me.Width = rect.Width
Me.Height = rect.Height
End Sub
Friend ReadOnly Property SizeF() As SizeF
Get
Return New SizeF(Me.Width, Me.Height)
End Get
End Property
Friend Function ToRectangleF() As RectangleF
Return New RectangleF(Me.X, Me.Y, Me.Width, Me.Height)
End Function
End Structure
Public Sub Draw4(ByVal Text As String)
Clear()
Dim i As Integer, j As Integer, tS() As String
j = Int(Text.Length / 52)
ReDim tS(j - 1)
For i = 0 To j - 1
tS(i) = Text.Substring(i * 52, 52)
Next
If Text.Length - j * 52 <> 0 Then
ReDim Preserve tS(j+1)
tS(j+1) = Text.Substring(j * 52)
End If
DrawLineText(mG, tS, mFont, New SolidBrush(mForeColor))
End Sub
Private Sub DrawLineText(ByVal G As Graphics, ByVal T() As String, ByVal F As Font, ByVal B As Brush)
If (G Is Nothing) Then Throw New ArgumentNullException("graphics")
If (T Is Nothing) Then Throw New ArgumentNullException("text")
If (F Is Nothing) Then Throw New ArgumentNullException("font")
If (B Is Nothing) Then Throw New ArgumentNullException("brush")
Dim Field As FieldInfo
Field = GetType(Graphics).GetField("nativeGraphics", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim hGraphics As IntPtr = Field.GetValue(G)
Field = GetType(Font).GetField("nativeFont", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim hFont As IntPtr = Field.GetValue(F)
Field = GetType(Brush).GetField("nativeBrush", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim hBrush As IntPtr = Field.GetValue(B)
Dim i As Integer, tR As GPRECTF
tR = New GPRECTF(0, 0, mBmp.Width, mBmp.Height)
For i = 0 To 17
tR.X = 3
tR.Y = 3 + i * mLineHeight
GdipDrawString(hGraphics, T(i), T(i).Length, hFont, tR, IntPtr.Zero, hBrush)
Next
End Sub
经测试,方法四和方法三的效率不相上下。但是,方法四更接近我们直观的想法,而且对Font的要求也不是很高。
可能还有更好的方法,欢迎各位网友交流。
在第三种的方法中,启用了GdipDrawDriverString这个函数。这个函数可以定义每个字符的位置,这是它的优点。不过它的缺点也比较明显。一是它定义的字符位置是以字符的左下角为基准的,和一般的概念是两样的。二是他对Font要求比较高,据说如果采用的是英文字体,在显示中文时会显示成一个个小方块。
再翻翻GDIP中的其他函数,发现graphics的DrawString的方法都是调用GdipDrawString这个函数。如果我们能跳过graphics直接调用GdipDrawString这个函数,是不是能提高效率呢?我们试试看。
<DllImport("gdiplus.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)> _
Friend Shared Function GdipDrawString(ByVal graphics As IntPtr, _
ByVal textString As String, _
ByVal length As Integer, _
ByVal font As IntPtr, _
ByRef layoutRect As GPRECTF, _
ByVal stringFormat As IntPtr, _
ByVal brush As IntPtr) As Integer
End Function
<StructLayout(LayoutKind.Sequential)> _
Friend Structure GPRECTF
Friend X As Single
Friend Y As Single
Friend Width As Single
Friend Height As Single
Friend Sub New(ByVal x As Single, ByVal y As Single, ByVal width As Single, ByVal height As Single)
Me.X = x
Me.Y = y
Me.Width = width
Me.Height = height
End Sub
Friend Sub New(ByVal rect As RectangleF)
Me.X = rect.X
Me.Y = rect.Y
Me.Width = rect.Width
Me.Height = rect.Height
End Sub
Friend ReadOnly Property SizeF() As SizeF
Get
Return New SizeF(Me.Width, Me.Height)
End Get
End Property
Friend Function ToRectangleF() As RectangleF
Return New RectangleF(Me.X, Me.Y, Me.Width, Me.Height)
End Function
End Structure
Public Sub Draw4(ByVal Text As String)
Clear()
Dim i As Integer, j As Integer, tS() As String
j = Int(Text.Length / 52)
ReDim tS(j - 1)
For i = 0 To j - 1
tS(i) = Text.Substring(i * 52, 52)
Next
If Text.Length - j * 52 <> 0 Then
ReDim Preserve tS(j+1)
tS(j+1) = Text.Substring(j * 52)
End If
DrawLineText(mG, tS, mFont, New SolidBrush(mForeColor))
End Sub
Private Sub DrawLineText(ByVal G As Graphics, ByVal T() As String, ByVal F As Font, ByVal B As Brush)
If (G Is Nothing) Then Throw New ArgumentNullException("graphics")
If (T Is Nothing) Then Throw New ArgumentNullException("text")
If (F Is Nothing) Then Throw New ArgumentNullException("font")
If (B Is Nothing) Then Throw New ArgumentNullException("brush")
Dim Field As FieldInfo
Field = GetType(Graphics).GetField("nativeGraphics", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim hGraphics As IntPtr = Field.GetValue(G)
Field = GetType(Font).GetField("nativeFont", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim hFont As IntPtr = Field.GetValue(F)
Field = GetType(Brush).GetField("nativeBrush", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim hBrush As IntPtr = Field.GetValue(B)
Dim i As Integer, tR As GPRECTF
tR = New GPRECTF(0, 0, mBmp.Width, mBmp.Height)
For i = 0 To 17
tR.X = 3
tR.Y = 3 + i * mLineHeight
GdipDrawString(hGraphics, T(i), T(i).Length, hFont, tR, IntPtr.Zero, hBrush)
Next
End Sub
经测试,方法四和方法三的效率不相上下。但是,方法四更接近我们直观的想法,而且对Font的要求也不是很高。
可能还有更好的方法,欢迎各位网友交流。
相关文章推荐
- GDI+绘制自定义行距的文本的三种方法。
- GDI+ 绘制自定义制表位位数的文本。
- GDI+绘制竖向文本
- 使用WebBrowser控件时在网页元素上绘制文本或其他自定义内容
- Android UI 之居中绘制文本内容的正确方法——实现自定义一个TextView
- MFC中使用GDI+绘制自定义的控件
- 图形的绘制,如何使用自定义画笔(颜色,线宽,线形)。如何为程序中添加选项菜单和选项设置对话框,如何使用标准颜色对话框,如何使用字体对话框,在选项对话框中实现预览功能。实现选项对话框和窗口类中的数据交换。如何改变对话框和控件的背景色,如何改变控件的文本颜色,
- GDI+中的文本绘制技术
- android 自定义view之文本绘制解析
- Delphi下的GDI+编程[5] 绘制直线-自定义虚线
- C#--GDI+绘制多行文本和格式化文本
- Android UI 之居中绘制文本内容的正确方法——实现自定义一个TextView
- GDI+ 绘制多行文本,自动换行。
- Android 自定义View-怎么绘制居中文本?
- C#中使用GDI+绘制形状时自动缩放文本
- GDI+在固定位置(固定点)的地方绘制文本
- Android UI 之居中绘制文本内容的正确方法——实现自定义一个TextView
- 自定义View之Paint - 绘制文本
- C#--GDI+绘制多行文本和格式化文本
- 使用 GDI+ 绘制有间距的文本