Click here to Skip to main content
Click here to Skip to main content

CRulerRichEditCtrl - a complete RTF mini-editor

By , 17 May 2005
 

Sample Image - rulerricheditctrl.gif

Introduction

The RTF-control is a very useful beast, but it takes a nerve-grating amount of code to accomplish even the most basic formatting tasks. Adding the capabilities to easily edit formatted text is often a boon to an application, but taking this amount of work? Why not some commands to get and set the RTF directly? Save and load to a file? Built-in editing buttons?

CRulerRichEditCtrl is just such a control (OK, combo of controls, actually). It can be added to a dialog box or a form view (it can, of course also be added to a CView, but then one might want to consider basing the application on WordPad instead...). It contains a mini-toolbar with formatting combos and buttons, a ruler that displays either inches or centimeters as well as the tabulator settings (which can be dragged around) and an embedded RTF-control. The complete control can be compiled for Unicode and uses Riched20.dll.

The package

CRulerRichEditCtrl consists of four main classes:

  • CRulerRichEditCtrl - the control itself, derived from CWnd. This is the class you manipulate in your application. This class also contains the ruler.
  • CRulerRichEdit - a CRichEditCtrl wrapper for an embedded RTF-control. The package uses its own class, as it needs to handle scrollbar messages, among other things.
  • CRRECRuler - a CWnd-derived class for the editor ruler.
  • CRRECToolbar - a CToolBarCtrl-derived class for the editor toolbar.

some helper classes:

  • CTextFile - for loading and saving the contents of the control (see this article for this class).
  • CStdGrfx - a series of static functions to draw in the system colors. This helper is taken from this article.
  • CFontComboBox - a font combo, displaying the installed fonts.
  • CSizeComboBox - a simple combo with predefined font sizes.

and a toolbar resource (bitmap and rc-file) for the built-in toolbar.

The toolbar

The toolbar controls and buttons are, from the left to the right:

  • Font name (a combobox where the user can set the font name of the selected text).
  • Font size (a combo where the user can set the size of the selected text).
  • Font (set the font for the selected text. The common font dialog is displayed.).
  • Color picker (set the color of the text. A color picker is displayed.).
  • Bold (make the selected text bold).
  • Italic (make the selected text italic).
  • Underline (underline the selected text).
  • Left-align (left align selected text or paragraph).
  • Center (center selected text or paragraph).
  • Right-align (right align selected text or paragraph).
  • Indent (indent the selected text or paragraph to the next tab-position).
  • Outdent (outdent the selected text or paragraph to the previous tab-position).
  • Bullets (make the selected text or paragraph bulleted).

The button handlers are located in the parent, but the toolbar class handles selection changes for the comboboxes as well as functions to update them as the text selection changes.

The toolbar can be hidden/displayed with a call to ShowToolbar. IsToolbarVisible will return the visibility state of the toolbar.

The ruler

The ruler displays a scale in either inches or centimeters. Tabulator markers are placed at the tab positions (there are 32 of them). The tabs can be changed by clicking and dragging the small markers on the ruler (yes, I know they are small and hard to hit). Tabs can't be moved before or after other tabs, or the start or end of the ruler.

Mouse messages (WM_LBUTTONDOWN, WM_MOUSEMOUSE, WM_LBUTTONUP) are handled by the ruler control. They are passed on with SendMessage to the parent using a registered window message, urm_RULERACTION. The parent handles dragging and setting the tabs.

The display mode of the ruler, inches or centimeters, can be changed with a call to SetMode, and gotten with GetMode.

The ruler can be hidden/displayed with a call to ShowRuler. IsRulerVisible will return the visibility state of the ruler.

The RTF stuff

From code, you can save or load the contents of the RTF-control with Save or Load. They will even display a CFileDialog automatically, if you don't submit a filename.

You can get or set the RTF contents directly with GetRTF or SetRTF.

You can set text, unformatted, to the control by calling SetWindowText. GetWindowText returns the text, GetWindowTextLength the number of characters in the control.

The RTF-control itself can be accessed directly by a call to GetRichEditCtrl.

Using the code

CRulerRichEditCtrl derives from CWnd, and can be used as such. It contains resources, so a little setup is necessary:

  • Add the cpp- and h-files to your project.
  • Include RulerRichEditCtrl.rc in the rc2-file of your project (you'll find it in the res-directory).
  • Declare a CRulerRichEditCtrl-member in the parent class and call CRulerRichEditCtrl::Create to create it.

Points of interest

This project is actually a complete fiasco. I intended to further investigate the implications of the edit rectangle for multi line edit boxes and RTF-controls (see this article and this).

"How about a complete mini-editor, with a ruler for graphical manipulation of the tab-settings, and perhaps even some common formatting buttons - ready to plunk down into an app with minimum effort", I thought (although not in English...). I started with not a small amount of enthusiasm, implementing the ruler and the communication/synchronization between it and the RTF-control. Imagine my annoyance when I realized that the vertical scrollbar would extend from the top of the control, not the top of the edit rectangle, and the initial idea was completely useless! I had, however, written so much code that I felt it to be an almost criminal waste not to do something with the code, and thus the solution to pack sub-controls in a parent CWnd. And it will still save development time, albeit with a somewhat more conventional solution - as well as demonstrate things like dragging and drawing, registered messages, control synchronization, simple RTF-streaming and such things.

First, I had the control style ES_AUTOHSCROLL for the embedded RTF-control. This revealed a bug in the control - evident in WordPad as well. Scroll messages are not sent when the max. horizontal position is reached. This means that the text scrolls on, but the ruler will not be synchronized. Sigh. Anyhow, I've left the style as an option for those who need it - if the last parameter in CRulerRichEditCtrl::Create is TRUE, the RTF-control will have the AutoHScroll style set.

Drawing should normally only be done in an OnPaint or OnDraw handler for a window. Otherwise, the drawing will be destroyed if the user switches to another application and back again, or the window is covered and uncovered for some other reason. Tracking is the one exception I can come to think of, and here I do it. Not only that, I draw over two child windows from a parent, but the alternative - creating a special "dragger"-window with the ruler line - is definitely overkill in this situation, in my opinion.

History

  • 23/4 2004 Initial version.
  • 16/5 2005 A complete re-write, with Unicode-support and a redesigned toolbar.

Credits

First of all, this is hardly my control any longer. The Unicode-adaptation was made by Iain Clarke, who also changed the toolbar to a proper one. Furthermore, he proposed the design changes for the toolbar, and is really far more than a co-author of this version. The credits for everything that is better goes to him, and blame for substandard implementation to me.

I've also used code from other articles here on CodeProject:

At the bottom of the text-file handling class CTextFile now lies CStdioFileEx by David Pritchard. I've taken the liberty of removing a few compile warnings, other than that, this excellent class worked straight away as a plug-in replacement for CStdioFile. Recommended, get it here [^]!

For the toolbar, I've added Chris Maunder's color picker (or perhaps rather colour picker). I would've liked to be able to add some stuff to this control and send the enhancements back to Chris, but to my dismay, the control was already as complete as could be wished. You'll find the picker here[^].

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

About the Author

Johan Rosengren
Software Developer (Senior) Abstrakt Mekanik AB
Sweden Sweden
45 years old, married, three kids.
 
Started with computers more than 20 years ago on a CBM-64.
 
Read Theoretical Philosophy at the University of Lund.
 
Working as a C++ consultant developer.
 
Science-fiction freak. Enjoy vintage punkrock.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralPaste tables from Word or WordPad into this rich edit controlmemberAlexandru Matei2-Nov-10 21:52 
Hi,
 
Could you please provide ideas how to paste simple tables (e.g. two rows, two columns) from Microsoft Word or WordPad into this editor?
 
After pasting from Word or Wordpad into this rich edit control, the table is not displayed correctly.
 
Any help is appreciated.
 
Thank you.
Generalthank youmemberfuturejo17-Feb-10 6:24 
This was a big help
QuestionSize of the text in the CRulerRichEditmemberLexaja837-Aug-08 1:16 
Hi @all,
I used this class in my application and now I am trying to print a CRulerRichEditCtrl! Everything works fine, just one thing does not work.
I use FormatRange and DisplayBand to print the CRichEditCtrl, but I don't know how to find out at which point on my paper the application stops printing. I want to print another line of text after the CRichEditCtrl and so I need to know, where I can print further.
Can anybody tell me what I have to do?
 
Sorry for my english Wink | ;-)
 
Greetings,
Lexaja
GeneralTexts in Two ColumnsmemberhINTModuleState5-Aug-08 0:44 
Hello there.
Is it possible to layout the edit text context in form of two columns ?
ie there should be a fictiouness vertical separator in the middle such that text is first draw to the left and then completed starting at the top of the right region ?
Thank you.
 
Our Philosophy, Mohammed Baqir Al Sadr

GeneralRe: Texts in Two ColumnsmemberJohan Rosengren9-Aug-08 20:39 
The RTF-control is not supporting this. I imagine it would be possible to do by hand (two controls, perhaps, or using the built in table capabilities?) - I do believe, however that it would be quite complicated to implement.
QuestionLicense?memberwukurtis3-Jun-08 18:35 
Hi there, great class and thank you for writing it.
Is it possible to use this class in a commercial application?
thanks.
AnswerRe: License?memberJohan Rosengren4-Jun-08 6:42 
The parts I've written are in the public domain. The control, however, uses code from two other articles as stated above. One (the color picker) is published under the The Code Project Open License (CPOL), the other - the CStdioFile class, has no licence at all. You might want to check with the two writers of those articles.
GeneralCan't copy&pastememberhiscom27-Feb-08 14:25 
in FormView.
GeneralRe: Can't copy&pastememberJohan Rosengren28-Feb-08 8:33 
If memory serves, you had to - at least MFC under MSVC 6.0, add code to accomplish this. It existed a component giving copy & paste support - you'll just have to check CFormView on MSDN.
AnswerRe: Can't copy&pastemembercapella27-Sep-11 19:31 
remove the copy & paste accelerator items,it will do work.
QuestionEmbedded images in a RTF file.memberdel Fuego7-Jan-08 7:28 
The demo does not display embedded images already present in a RTF file. Does your control support embedded images? If it does, then I have a great need for your control.
GeneralRe: Embedded images in a RTF file.memberJohan Rosengren10-Jan-08 19:03 
It does not, unfortunately. But I've noticed the article http://www.codeproject.com/KB/edit/COleRichEditCtrl.aspx[^] here on CodeProject, which would seem to be a fine starting point to enable this.
QuestionHow do I use that control inside a CView classmemberalamgir mohammed17-Dec-06 19:34 
Hi
Is is possible to use it inside a CView (or derived class)? If yes, how? I dont want to use CRichEditView class (and the associated Doc one). Also is there any way of forcing with richedit.dll would be loaded?
 
thanks
 

AnswerRe: How do I use that control inside a CView classmemberJohan Rosengren19-Dec-06 8:27 
You could make an instance of the control a member of a plain vanilla view, resizing it in the view OnSize-handler. A specific DLL is already loaded by the CRulerRichEditCtrl constructor, you might want to modify this.
GeneralRe: How do I use that control inside a CView classmemberalamgir mohammed20-Dec-06 20:19 
Thanks a lot Johan
The resize is not working. Assertion fails. I did this: (m_rtf is the CRichEditRulerCtrl type member of CView derived class).
 

void CRTFCtrlTestView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if(m_rtf.GetSafeHwnd())
{
m_rtf.MoveWindow(0, 0, cx, cy);
 
}
}
 

GeneralRe: How do I use that control inside a CView classmemberJohan Rosengren26-Dec-06 23:25 
You might want to break into the code when the assertion triggers. By pressing - if memory serves - the middle button, the line with the assert from the MFC source code will be displayed. More often than not, this gives a clear indication what has gone wrong.
General[Solved]Re: How do I use that control inside a CView classmemberalamgir mohammed27-Dec-06 14:10 
Hi Johan
Finally got it working. The fact is MoveWindow wont work, dont know why.
 
This piece works:
 
GetClientRect(&rect);
m_Rtf.SetWindowPos(&wndTop, 0,0, rect.right-rect.left, rect.bottom-rect.top, SWP_SHOWWINDOW);

 
(thanks to David Kruglinsky)
 
The toolbar bitmap was also not loading.
 
regards.
 
alam

GeneralNeed Support to link it with url , e-mailmemberamit.dgupta30-Nov-06 22:16 
Hello,
GeneralRe: Need Support to link it with url , e-mailmemberJohan Rosengren1-Dec-06 8:35 
this was a bit brief, I guess the body got lost somewhere Smile | :)
GeneralLittle Problem on Win 2003memberGideonMeyer31-Oct-06 3:12 
Hi. Thanks for your good Rich Edit Implementation. It works very fine, but i got a Problem on a Windows 2003 Server. The Rich Edit Box is not Displayed. Any guess, what might cause this?
Thanks a lot
GeneralRe: Little Problem on Win 2003memberJohan Rosengren31-Oct-06 7:18 
Most likely because the RTF-control is missing on it. I've no idea on the redistribution rules, and must therefore unfortunately recommend a search on MSDN (www.msdn.microsoft.com). Riched20.dll is the dll containing the control.
QuestionRTF Documents greater than 30 MB ?member@thehop13-Jul-06 6:36 
Hello,
 
I'm End-User and looking for a RTF Editor that can handle
bigger Files than 30 MB. Windows WordPad limits ca. 28 MB.
 
Your Demo.exe (and many RTF Editors i tested)freezing, when
I wan't start a 28MB.RTF(Wordpad load this File in 3 sec.)
 
Is there a Way to create a RTF Editor for Big Documents?
 
salü
@thehop
AnswerRe: RTF Documents greater than 30 MB ?memberJohan Rosengren14-Jul-06 6:55 
You might want to experiment with the LimitText method of the control. You might perhaps also want to think of ways to split that amount of data, rest assured, no one will ever have the patience to read that much Smile | :)
GeneralBig at Control Creation timememberIain Clarke24-Apr-06 4:53 

Not a particularly big thing, but if you call ShowRuler / ShowToolbar (FALSE) before creating the control, the show state is ignored in CreateRuler / CreateToolbar.
 
The corrected code (without comments) is below.
 
Iain.
 
BOOL CRulerRichEditCtrl::CreateToolbar()
{
 
	CRect rect;
	GetClientRect( rect );
 
	CRect toolbarRect( 0, 0, rect.right, TOOLBAR_HEIGHT );
	BOOL bReturn = m_toolbar.Create( this, toolbarRect );
 
	ShowRuler (m_showRuler);
 
	return bReturn;
}
 
BOOL CRulerRichEditCtrl::CreateRuler()
{
 
	CRect rect;
	GetClientRect( rect );
 
	CRect rulerRect( 0, TOOLBAR_HEIGHT, rect.right, TOOLBAR_HEIGHT + RULER_HEIGHT );
	BOOL bReturn = m_ruler.Create( rulerRect, this, RULER_CONTROL );
 
	ShowRuler (m_showRuler);
 
	return bReturn;
 
}

GeneralRe: Big at Control Creation timememberJohan Rosengren24-Apr-06 6:06 
Hoho! The bug count is creeping upwards, soon time for an update, I should think.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130617.1 | Last Updated 18 May 2005
Article Copyright 2004 by Johan Rosengren
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid