2010-10-06 35 views
0

我正在使用一些代码来使我能够使用TextRenderer.DrawText方法呈现旋转的文本。 (默认情况下,DrawText只能从图形对象复制直接的x和y转换)。在.Net中使用GDI + interop帮助

代码(C#)来自:connect.microsoft.com。请参阅下面的VB转换。

该代码需要一个图形对象,创建一个设备上下文并从图形对象复制变换矩阵。它的工作原理,但我想,也是,设置TextRenderingHint,所以我尝试:

<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 

然后是setClip的发言后,我把:GdipSetTextRenderingHint(HDC,someHint)

这给了我一个内存访问冲突错误,所以我想我应该使用除hDC以外的其他参数作为参数。

我可以通过从原始图形对象创建设备上下文,然后从设备上下文创建另一个图形对象来实现它。然后我在新的图形对象上设置提示。这似乎有点令人费解,所以我想知道是否可以通过互操作。

VB.Net代码转换:

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 

回答

2

哇,符合 “一知半解可能是危险的” 模具。甚至不是原生的C++程序员直接调用gdiplus切入点,他们使用C++包装在<gdiplus.h>

这里的失效模式是你的程序加载错误版本的gdiplus.dll中,在c:\ Windows \ System32下。旧版本。正确的是在Windows并行缓存中,.NET的System.Drawing程序集包含代码以确保它从缓存中获取正确版本的DLL。

不是你得到的那个。你的甚至没有初始化,GdiplusStartup从未被调用过。 KABOOM。

不知道你想要完成什么。 Graphics类具有TextRenderingHint属性,不需要杀手捅。

+0

嗯,我以前从来没有见过类似的东西,我已经完成了互操作。我看到了GDip中的共享子New,它调用初始化来加载库。我会假定正确的lib将被自动拾取。无论如何,至于我为什么要这样做,当创建TexterRendererDC时,它会从提供的图形对象中复制转换矩阵和剪辑 - 没有别的。无论如何,当DrawText方法尝试将设备上下文转换为图形以获取呈现提示时,它现在是一个模拟点。因此,在我的问题结束时,我的解决方案是唯一的出路。 – Jules 2010-10-07 00:35:14