2010-10-06 6 views
0

J'utilise du code pour activer le rendu de texte avec la méthode TextRenderer.DrawText. (Par défaut, DrawText ne peut copier qu'une transformation x et y directe à partir d'un objet graphique).Aide avec GDI + interop in .Net

Le code (C#) provient de: connect.microsoft.com. Voir ci-dessous pour une conversion VB.

Le code prend un objet graphique, crée un contexte de périphérique et copie la matrice de transformation à partir de l'objet graphique. Il fonctionne, mais je voudrais, aussi, pour régler le TextRenderingHint, donc j'ai essayé:

<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 

Et puis après la déclaration SetClip, je place: GdipSetTextRenderingHint (hdc, someHint)

Cela me donne une erreur de violation d'accès à la mémoire, donc je pense que je devrais utiliser autre chose que hDC comme argument.

Je peux le faire fonctionner en créant le contexte de périphérique à partir de l'objet graphique d'origine, puis en créant un autre objet graphique à partir du contexte de périphérique. Je définis ensuite l'indice sur le nouvel objet graphique. Cela semble un peu compliqué alors je me demandais si c'était possible grâce à interop.

conversion de code 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 

Répondre

2

Wow, qui correspond à la moule "un peu de connaissance pourrait être dangereux". Pas même le natif C++ programmeurs appellent le point d'entrée de gdiplus directement, ils utilisent l'emballage C++ dans <gdiplus.h>

Le mode d'échec est que votre programme est de charger le mauvaise version de gdiplus.dll, celui de c: \ windows \ system32. La version héritée La bonne est dans le cache side-by-side de Windows, l'assembly System.Drawing de .NET contient du code pour s'assurer qu'il obtient la bonne version de la DLL à partir du cache.

Pas celui que vous obtenez. Le vôtre n'est même pas initialisé, GdiplusStartup n'a jamais été appelé. Kaboom.

Aucune idée de ce que vous essayez d'accomplir. La classe Graphics a une propriété TextRenderingHint, pas besoin du tueur de tueur.

+0

Eh bien, je n'ai jamais vu quelque chose comme ça avant quand j'ai fait interop. Je vois le sous-répertoire partagé New dans GDip qui appelle initialize pour charger la librairie. J'aurais supposé que la bonne lib serait automatiquement récupérée. Quoi qu'il en soit, pour ce que je fais, quand TexterRendererDC est créé, il copie la matrice de transformation et le clip de l'objet graphique fourni - rien d'autre. C'est un point discutable de toute façon, car la méthode DrawText essaie de transformer le contexte du périphérique en graphique pour obtenir l'indice de rendu. Par conséquent, ma solution compliquée, à la fin de ma question, est la seule voie à suivre. – Jules