从hDC创建图形导致算术运算溢出

时间:2012-05-12 20:51:27

标签: vb.net winapi

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

有没有解决方法呢?

1 个答案:

答案 0 :(得分: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作为指针类型,并将LongInteger混合用于数字类型,因为这些类型的含义从VB 6更改为VB.NET。

您可能根本不需要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.Zero lpInitData lpszOutput,就像IntPtr.Zero所指示的那样,the documentation - 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

根据the documentationPrivate Const DI_APPBANDING As Integer = &H1成员可以是以下任何常量:

  • 0
  • Private Const DI_ROPS_READ_DESTINATION As Integer = &H2
  • {{1}}

所有这些都说......你知道在.NET世界中有更简单的打印方式,对吗?