【问题标题】:Help with GDI+ interop in .Net.Net 中的 GDI+ 互操作帮助
【发布时间】:2010-10-06 20:41:51
【问题描述】:

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

代码 (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

【问题讨论】:

    标签: c# .net vb.net interop gdi+


    【解决方案1】:

    哇,这符合“一点知识可能很危险”的模式。甚至原生 C++ 程序员也没有直接调用 gdiplus 入口点,他们使用 &lt;gdiplus.h&gt; 中的 C++ 包装器

    这里的故障模式是您的程序正在加载 错误 版本的 gdiplus.dll,即 c:\windows\system32 中的那个。旧版。正确的是在 Windows 并行缓存中,.NET 的 System.Drawing 程序集包含确保它从缓存中获取正确版本的 DLL 的代码。

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

    不知道您要完成什么。 Graphics 类有一个 TextRenderingHint 属性,不需要杀手锏。

    【讨论】:

    • 好吧,当我完成互操作时,我从未见过这样的事情。我看到 GDip 中的共享子 New 调用初始化来加载库。我会假设正确的库会被自动拾取。无论如何,至于我为什么这样做,当 TexterRendererDC 创建时,它会从提供的图形对象中复制变换矩阵和剪辑 - 仅此而已。无论如何,它现在仍然是一个有争议的问题,因为 DrawText 方法试图将设备上下文转换为图形以获取渲染提示。因此,在我的问题结束时,我的复杂解决方案是唯一的出路。
    猜你喜欢
    • 2011-02-02
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多