I'm using some code to enable me to render rotated text with the TextRenderer.DrawText method. (By default, DrawText can only copy a straight forward x and y transform from a graphics object).
The code (C#) is from: connect.microsoft.com. See below for a VB conversion.
The code takes a graphics object, creates a device context and copies the transform matrix from the graphics object. It works, but I'd like, also, to set the TextRenderingHint, so I tried:
<DllImport("gdiplus.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)> _
Public Shared Function GdipSetTextRenderingHint(ByVal graphics As HandleRef, ByVal textRenderingHint As System.Drawing.Text.TextRenderingHint) As Integer
End Function
And then after the SetClip statement, I place: GdipSetTextRenderingHint(hDC, someHint)
This gives me a memory access violation error, so I think I should be using something other than hDC as the argument.
I can get it to work by creating the device context from the original graphics object, and then creating another graphics object from the device context. I then set the hint on the new graphics object. This seems a bit convoluted so I was wondering if it was possible through interop.
VB.Net code conversion:
Friend Class TextRendererDC
Implements IDeviceContext
Implements IDisposable
Private graphics As Graphics
Private dc As IntPtr
Private Sub New()
End Sub
Public Sub New(ByVal g As Graphics)
Me.graphics = g
End Sub
Public Function GetHdc() As IntPtr Implements System.Drawing.IDeviceContext.GetHdc
Dim xform As NativeMethods.XFORM
Dim clipRgn As IntPtr
Using transf As Matrix = Me.graphics.Transform
xform = New NativeMethods.XFORM(transf)
End Using
Using clip As Region = Me.graphics.Clip
clipRgn = clip.GetHrgn(Me.graphics)
End Using
Me.dc = Me.graphics.GetHdc()
Dim hDC As New HandleRef(Me, Me.dc)
Dim hRegion As New HandleRef(Nothing, clipRgn)
SetTransform(hDC, xform)
SetClip(hDC, hRegion)
// The below call creates a memory access violation.
NativeMethods.GdipSetTextRenderingHint(hDC, System.Drawing.Text.TextRenderingHint.AntiAliasGridFit)
Return Me.dc
End Function
Public Sub ReleaseHdc() Implements System.Drawing.IDeviceContext.ReleaseHdc
If Me.dc <> IntPtr.Zero Then
Me.graphics.ReleaseHdc()
Me.dc = IntPtr.Zero
End If
End Sub
Public Sub Dispose() Implements System.IDisposable.Dispose
ReleaseHdc()
End Sub
Private Shared Sub SetTransform(ByVal hdc As HandleRef, ByVal xform As NativeMethods.XFORM)
NativeMethods.SetGraphicsMode(hdc, NativeMethods.GM_ADVANCED)
NativeMethods.SetWorldTransform(hdc, xform)
End Sub
Private Shared Sub SetClip(ByVal hdc As HandleRef, ByVal hRegion As HandleRef)
NativeMethods.SelectClipRgn(hdc, hRegion)
End Sub
Private Class NativeMethods
Public Const GM_ADVANCED As Integer = 2
<DllImport("Gdi32")> _
Public Shared Function SetGraphicsMode(ByVal hdc As HandleRef, ByVal mode As Integer) As Integer
End Function
<DllImport("Gdi32")> _
Public Shared Function SetWorldTransform(ByVal hDC As HandleRef, ByVal xform As NativeMethods.XFORM) As Boolean
End Function
<DllImport("Gdi32")> _
Public Shared Function SelectClipRgn(ByVal hDC As HandleRef, ByVal hRgn As HandleRef) As Integer
End Function
<DllImport("gdiplus.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)> _
Public Shared Function GdipSetTextRenderingHint(ByVal graphics As HandleRef, ByVal textRenderingHint As System.Drawing.Text.TextRenderingHint) As Integer
End Function
<StructLayout(LayoutKind.Sequential)> _
Public Class XFORM
Public eM11 As Single
Public eM12 As Single
Public eM21 As Single
Public eM22 As Single
Public eDx As Single
Public eDy As Single
Public Sub New()
Me.eM11 = 1.0!
Me.eM22 = 1.0!
End Sub
Public Sub New(ByVal transform As Matrix)
Me.eM11 = 1.0!
Me.eM22 = 1.0!
Me.eM11 = transform.Elements(0)
Me.eM12 = transform.Elements(1)
Me.eM21 = transform.Elements(2)
Me.eM22 = transform.Elements(3)
Me.eDx = transform.Elements(4)
Me.eDy = transform.Elements(5)
End Sub
End Class
End Class
End Class