Versions 2 and later of the Windows rich-edit library come with a
feature known as the windowless rich-edit control. There is no window
handle and no visible control at all, but it provides all the RTF-handling abilities of a normal rich-edit control.
The functionality is exposed via the ITextHost and ITextServices interfaces. To use a windowless
rich-edit control, your program needs to implement the
ITextHost interface. The control will call that
interface’s methods when it requires information from the program
or when it wants to notify the program of something. Your program in turn
calls methods on the control’s ITextServices interface
when it needs the control to do something, such as recalculate its size
or process a keystroke.
There is one major obstacle to using windowless rich-edit controls in
Delphi: Microsoft messed up. The interfaces are declared in the TextServ.h Platform SDK header, but they are declared without using the
proper interface-related macros that appear throughout the rest of the
SDK. Instead, they are just plain C++ pure
virtual classes. The most important omission is the macro that specifies
the calling conventions for all the interface’s methods. Since they
are not explicitly declared as stdcall, they are given the default
thiscall calling convention, which Delphi cannot use. Thus, a Delphi
program cannot call methods on an ITextServices object
created by the rich-edit DLL, and the DLL cannot call methods on an ITextHost
object provided by a Delphi program.
I have written a Delphi unit that solves that problem. After receiving
a new ITextServices interface from the rich-edit library, my
PatchTextServices function wraps the interface reference
within another interface. The implementations of all the wrapper’s
methods are merely stubs that fix up the registers and the stack so that
both sides can talk to each other properly.
In addition to the TextServ.h
declarations in TOM.pas, I also include
PatchTextServices, for wrapping the OS-supplied ITextServices object, and
CreateTextHost, for wrapping a Delphi ITextHost
implementation into something the OS can use.
A simple demonstration of using PatchTextServices and
ITextHost is in the file RTFPaint.pas. It provides a function for
painting an RTF string to a canvas.