SelPrint 属性未升级

在 Visual Basic 6.0 中,RichTextBox 控件的 SelPrint 方法可用于打印该控件的内容。它采用单一参数 hDC,该参数指定设备的设备上下文。

在 Visual Basic 2008 中,不再存在 SelPrint 方法,设备上下文也不再用于打印。RichTextBox 控件不提供打印其内容的方法。但是,您可以扩展 RichTextBox 类以使用 EM_FORMATRANGE 消息。然后,可以将 RichTextBox 的内容发送到输出设备,如打印机。用于完成此过程的两个步骤为:

  1. 创建一个从 RichTextBox 继承的 RichTextBoxPrintCtrl 类。

  2. 在升级后的项目中使用 RichTextBoxPrintCtrl 类。

创建从 RichTextBox 类继承的类

  1. 使用 Visual Basic 2008 创建一个名为 RichTextBoxPrintCtrl 的新“类库”项目。

    默认情况下,创建 Class1.vb。

  2. 将 Class1.vb 文件的名称更改为 RichTextBoxPrintCtrl.vb。

  3. 在“解决方案资源管理器”中,右键单击“引用”,然后单击“添加引用”。

  4. 在“添加引用”对话框中,双击“System.Drawing.dll”,然后双击“System.Windows.Forms.dll”。

  5. 要添加引用,请单击“确定”。

  6. 删除 RichTextBoxPrintCtrl.vb 中现有的代码。

  7. 将下列代码复制到 RichTextBoxPrintCtrl.vb:

    Option Explicit On 
    
    Imports System
    Imports System.Windows.Forms
    Imports System.Drawing
    Imports System.Runtime.InteropServices
    Imports System.Drawing.Printing
    
    Namespace RichTextBoxPrintCtrl
        Public Class RichTextBoxPrintCtrl
            Inherits RichTextBox
    
            ' Convert the unit that is used by the .NET framework 
            ' (1/100 inch) and the unit that is used by Win32 API calls  
            ' (twips 1/1440 inch)
            Private Const AnInch As Double = 14.4
    
            Private WithEvents m_PrintDocument As Printing.PrintDocument
            Private intCharactersToPrint As Integer
            Private intCurrentPosition As Integer
    
            <StructLayout(LayoutKind.Sequential)> _
            Private Structure RECT
                Public Left As Integer
                Public Top As Integer
                Public Right As Integer
                Public Bottom As Integer
            End Structure
    
            <StructLayout(LayoutKind.Sequential)> _
            Private Structure CHARRANGE
                ' First character of range (0 for start of doc)
                Public cpMin As Integer
                ' Last character of range (-1 for end of doc)
                Public cpMax As Integer
            End Structure
    
            <StructLayout(LayoutKind.Sequential)> _
            Private Structure FORMATRANGE
                ' Actual DC to draw on
                Public hdc As IntPtr
                ' Target DC for determining text formatting
                Public hdcTarget As IntPtr
                ' Region of the DC to draw to (in twips)
                Public rc As Rect
                ' Region of the whole DC (page size) (in twips)
                Public rcPage As Rect
                ' Range of text to draw (see above declaration)
                Public chrg As CHARRANGE
            End Structure
    
            Private Const WM_USER As Integer = &H400
            Private Const EM_FORMATRANGE As Integer = WM_USER + 57
    
            Private Declare Function SendMessage Lib "USER32" Alias _
                "SendMessageA" (ByVal hWnd As IntPtr, ByVal msg As Integer, _
                ByVal wp As IntPtr, ByVal lp As IntPtr) As IntPtr
    
            Public Sub SelPrint()
    
                'print only the selected text if any is selected
                If Me.SelectionLength > 0 Then
                    intCharactersToPrint = Me.SelectionStart + Me.SelectionLength
                    intCurrentPosition = Me.SelectionStart
                Else
                    'otherwise print the entire document
                    intCharactersToPrint = Me.TextLength
                    intCurrentPosition = 0
                End If
    
                m_PrintDocument.Print()
    
            End Sub
            ' Render the contents of the RichTextBox for printing
            ' Return the last character printed + 1 (printing start from 
            ' this point for next page)
            Private Function Print(ByVal charFrom As Integer, _
    ByVal charTo As Integer, ByVal e As PrintPageEventArgs) As Integer
    
                ' Mark starting and ending character
                Dim cRange As CHARRANGE
                cRange.cpMin = charFrom
                cRange.cpMax = charTo
    
                ' Calculate the area to render and print
                Dim rectToPrint As RECT
                rectToPrint.Top = e.MarginBounds.Top * AnInch
                rectToPrint.Bottom = e.MarginBounds.Bottom * AnInch
                rectToPrint.Left = e.MarginBounds.Left * AnInch
                rectToPrint.Right = e.MarginBounds.Right * AnInch
    
                ' Calculate the size of the page
                Dim rectPage As RECT
                rectPage.Top = e.PageBounds.Top * AnInch
                rectPage.Bottom = e.PageBounds.Bottom * AnInch
                rectPage.Left = e.PageBounds.Left * AnInch
                rectPage.Right = e.PageBounds.Right * AnInch
    
                Dim hdc As IntPtr = e.Graphics.GetHdc()
    
                Dim fmtRange As FORMATRANGE
                ' Indicate character from to character to
                fmtRange.chrg = cRange
                ' Use the same DC for measuring and rendering
                fmtRange.hdc = hdc
                ' Point at printer hDC
                fmtRange.hdcTarget = hdc
                ' Indicate the area on page to print
                fmtRange.rc = rectToPrint
                ' Indicate whole size of page
                fmtRange.rcPage = rectPage
    
                Dim res As IntPtr = IntPtr.Zero
    
                Dim wparam As IntPtr = IntPtr.Zero
                wparam = New IntPtr(1)
    
                ' Move the pointer to the FORMATRANGE structure in 
                ' memory
                Dim lparam As IntPtr = IntPtr.Zero
                lparam = _
    Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange))
                Marshal.StructureToPtr(fmtRange, lparam, False)
    
                ' Send the rendered data for printing
                res = _
    SendMessage(Handle, EM_FORMATRANGE, wparam, lparam)
    
                ' Free the block of memory allocated
                Marshal.FreeCoTaskMem(lparam)
    
                ' Release the device context handle obtained by a 
                ' previous call
                e.Graphics.ReleaseHdc(hdc)
    
                'return the last + 1 character printed
                Return res.ToInt32
    
            End Function
            Public ReadOnly Property PrintDocument() As Printing.PrintDocument
                Get
                    If m_PrintDocument Is Nothing Then
                        m_PrintDocument = New Printing.PrintDocument
                    End If
    
                    Return m_PrintDocument
                End Get
            End Property
    
            Private Sub m_PrintDocument_PrintPage(ByVal sender As _
    Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
    Handles m_PrintDocument.PrintPage
                ' Print the content of the RichTextBox. 
                ' Store the last character printed.
    
                intCurrentPosition = Me.Print(intCurrentPosition, _
    intCharactersToPrint, e)
    
                ' Look for more pages by checking 
                If intCurrentPosition < intCharactersToPrint Then
                    e.HasMorePages = True
                Else
                    e.HasMorePages = False
                End If
    
            End Sub
        End Class
    End Namespace
    
  8. 要创建 RichTextBoxPrintCtrl.dll,请单击“生成”菜单上的“生成解决方案”。

在升级后的项目中使用 RichTextBoxPrintCtrl 类

  1. 在 Visual Basic 2008 中打开升级后的 Windows 应用程序项目。

  2. 从“工具箱”中,将 PrintDialog 组件拖动到包含 RichTextBox 控件的窗体中。

  3. 在“工具”菜单上,单击“自定义工具箱”。

  4. 单击“.NET Framework 组件”,单击“浏览”,单击以选择“RichTextBoxPrintCtrl.dll”,然后单击“确定”。

  5. 将一个 RichTextBoxPrintCtrl 从“工具箱”中拖动到窗体上。

  6. 将 RichTextBoxPrintCtrl 的属性设置为与您的原始 RichTextBox 控件的属性相匹配。

  7. 删除 RichTextBox 控件,然后将 RichTextBoxPrintCtrl 控件重命名为您的原始 RichTextBox 控件的名称。

  8. 双击此窗体以打开代码编辑器。

  9. 在 Button_Click 事件处理程序(或在原始代码中调用 SelPrint 的位置)中添加以下代码:

    ' NOTE: Replace "Button1" with the name of your actual Print button
    Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    
        'associate the correct printdocument to the printdialog
        PrintDialog1.Document = Me.RichTextBoxPrintCtrl1.PrintDocument
    
        If PrintDialog1.ShowDialog() = DialogResult.OK Then
            Me.RichTextBoxPrintCtrl1.SelPrint()
        End If
    End Sub 
    

请参见

参考

RichTextBox 控件概述(Windows 窗体)

EM_FORMATRANGE 消息