0

我尝试使用 WinAPI 而不是 (System.Drawing.Printing.PrintDocument) 来准备打印文档,因为 Graphic.DrawString 无法正确呈现高棉 Unicode。只有 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

对于 VB.NET,您的所有 P/Invoke 定义都是错误的。您显然已经从面向 VB 6 的项目或网站中复制了它们,但是很多事情已经随着 .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

您对DEVMODEDOCINFO结构的定义也很有可能是错误的。您可能正在使用指针类型Long而不是指针类型,并且IntPtr混合了数字类型,因为这些类型的含义从 VB 6 更改为 VB.NET。LongInteger

您可能根本不需要该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.Zerofor lpInitData,就像文档lpszOutput中所指示的那样for ——<code>IntPtr.Zero 实际上等效于for 指针类型。NULL

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 回答