Microsoft KB Archive/811401

= How to print the content of a RichTextBox control by using Visual Basic .NET or Visual Basic 2005 =

Article ID: 811401

Article Last Modified on 11/13/2007

-

APPLIES TO


 * Microsoft Visual Basic 2005
 * Microsoft Visual Basic .NET 2003 Standard Edition
 * Microsoft Visual Basic .NET 2002 Standard Edition

-





For a Microsoft Visual Basic 6.0 version of this article, see 146022.



For a Microsoft Visual C# .NET version of this article, see 812425.



SUMMARY
This step-by-step article describes how to print the content of a RichTextBox control. The RichTextBox control does not provide a method to print its content. However, you can extend the RichTextBox class to use the EM_FORMATRANGE message. You can then send the content of a RichTextBox to an output device, such as a printer.

Create a RichTextBoxPrintCtrl control
To extend the RichTextBox class and use EM_FORMATRANGE to print the content of the RichTextBox control, follow these steps:  Use Microsoft Visual Basic .NET or Microsoft Visual Basic 2005 to create a new Class Library project named RichTextBoxPrintCtrl.

By default, Class1.vb is created. Change the name of the Class1.vb file to RichTextBoxPrintCtrl.vb . In the Solution Explorer, right-click References, and then click Add Reference. In the Add Reference dialog box, double-click System.Drawing.dll, and then double-click System.Windows.Forms.dll. To add references, click OK. Delete the existing code in RichTextBoxPrintCtrl.vb.</li>  Copy the following code to 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

<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 Public cpMin As Integer         ' First character of range (0 for start of doc) Public cpMax As Integer         ' Last character of range (-1 for end of doc) End Structure

<StructLayout(LayoutKind.Sequential)> _ Private Structure FORMATRANGE Public hdc As IntPtr            ' Actual DC to draw on         Public hdcTarget As IntPtr       ' Target DC for determining text formatting Public rc As Rect               ' Region of the DC to draw to (in twips) Public rcPage As Rect           ' Region of the whole DC (page size) (in twips) Public chrg As CHARRANGE        ' Range of text to draw (see above declaration) End Structure

Private Const WM_USER As Integer = &H400 Private Const EM_FORMATRANGE As Integer = WM_USER + 57

Private Declare Function SendMessage Lib &quot;USER32&quot; Alias &quot;SendMessageA&quot; (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wp As IntPtr, ByVal lp As IntPtr) As IntPtr

' Render the contents of the RichTextBox for printing ' Return the last character printed + 1 (printing start from this point for next page) Public 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 fmtRange.chrg = cRange                ' Indicate character from to character to          fmtRange.hdc = hdc                     ' Use the same DC for measuring and rendering fmtRange.hdcTarget = hdc              ' Point at printer hDC fmtRange.rc = rectToPrint             ' Indicate the area on page to print fmtRange.rcPage = rectPage            ' Indicate whole size of page

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 last + 1 character printer Return res.ToInt32 End Function

End Class End Namespace </li> To create RichTextBoxPrintCtrl.dll, click Build Solution on the Build menu.</li></ol>

Test the control
To test the control, follow these steps: <ol> Create a new Windows Application project by using Visual Basic .NET or Visual Basic 2005.

By default, Form1.vb is created.</li> From the Toolbox, drag a button onto Form1. Change the Name to btnPageSetup, and change the Text to Page Setup .</li> From the Toolbox, drag another button onto Form1. Change the Name to btnPrintPreview, and change the Text to Print Preview .</li> From the Toolbox, drag another button onto Form1. Change the Name to btnPrint, and change the Text to Print .</li> In the Toolbox, double-click PrintDialog, double-click PrintPreviewDialog, double-click PrintDocument, and then double-click PageSetupDialog to add these controls to Form1.</li> Modify the Document property of PrintDialog1, PrintPreviewDialog1, and PageSetupDialog1 to PrintDocument1 .</li> On the Tools menu, click Customize Toolbox.</li> Click .NET Framework Components, click Browse, click to select RichTextBoxPrintCtrl.dll, and then click OK.</li> From the Toolbox, drag RichTextBoxPrintCtrl onto Form1.</li> In the Solution Explorer, right-click Form1.vb, and then click View Code.</li>  Add the following code to Class Form1: Private checkPrint As Integer

Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint checkPrint = 0 End Sub

Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage ' Print the content of the RichTextBox. Store the last character printed. checkPrint = RichTextBoxPrintCtrl1.Print(checkPrint, RichTextBoxPrintCtrl1.TextLength, e)

' Look for more pages If checkPrint < RichTextBoxPrintCtrl1.TextLength Then e.HasMorePages = True Else e.HasMorePages = False End If  End Sub

Private Sub btnPageSetup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPageSetup.Click.Click PageSetupDialog1.ShowDialog End Sub

Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click If PrintDialog1.ShowDialog = DialogResult.OK Then PrintDocument1.Print End If  End Sub

Private Sub btnPrintPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrintPreview.Click PrintPreviewDialog1.ShowDialog End Sub </li> To run the application, click Start on the Debug menu.</li> Type text in RichTextBoxPrintCtrl.</li> To set the page settings, click Page Setup.</li> <li>To see a preview of the page, click Print Preview.</li> <li>To print the content of the RichTextBoxPrintCtrl, click Print.</li></ol>

<div class="references_section">