ITextSevices -- Using the Windowless RichEdit for Drawing RTF

Environment: VC6 SP4, Platform SDK November 2001 recommended

Introduction to the Windowless RichEdit

It is a little-known fact that the RichEdit from version 2.0 onwards comes with a COM interface to drive it. To use this interface, you don't need to create a RichEdit window, so it is perfect for applications that don't need the extra handling required by having just another window. The example given here illustrates this point by providing a class that can draw RTF text anywhere you'd like.

The main COM interfaces involved are ITextHost, ITextServices, and ITextDocument. When you create a windowless RichEdit, you have to provide it with a class that implements ITextHost. This class is usually quite simple, even more so in my example because I just use it for drawing and don't provide editing capabilities. ITextServices is the main interface you use to communicate with RichEdit. It provides the functions for setting, getting, and drawing the text. Moreover, it lets you send messages to the RichEdit that's hidden behind it. So you can still use all the standard messages such as EM_SETCHARFORMAT. ITextDocument is the interface you can use to bypass the message passing. By using it, you can get an ITextSelection interface to the current selection—an ITextRange interface for any range, for example. These in turn let you get ITextFont objects and so on.

ITextDocument is not specific to the windowless RichEdit, though. When you have created a windowed RichEdit, you can use the EM_GETOLEINTERFACE message to retrieve a COM interface to the RichEdit, anyhow. This interface can be queried for ITextDocument and you will be able to use all its functionality.

Implementing ITextHost

This is where it gets a little complicated. The MSDN documentation on ITextHost is pretty much non-existant, so you have to work from the few indications you get. If you want to implement a fully editable ITextServices object, you will have to fill in all the functions I have left blank in my example. This is because, for the sole purpose of drawing RTF text, you don't need to provide much information to ITextServices, aside from the RTF text, the formatting rectangle, and the HDC. It is recommended that the class that implements ITextHost be a COM class because that's the way ITextServices communicates with it. To make my example easier, I left out the COM bits and provided myself the basic IUnknown functions. It is interesting to note that just after creating the TextServices object, it queries the TextHost for some other interface. I have not been able to figure out what this is, though.

Using the Example Code

All the windowless RichEdit functionality is provided by the CFormattedTextDraw class. It implements ITextHost minimally and also the custom interface (or rather purely abstract class) IFormattedTextDraw. The reason for using IFormattedTextDraw is that you should not call any functions on ITextHost directly; access should always be through IFormattedTextDraw instead of CFormattedTextDraw. The usage of the class can be seen in the Win32Test.cpp file. It is based on the sample "Hello World" Win32 project that VC6 generates. Here is the simplicity with which you use this class:

IFormattedTextDraw *g_Formatter;
BSTR               bstrText;
RECT               rt;
HDC                hdc;

g_Formatter = new CFormattedTextDraw;
// Fill in the Unicode text, the rectangle, and get an HDC
g_Formatter->Draw(hdc, &rt);


To use this code in your own projects, you will have to link with riched20.lib. Moreover, you will most probably get a linker error related to _IID_ITextServices and _IID_ITextHost. If this is the case, open your version of textserv.h (you will find it in the ..\Microsoft SDK\include directory) and comment out the two following lines:

//EXTERN_C const IID IID_ITextServices;
//EXTERN_C const IID IID_ITextHost;


Download demo project - 17 Kb
Download source - 13 Kb


Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • Hurricane Sandy was one of the most destructive natural disasters that the United States has ever experienced. Read this success story to learn how Datto protected its partners and their customers with proactive business continuity planning, heroic employee efforts, and the right mix of technology and support. With storm surges over 12 feet, winds that exceeded 90 mph, and a diameter spanning more than 900 miles, Sandy resulted in power outages to approximately 7.5 million people, and caused an estimated $50 …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds