Here we go a working version YIPPIE :p

a_jam_sandwich

Junior Contributor
Joined
Dec 10, 2002
Messages
367
Location
Uk
Help adapted C not working for RTB printing

Complies. Put on form & error;

the user control could not be loaded. Ensure that the library containing the control has been built ...

C#:
namespace de.cortex.text.util
{
	using System;
	using System.Drawing.Printing;
	using System.Runtime.InteropServices;
	using System.Windows.Forms;

	// <doc>
	// <desc>
	//     RichTextPrintDocument prints the content of a RichTextBox
	//     control as RTF formatted text to a printer.
	//     
	//     Usage:
	//         RichTextBox rtb = new RichTextBox();
	//         ... define content of rich text box control
	//         RichTextPrintDocument pd = new RichTextPrintDocument(rtb);
	//         ... define default page settings
	//         ... show standard or custom print dialog
	//         if (dlgResult == DialogResult.OK) 
	//             pd.Print();
	// </desc>
	// </doc>
	public class RichTextPrintDocument : PrintDocument 
	{
		// internal data structures needed for EM_FORMATRANGE message
		// send to RichTextBox control windows handle via SendMessage()
		// The windows message handling is based on code posted by
		// Martin Müller on 08.Feb.2002 in his RichTextBoxEx class.
		[ StructLayout( LayoutKind.Sequential )]
		private struct RECT 
		{
			public int left;
			public int top;
			public int right;
			public int bottom;
		}
		[ StructLayout( LayoutKind.Sequential )]
		private struct CHARRANGE 
		{
			public int cpMin;
			public int cpMax;
		}
		[ StructLayout( LayoutKind.Sequential )]
		private struct FORMATRANGE 
		{
			public IntPtr hdc; 
			public IntPtr hdcTarget; 
			public RECT rc; 
			public RECT rcPage; 
			public CHARRANGE chrg; 
		}

		[DllImport("user32.dll", CharSet=CharSet.Auto)]
		private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

		private const int WM_USER        = 0x400;
		private const int EM_FORMATRANGE = WM_USER+57;

		private RichTextBox richTextBox = null;
		private int textLength;
		private int firstChar;

		public RichTextPrintDocument(RichTextBox richTextBox) : base ()  
		{
			this.richTextBox = richTextBox;
			this.textLength  = richTextBox.TextLength;
			this.firstChar   = 0; // start at the beginning of text
		}

		// Override the OnPrintPage to provide the document printing logic
		protected override void OnPrintPage(PrintPageEventArgs ev) 
		{
			base.OnPrintPage(ev);

			// calculate and render as much text as will fit on the page
			// and remember the last character printed for the next page
			firstChar = FormatRange (ev, firstChar, textLength);

			if (firstChar < textLength)
				ev.HasMorePages = true;
			else
				ev.HasMorePages = false;
		}

		// Override OnEndPrint to perform clean up after printing
		protected override void OnEndPrint(PrintEventArgs ev) 
		{
			base.OnBeginPrint(ev);
			FormatRangeDone();
		}

		/// <summary>
		/// Convert between 1/100 inch (unit used by the .NET framework) and
		/// twips (1/1440 inch, used by Win32 API calls)
		/// </summary>
		/// <param name="n">Value in 1/100 inch</param>
		/// <returns>Value in twips</returns>
		private int HundredthInchToTwips(int n)
		{
			return (int)(n*14.4);
		}

		/// <summary>
		/// Calculate and render the contents of the RichTextBox for a printing
		/// page
		/// </summary>
		/// <param name="e">The PrintPageEventArgs object from the PrintPage
		/// event</param>
		/// <param name="charFrom">Index of first character to be printed</param>
		/// <param name="charTo">Index of last character to be printed</param>
		/// <returns>(Index of last character that fitted on the page) + 1</returns>
		private int FormatRange(PrintPageEventArgs ev, int charFrom, int charTo)
		{
			// build content of FORMATRANGE struct
			CHARRANGE cr;
			cr.cpMin=charFrom;
			cr.cpMax=charTo;

			RECT rc;
			rc.top	  = HundredthInchToTwips(ev.MarginBounds.Top);
			rc.bottom = HundredthInchToTwips(ev.MarginBounds.Bottom);
			rc.left	  = HundredthInchToTwips(ev.MarginBounds.Left);
			rc.right  = HundredthInchToTwips(ev.MarginBounds.Right);

			RECT rcPage;
			rcPage.top    = HundredthInchToTwips(ev.PageBounds.Top);
			rcPage.bottom = HundredthInchToTwips(ev.PageBounds.Bottom);
			rcPage.left   = HundredthInchToTwips(ev.PageBounds.Left);
			rcPage.right  = HundredthInchToTwips(ev.PageBounds.Right);

			IntPtr hdc = ev.Graphics.GetHdc();

			FORMATRANGE fr;
			fr.chrg	     = cr;
			fr.hdc       = hdc;
			fr.hdcTarget = hdc;
			fr.rc        = rc;
			fr.rcPage    = rcPage;

			// build SendMessage arguments
			IntPtr res;
			IntPtr wpar = new IntPtr(1);
			IntPtr lpar = Marshal.AllocCoTaskMem( Marshal.SizeOf( fr ) ); 
			Marshal.StructureToPtr(fr, lpar, false);

			// let richTextBox control format its content for printing device
			res = SendMessage(richTextBox.Handle, EM_FORMATRANGE, wpar, lpar);

			// clean-up resources
			Marshal.FreeCoTaskMem(lpar);
			ev.Graphics.ReleaseHdc(hdc);

			return res.ToInt32();
		}

		/// <summary>
		/// Clean-up method after the print job is finished to release cached
		/// information
		/// </summary>
		private void FormatRangeDone()
		{
			IntPtr wpar = new IntPtr(0);
			IntPtr lpar = new IntPtr(0);
			SendMessage(richTextBox.Handle, EM_FORMATRANGE, wpar, lpar);
		}
	}
}

Tried to covert to

Visual Basic:
Imports System
Imports System.Drawing.Printing
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

Public Class printRTF
    Inherits PrintDocument

    Private Structure RECT
        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer
    End Structure

    Private Structure CHARRANGE
        Public cpMin As Integer
        Public cpMax As Integer
    End Structure

    Private Structure sFORMATRANGE
        Public hdc As IntPtr
        Public hdcTarget As IntPtr
        Public rc As RECT
        Public rcPage As RECT
        Public chrg As CHARRANGE
    End Structure

    Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessage" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

    Private Const WM_USER As Integer = 1024
    Private Const EM_FORMATRANGE As Integer = WM_USER + 57

    Private richTextBox As richTextBox
    Private textLength As Integer
    Private firstChar As Integer

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'UserControl overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        components = New System.ComponentModel.Container()
    End Sub

#End Region

    Public Function RichTextPrintDocument(ByVal tRichTextbox As richTextBox)
        richTextBox = tRichTextbox
        textLength = tRichTextbox.TextLength
        firstChar = 0
    End Function

    Protected Overrides Sub OnPrintPage(ByVal e As System.Drawing.Printing.PrintPageEventArgs)
        MyBase.OnPrintPage(e)
        firstChar = FormatRange(e, firstChar, textLength)
        If (firstChar < textLength) Then
            e.HasMorePages = True
        Else
            e.HasMorePages = False
        End If
    End Sub

    Protected Overrides Sub OnEndPrint(ByVal e As System.Drawing.Printing.PrintEventArgs)
        MyBase.OnBeginPrint(e)
        FormatRangeDone()
    End Sub

    Private Function HundredthInchToTwips(ByVal n As Integer) As Integer
        Return CInt(n * 14.4)
    End Function

    Private Function FormatRange(ByVal e As PrintPageEventArgs, ByVal charFrom As Integer, ByVal charTo As Integer) As Integer
        Dim cr As CHARRANGE
        cr.cpMin = charFrom
        cr.cpMax = charTo

        Dim rc As RECT
        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 RECT
        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 = e.Graphics.GetHdc()

        Dim fr As sFORMATRANGE
        fr.chrg = cr
        fr.hdc = hdc
        fr.hdcTarget = hdc
        fr.rc = rc
        fr.rcPage = rcPage

        Dim res As IntPtr
        Dim wpar As IntPtr = New IntPtr(1)
        Dim lpar As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(fr))
        Marshal.StructureToPtr(fr, lpar, False)

        res = SendMessage(richTextBox.Handle, EM_FORMATRANGE, wpar, lpar)

        Marshal.FreeCoTaskMem(lpar)
        e.Graphics.ReleaseHdc(hdc)

        Return res.ToInt32()

    End Function

    Private Function FormatRangeDone()
        Dim wpar As IntPtr = New IntPtr(0)
        Dim lpar As IntPtr = New IntPtr(0)
        SendMessage(richTextBox.Handle, EM_FORMATRANGE, wpar, lpar)
    End Function

End Class
 
Also, you have a load of useless form designer code which you should delete. You have mistaken the constructor in the C# example for a function, your RichTextPrintDocument function should actually be Sub New.
 
right should it be like this ?

Visual Basic:
    <StructLayout(LayoutKind.Sequential)> _
    Private Structure RECT
        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer
    End Structure
 
im getting closer

Visual Basic:
Imports System
Imports System.Drawing.Printing
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

Namespace RichTextExLib
    Public Class printRTF
        Inherits RichTextBox

        <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
            Public cpMax As Integer
        End Structure

        <StructLayout(LayoutKind.Sequential)> _
        Private Structure sFORMATRANGE
            Public hdc As IntPtr
            Public hdcTarget As IntPtr
            Public rc As RECT
            Public rcPage As RECT
            Public chrg As CHARRANGE
        End Structure

        Private Declare Function SendMessage Lib "user32" Alias "SendMessage" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

        Private Const WM_USER As Integer = 1024
        Private Const EM_FORMATRANGE As Integer = 1081
        Private Const EM_SETTARGETDEVICE As Integer = 1096

        Private Function HundredthInchToTwips(ByVal n As Integer) As Integer
            Return CInt(n * 14.4)
        End Function

        Public Function SetTargetDevice(ByVal g As Graphics, ByVal lineLen As Integer) As Boolean
            Dim res As IntPtr
            Dim wpar As IntPtr = g.GetHdc()
            Dim lpar As IntPtr = New IntPtr(HundredthInchToTwips(lineLen))
            res = SendMessage(Handle, EM_SETTARGETDEVICE, wpar, lpar)
            g.ReleaseHdc(wpar)
            Return (Not res.ToInt32() = 0)
        End Function

        Public Function FormatRange(ByVal e As PrintPageEventArgs, ByVal charFrom As Integer, ByVal charTo As Integer) As Integer
            Dim cr As CHARRANGE
            cr.cpMin = charFrom
            cr.cpMax = charTo

            Dim rc As RECT
            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 RECT
            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 = e.Graphics.GetHdc()

            Dim fr As sFORMATRANGE
            fr.chrg = cr
            fr.hdc = hdc
            fr.hdcTarget = hdc
            fr.rc = rc
            fr.rcPage = rcPage

            Dim res As IntPtr
            Dim wpar As IntPtr = New IntPtr(1)
            Dim lpar As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(fr))
            Marshal.StructureToPtr(fr, lpar, False)

            res = CObj(SendMessage(Handle, EM_FORMATRANGE, wpar, lpar))

            Marshal.FreeCoTaskMem(lpar)
            e.Graphics.ReleaseHdc(hdc)

            Return res.ToInt32()
        End Function

        Public Function FormatRangeDone()
            Dim wpar As IntPtr = New IntPtr(0)
            Dim lpar As IntPtr = New IntPtr(0)
            SendMessage(Handle, EM_FORMATRANGE, wpar, lpar)
        End Function

    End Class

End Namespace

Now it doesn't display when you do a print preview 'no pages to display'
 
Project so far for RTB printing in VB.NET

Here is the project as it is so far anyone help ?

Almost had enough of it

Andy

[edit] Removed binaries from attachment - divil [/edit]
 

Attachments

Last edited by a moderator:
You still haven't implemented the constructor, like I said.

Visual Basic:
Public Sub New(ByVal tRichTextbox As richTextBox)
    richTextBox = tRichTextbox
    textLength = tRichTextbox.TextLength
    firstChar = 0
End Function
 
Wow, that site (page) is attempting to run a ton of ActiveX when loading. Or it's stuck in a loop because I disabled ActiveX.

Sorry I can't see it.


[edit]Oh, the thread has been merged, I guess that I can see it now...[/CODE]
 
Back
Top