0

Graphic.DrawString はクメール語 Unicode を適切にレンダリングしないため、(System.Drawing.Printing.PrintDocument) の代わりに WinAPI を使用して印刷ドキュメントを準備しようとしています。TextRendering.DrawText のみが正しくレンダリングされます。Graphic は GDI+ ラッパーであり、TextRendering.DrawText は GDI を使用していると思います。さらに、PrintDocument は TextRendering.DrawText では機能しません。

Private Declare Function CreateDC Lib "gdi32" Alias "CreateDCA" _
(ByVal lpDriverName As String, ByVal lpDeviceName As String, _
 ByVal lpOutput As String, ByVal lpInitData As DEVMODE) As Long
Private Declare Function EndDoc Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function StartDoc Lib "gdi32" Alias "StartDocA" (ByVal hdc As Long, ByVal lpdi As DOCINFO) As Long
Private Declare Function StartPage Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function EndPage Lib "gdi32" (ByVal hdc As Long) As Long

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    '' Getting Printer hDC
    Dim printHandler As Long = CreateDC(Nothing, "Send To OneNote 2010", Nothing, Nothing)
    Dim docInfo As New DOCINFO
    docInfo.cbSize = Len(docInfo)
    docInfo.lpszDatatype = Nothing
    docInfo.lpszOutput = Nothing
    docInfo.lpszDocName = "Testing"

    StartDoc(printHandler, docInfo)
    StartPage(printHandler)

    Dim g As Graphics = Graphics.FromHdc(printHandler)
    TextRenderer.DrawText(g, "Hello World", Me.Font, New Point(10, 10), Color.Black)

    EndPage(printHandler)
    EndDoc(printHandler)
End Sub

これが私の試みです。次のコード行で失敗します: Dim g As Graphics = Graphics.FromHdc(printHandler). Long は 64 ビット、IntPtr は 32 ビットのようです。

これに対する回避策はありますか?

4

1 に答える 1

2

すべての P/Invoke 定義が VB.NET に対して間違っています。VB 6 を対象とするプロジェクトまたは Web サイトからそれらをコピーしたことは明らかですが、.NET では多くのことが変更されています。

正しい定義は次のようになります。

<DllImport("gdi32.dll", SetLastError:=False, CharSet:=CharSet.Auto)> _
Private Shared Function CreateDC(lpszDriver As String, _
                                 lpszDevice As String, _
                                 lpszOutput As IntPtr, _
                                 ByRef lpInitData As DEVMODE) As IntPtr
End Function

<DllImport("gdi32.dll", SetLastError:=False)> _
Private Shared Function EndDoc(hdc As IntPtr) As Integer
End Function

<DllImport("gdi32.dll", SetLastError:=False)> _
Private Shared Function StartDoc(hdc As IntPtr, ByRef lpdi As DOCINFO) As Integer
End Function

<DllImport("gdi32.dll", SetLastError:=False)> _
Private Shared Function StartPage(hdc As IntPtr) As Integer
End Function

<DllImport("gdi32.dll", SetLastError:=False)> _
Private Shared Function EndPage(hdc As IntPtr) As Integer
End Function

DEVMODEまた、および構造体の定義DOCINFOが間違っている可能性も十分にあります。これらの型の意味が VB 6 から VB.NET に変更されたため、ポインター型Longの代わりに ととを混同している可能性があります。IntPtrLongInteger

おそらく構造体はまったく必要ありません。その場合は、関数定義を次DEVMODEのように置き換えることができます。CreateDC

<DllImport("gdi32.dll", SetLastError:=False, CharSet:=CharSet.Auto)> _
Private Shared Function CreateDC(lpszDriver As String, _
                                 lpszDevice As String, _
                                 lpszOutput As IntPtr, _
                                 lpInitData As IntPtr) As IntPtr _
End Function

ドキュメントで指示されているように、 IntPtr.ZeroforlpInitDataと同じようにforを渡します— <code>IntPtr.Zero は実質的にfor ポインター型と同等です。lpszOutputNULL

構造体は次のDOCINFOように宣言されます。

<StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)> _
Private Structure DOCINFO
    Dim cbSize As Integer
    Dim lpszDocName As String
    Dim lpszOutput As String
    Dim lpszDatatype As String
    Dim fwType As Integer
End Structure

ドキュメントに従って、fwTypeメンバーは次の定数のいずれかになります。

  • 0
  • Private Const DI_APPBANDING As Integer = &H1
  • Private Const DI_ROPS_READ_DESTINATION As Integer = &H2

とはいえ、.NET の世界にはもっと簡単に印刷する方法があることをご存知でしょうか?

于 2012-05-13T09:49:08.347 に答える