a_jam_sandwich Posted February 12, 2003 Posted February 12, 2003 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 ... 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 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 Quote Code today gone tomorrow!
a_jam_sandwich Posted February 12, 2003 Author Posted February 12, 2003 Any help would be greatly accepted Andy Quote Code today gone tomorrow!
a_jam_sandwich Posted February 14, 2003 Author Posted February 14, 2003 Does noone have any idea? Could it be somthing to do with the IntPtr's ? Quote Code today gone tomorrow!
*Gurus* divil Posted February 14, 2003 *Gurus* Posted February 14, 2003 You might want to check here as this guy appears to have successfully implemented printing. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
a_jam_sandwich Posted February 14, 2003 Author Posted February 14, 2003 Cheers will look Andy Quote Code today gone tomorrow!
a_jam_sandwich Posted February 14, 2003 Author Posted February 14, 2003 Its the same control i tried to covert into vb.net above Arh .... no..... Any ideas? Quote Code today gone tomorrow!
*Gurus* divil Posted February 14, 2003 *Gurus* Posted February 14, 2003 You're missing the StructLayout attributes from your structures, for a start. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
*Gurus* divil Posted February 14, 2003 *Gurus* Posted February 14, 2003 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. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
a_jam_sandwich Posted February 14, 2003 Author Posted February 14, 2003 Never messed with structures before in vb.net so how should i go about it? Quote Code today gone tomorrow!
a_jam_sandwich Posted February 14, 2003 Author Posted February 14, 2003 right should it be like this ? <StructLayout(LayoutKind.Sequential)> _ Private Structure RECT Public Left As Integer Public Top As Integer Public Right As Integer Public Bottom As Integer End Structure Quote Code today gone tomorrow!
a_jam_sandwich Posted February 14, 2003 Author Posted February 14, 2003 im getting closer 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' Quote Code today gone tomorrow!
a_jam_sandwich Posted February 14, 2003 Author Posted February 14, 2003 (edited) 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]prtb.zip Edited February 14, 2003 by divil Quote Code today gone tomorrow!
*Gurus* divil Posted February 14, 2003 *Gurus* Posted February 14, 2003 You still haven't implemented the constructor, like I said. Public Sub New(ByVal tRichTextbox As richTextBox) richTextBox = tRichTextbox textLength = tRichTextbox.TextLength firstChar = 0 End Function Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
a_jam_sandwich Posted February 14, 2003 Author Posted February 14, 2003 FIXED IT WILL POST SOON Was the was I was referencing the user32.DLL Quote Code today gone tomorrow!
a_jam_sandwich Posted February 14, 2003 Author Posted February 14, 2003 Here we go a working version YIPPIE :p It can load multiple files into the class and then you can print preview them all in one go. Take a look Thanks to Martin Müller for the original C# code and Divil whos help is greatly appreciated . To view the original c# click here http://www.codeguru.com/cs_controls/RichTextEx.html Quote Code today gone tomorrow!
Moderators Robby Posted February 14, 2003 Moderators Posted February 14, 2003 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] Quote Visit...Bassic Software
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.