Instead of using the RTB directly use it and do it ownerdrawn. Then use something as a canvas where you draw the RTB output.
No selection possible, no access to the data. Not necessary to make it read only. No cursor
Here is the class I'm using
Code:
/// <summary>
/// Ownerdrawn Richtextbox not zoomable
/// </summary>
public class RichTextBoxPrintCtrl:RichTextBox{
//Convert the unit used by the .NET framework (1/100 inch) 0.254 mm)
//and the unit used by Win32 API calls (twips 1/1440 inch)
// 1 mm = 56,6928 twip
private const double anInch = 14.4;
[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; //First character of range (0 for start of doc)
public int cpMax; //Last character of range (-1 for end of doc)
}
[StructLayout(LayoutKind.Sequential)]
private struct FORMATRANGE {
public IntPtr hdc; //Actual DC to draw on
public IntPtr hdcTarget; //Target DC for determining text formatting
public RECT rc; //Region of the DC to draw to (in twips)
public RECT rcPage; //Region of the whole DC (page size) (in twips)
public CHARRANGE chrg; //Range of text to draw (see earlier declaration)
}
private const int WM_USER = 0x0400;
private const int EM_FORMATRANGE = WM_USER + 57;
[DllImport("USER32.dll")]
private static extern IntPtr SendMessage (IntPtr hWnd , int msg , IntPtr wp, IntPtr lp);
// Renders the contents of the RichTextBox for printing
// Return the last character printed + 1 (printing start from this point for next page)
/// <summary>
/// Prints the RTB in the devicecontext
/// Margin sizes needs to be done in the PrintPageEvents
/// </summary>
/// <param name="charFrom"></param>
/// <param name="charTo"></param>
/// <param name="e"></param>
/// <returns></returns>
public int Print( int charFrom, int charTo,PrintPageEventArgs e) {
//Calculate the area to render and print
RECT rectToPrint;
rectToPrint.Top = (int)(e.MarginBounds.Top * anInch);
rectToPrint.Bottom = (int)(e.MarginBounds.Bottom * anInch);
rectToPrint.Left = (int)(e.MarginBounds.Left * anInch);
rectToPrint.Right = (int)(e.MarginBounds.Right * anInch);
//Calculate the size of the page
RECT rectPage;
rectPage.Top = (int)(e.PageBounds.Top * anInch);
rectPage.Bottom = (int)(e.PageBounds.Bottom * anInch);
rectPage.Left = (int)(e.PageBounds.Left * anInch);
rectPage.Right = (int)(e.PageBounds.Right * anInch);
Graphics g = e.Graphics;
IntPtr res = Draw(charFrom, charTo, ref rectToPrint, ref rectPage, g);
//Return last + 1 character printer
return res.ToInt32();
}
/// <summary>
/// The internal Draw method that draws the RTB Text in WYSIWYG Format.
/// </summary>
/// <param name="charFrom"></param>
/// <param name="charTo"></param>
/// <param name="rectToPrint"></param>
/// <param name="rectPage"></param>
/// <param name="g"></param>
/// <returns></returns>
private IntPtr Draw(int charFrom, int charTo, ref RECT rectToPrint, ref RECT rectPage, Graphics g) {
IntPtr hdc = g.GetHdc();
FORMATRANGE fmtRange;
fmtRange.chrg.cpMax = charTo; //Indicate character from to character to
fmtRange.chrg.cpMin = charFrom;
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 size of page
IntPtr res = IntPtr.Zero;
IntPtr wparam = IntPtr.Zero;
wparam = new IntPtr(1);
//Get the pointer to the FORMATRANGE structure in memory
IntPtr lparam = 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
g.ReleaseHdc(hdc);
return res;
}
/// <summary>
/// Draws the RTB as it is by use of the Graphics adapter of the canvas. Sizes in Twips
/// </summary>
/// <param name="recInner"></param>
/// <param name="recDoc"></param>
/// <param name="g"></param>
public void DrawRTBText( int width, int height, Rectangle recMargin, Rectangle recDoc, Graphics g) {
RECT rectToPrint;
this.Width = width;
this.Height = height;
rectToPrint.Left = recMargin.Left;
rectToPrint.Right = recMargin.Width+ recMargin.Left;
rectToPrint.Top = recMargin.Top;
rectToPrint.Bottom = recMargin.Top + recMargin.Height;
RECT rectPage;
rectPage.Left = recDoc.Left;
rectPage.Top = recDoc.Top;
rectPage.Right = recDoc.Left + recDoc.Width;
rectPage.Bottom = recDoc.Top + recDoc.Height;
int len = this.Text.Length;
Draw(0, len, ref rectToPrint, ref rectPage, g);
}
}
Last edited by JonnyPoet; October 14th, 2009 at 02:45 PM.
Jonny Poet
To be Alive is depending on the willingsness to help others and also to permit others to help you. So lets be alive. !
Using Code Tags makes the difference: Code is easier to read, so its easier to help. Do it like this: [CODE] Put Your Code here [/code]
If anyone felt he has got help, show it in rating the post.
Also dont forget to set a post which is fully answered to 'resolved'. For more details look to FAQ's about Forum Usage. BTW I'm using Framework 3.5 and you ? My latest articles : Creating a Dockable Panel-Controlmanager Using C#, Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7
Simple use for example a picturebox as the canvas and the class I provided as the RTB class. The picturebox has the possibillity to ownerdraw so in that drawing method use call the DrawRTBText method of the derived RTB class.
So after you have filled your RTB with data simple invalidate the Picturebox so it will call its draw method, which will call the DrawRTBTex mmethod. The RTB is drawn on the canvas then (in the picturebox) In my case this looks like the picture in the bottom. ( BTW The text is simple an example its a word doc loaded into that RTB and as I also did some rulers it also looks like word, but it is an ownerdrawn RTB.) The text is a letter talking to a friend about a learning project and if people would be interested into a project like that. )
Last edited by JonnyPoet; October 14th, 2009 at 03:37 PM.
Jonny Poet
To be Alive is depending on the willingsness to help others and also to permit others to help you. So lets be alive. !
Using Code Tags makes the difference: Code is easier to read, so its easier to help. Do it like this: [CODE] Put Your Code here [/code]
If anyone felt he has got help, show it in rating the post.
Also dont forget to set a post which is fully answered to 'resolved'. For more details look to FAQ's about Forum Usage. BTW I'm using Framework 3.5 and you ? My latest articles : Creating a Dockable Panel-Controlmanager Using C#, Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7
Lokk at this page http://www.codeproject.com/KB/cs/Biz...02#xx3104702xx
When you modify that code as I did then you can use that RTB together wiz the canvas created by that control.
Read the comments too and especially look for the corrections of code I did as 'nussknacker' there
Jonny Poet
To be Alive is depending on the willingsness to help others and also to permit others to help you. So lets be alive. !
Using Code Tags makes the difference: Code is easier to read, so its easier to help. Do it like this: [CODE] Put Your Code here [/code]
If anyone felt he has got help, show it in rating the post.
Also dont forget to set a post which is fully answered to 'resolved'. For more details look to FAQ's about Forum Usage. BTW I'm using Framework 3.5 and you ? My latest articles : Creating a Dockable Panel-Controlmanager Using C#, Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.