Question Printing the contents of a Rich Text Box

JamH

New member
Joined
Nov 9, 2024
Messages
1
Programming Experience
5-10
Although I have written a few applications and have gotten paid for a couple of them, programming is for the most part just a hobby. I am trying to make an application
that I wrote for my employer a little more functional. The trouble I am having is printing the text from a Rich Text Box in which the use can change the font. For example,
when making an address label I wanted to make it so the return address can be smaller than the to address. The text box works perfect and does what it is supposed to do
but when you print the label, it prints out all the same size. That is the most important part. As a side note, the user can place the text anywhere they want to using the enter
key and the spacebar, but for some reason using the tab key messes up the printout. Just to clarify, if you do not use the tab key, the label will print exactly as shown.
I hope someone can help with this and thank you in advance. I am using VB in Visual Studio 2022 and I hope this is the correct forum?
 
Here's a solution and usage for you. I tested it and its functional.

Public Class RichTextBoxEx
Inherits RichTextBox

<StructLayout(LayoutKind.Sequential)>
Private Structure STRUCT_RECT
Public left As Int32
Public top As Int32
Public right As Int32
Public bottom As Int32
End Structure

<StructLayout(LayoutKind.Sequential)>
Private Structure STRUCT_CHARRANGE
Public cpMin As Int32
Public cpMax As Int32
End Structure

<StructLayout(LayoutKind.Sequential)>
Private Structure STRUCT_FORMATRANGE
Public hdc As IntPtr
Public hdcTarget As IntPtr
Public rc As STRUCT_RECT
Public rcPage As STRUCT_RECT
Public chrg As STRUCT_CHARRANGE
End Structure

<DllImport("user32.dll")>
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Int32, ByVal wParam As Int32, ByVal lParam As IntPtr) As Int32
Private Const WM_USER As Int32 = &H400
Private Const EM_FORMATRANGE As Int32 = WM_USER + 57
Private Const EM_GETCHARFORMAT As Int32 = WM_USER + 58
Private Const EM_SETCHARFORMAT As Int32 = WM_USER + 68

Public Function FormatRange(ByVal measureOnly As Boolean, ByVal e As PrintPageEventArgs, ByVal charFrom As Integer, ByVal charTo As Integer) As Integer
Dim cr As STRUCT_CHARRANGE = Nothing
cr.cpMin = charFrom
cr.cpMax = charTo
Dim rc As STRUCT_RECT = Nothing
rc.top = HundredthInchToTwips(e.MarginBounds.Top)
rc.bottom = HundredthInchToTwips(e.MarginBounds.Bottom)
rc.left = HundredthInchToTwips(e.MarginBounds.Left)
rc.right = HundredthInchToTwips(e.MarginBounds.Right)
Dim rcPage As STRUCT_RECT = Nothing
rcPage.top = HundredthInchToTwips(e.PageBounds.Top)
rcPage.bottom = HundredthInchToTwips(e.PageBounds.Bottom)
rcPage.left = HundredthInchToTwips(e.PageBounds.Left)
rcPage.right = HundredthInchToTwips(e.PageBounds.Right)
Dim hdc As IntPtr = Nothing
hdc = e.Graphics.GetHdc()
Dim fr As STRUCT_FORMATRANGE = Nothing
fr.chrg = cr
fr.hdc = hdc
fr.hdcTarget = hdc
fr.rc = rc
fr.rcPage = rcPage
Dim wParam As Int32 = Nothing

If measureOnly Then
wParam = 0
Else
wParam = 1
End If

Dim lParam As IntPtr = Nothing
lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fr))
Marshal.StructureToPtr(fr, lParam, False)
Dim res As Integer = 0
res = SendMessage(Handle, EM_FORMATRANGE, wParam, lParam)
Marshal.FreeCoTaskMem(lParam)
e.Graphics.ReleaseHdc(hdc)
Return res
End Function

Private Function HundredthInchToTwips(ByVal n As Integer) As Int32
Return Convert.ToInt32(n * 14.4)
End Function

Public Sub FormatRangeDone()
Dim lParam As IntPtr = New IntPtr(0)
SendMessage(Handle, EM_FORMATRANGE, 0, lParam)
End Sub
End Class

USAGE: FOR PRINTING
Class SurroundingClass
Private Sub printDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs)
firstCharOnPage = 0
End Sub

Private Sub printDocument1_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs)
richTextBoxEx1.FormatRangeDone()
End Sub

Private Sub printDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
firstCharOnPage = richTextBoxEx1.FormatRange(False, e, firstCharOnPage, richTextBoxEx1.TextLength)

If firstCharOnPage < richTextBoxEx1.TextLength Then
e.HasMorePages = True
Else
e.HasMorePages = False
End If
End Sub

Private Sub printToolStripButton_Click(ByVal sender As Object, ByVal e As EventArgs)
printDocument1.Print()
End Sub
End Class
 
Back
Top