When enhancing the TRichEdit class, I ran into a couple of problems worth noting. The first is reasonably obvious and the second is likely to be a mystery until reading the VCL source code.
The first problem that I ran into was attempting to send messages to a TRichEdit before the underlying Windows handle was created. For example, if you try to do the following in the form's constructor, it will not work.
::SendMessage(RichEdit1->Handle, EM_EXLIMITTEXT, 0, (LPARAM) 0x7fffffff);
The problem is two-fold: (1) RichEdit1->Handle is not valid at the time the form's constructor is called and (2) The EM_EXLIMITTEXT message does not return a value indicating success or failure. Worse yet, the error can be silent (no abend) if the handle parameter is a valid window handle (zero, for example, is a valid handle). I do not know for sure, but Windows may simply discard invalid messages with invalid handle parameters, so you may never get an error.
I cannot blame anyone for myself for stumbling on this one, though. The next one was much less obvious, at least to me.
The second problem was that the VCL destroys and re-creates the TRichEdit control's underlying Windows handle unexpectedly. For example, and I am working from memory here, changing the control's HideScrollBars and ScrollBars properties causes the VCL to destroy the window and re-create it. This is done because these attributes are set when the window is created -- the Windows API does not supply a way to change them on the fly.
The VCL jumps through some hoops to try to make this transparent. For example, the current contents of the control are saved in a memory stream and reloaded after the window is re-created.
The problem with all of this is that some information about the TRichEdit's current state may get lost in the shuffle. For example, the TRichEditOleCallback code available on this site sends a message to the TRichEdit's true Windows handle to set the Rich Edit OLE callback to point to the TRichEditOleCallback class's OLE handler. The VCL knows nothing about all of this and, thus, does not save and restore the setting. The net result is that, when the Windows handle is destroyed and re-created, the OLE callback functionality is lost.
This Windows handle destruction and re-creation dance happens elsewhere in the VCL in a function called RecreateWnd(). This may affect your TRichEdit unexpectedly. For example, I had placed my TRichEdit on a TTabSheet on a TPageControl. I then added a user option to change the TPageControl's MultiLine property. Guess what when the user changes the MultiLine property, the VCL does a RecreateWnd() on the TPageControl which cascades down to all of its child controls. My TRichEdit just got trashed and re-created.
I do not blame Borland for taking this approach. In fact, I do not think there is a significantly better way given the limitations in the Windows API. And I even suppose that we should expect side-effects when changing property values since that is pretty much what properties are for. However, I do wish that Borland would document these side-effects in the help files.
The good news is that you can override RecreateWnd() in your own TRichEdit-derived class to add the needed functionality.
Copyright © 1998-2001 Thin Air Enterprises and Robert Dunn. All rights reserved.