Formatted Text via RichEdit and TOM - by just me

Helpful script writing tricks and HowTo's
Posts: 547
Joined: 22 Jan 2017, 19:37

Formatted Text via RichEdit and TOM - by just me

12 Mar 2018, 10:28

I found this tutorial by just me in the German forum, and thought it would be useful for those who come here.
With just me's kind permission, I offer this translation.
MyRTF.PNG (29.36 KiB) Viewed 497 times

As a developer, every now and then you might need to display formatted text in a GUI. AHK does not provide suitable control for this. AHK 1. 1 offers two possibilities for embedding further controls registered in the system:
• ActiveX
• Custom
As a rule, ActiveX controls are COM objects that can only be integrated with a GUI in a way that permits use similar to that of built-in controls.

Custom controls usually behave similar to built-in controls. You can assign variables and subroutines, for example. In principle, all built-in controls can also be used as custom controls. That offers few practical benefits.

For 'simple' output of formatted text, there are two alternatives:
1. HTML -> MSIE-Browser Control (ActiveX)
2. RTF -> RichEdit Control (Custom)
We'll limit ourselves here to the second variant (RTF), and the implementation of custom controls.

RichEdit Control

Like the Edit Control, the RichEdit Control is one of the controls provided by Microsoft via the system, but unlike the 'normal' Edit Control, it has not yet been integrated into AHK..

Some time ago I wrote a RichEdit Class, which allows integrating RichEdit Controls into your own GUIs. The actual reason for this was that I needed a way to print formatted text out of AHK without being dependent on any other application. Nonetheless, I equipped the class with a lot of features and methods only used for editing. This makes the whole package a bit on the bulky side, and it requires a bit of training and practice to use.

While I was developing the class, I kept running across documentation for the Text Object Model (TOM). At first I couldn't get very far with it, and even later I remained a bit leery of getting used to this … 'stuff'. Recently I found this post by teadrinker, motivating me to take a closer look at it. I realized that TOM can make the handling of RichEdit Controls for simple tasks, such as the display of RTF files, much easier. Thus, the following tutorial!

Let's get started!

Step 1:

The RichEdit control is provided and registered by the system library msftedit. dll. From WinXP on, the control class registered is RICHEDIT50W. To be able to use the RichEdit control, the script has to explicitly load this dll, i.e.:

Code: [Select all] [Download] GeSHi © Codebox Plus

RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")

Step 2:

Once you've done that, you can add your RichEdit control to the GUI as a custom control:

Code: [Select all] [Download] GeSHi © Codebox Plus

Gui, Add, Custom, ClassRICHEDIT50W vRE hwndHRE

Because AHK doesn't recognize the controls added as being Custom, only the essential styles are set automatically, such as: Eg WS_CHILD, WS_TABSTOP, WS_VISIBLE. Scrollbars can be set with the usual options HScroll / VScroll, because they are not control specific (WS_HSCROLL, WS_VSCROLL). However, even with a height specification such as h400 or r20, AHK can't tell it's a multi-line RichEdit Control. You have to set the appropriate style ES_MULTILINE (0x04) yourself. This applies to all other possible RichEdit styles too, for example, ES_READONLY (0x0800). For a multi-line, read-only RichEdit Control with a width and height of 400 pixels each and a vertical scrollbar, you need:

Code: [Select all] [Download] GeSHi © Codebox Plus

Gui, Add, Custom, ClassRICHEDIT50W w400 h400 vRE hwndHRE +VScroll +0x0804 ; ES_MULTILINE | ES_READONLY

Step 3:

Now we have an empty RichEdit Control. To get this to display an existing RTF file, we need the associated TOM object, more specifically the TextDocument object. This can be elicited by the control via the message EM_GETOLEINTERFACE. How to do that is roughly described here. For AHK, it looks like this (without going into the ComObj instructions):
• Here, we send an EM_GETOLEINTERFACE message to the RichEdit control. This returns a pointer to the IRichEditOle interface.

Code: [Select all] [Download] GeSHi © Codebox Plus

DllCall("SendMessage", "Ptr", HRE, "UInt", 0x043C, "Ptr", 0, "PtrP", IRichEditOle, "UInt") ; EM_GETOLEINTERFACE

• Now, using ComObjQuery (), we get a pointer to the ITextDocument interface,

Code: [Select all] [Download] GeSHi © Codebox Plus

ITextDocument := ComObjQuery(IRichEditOle, IID_ITextDocument)

• which we in turn transform, via ComObject() into a TextDocument object.

Code: [Select all] [Download] GeSHi © Codebox Plus

DocObject := ComObject(9, ITextDocument, 1)

Here's an example of a complete function:

Code: [Select all] [Download] GeSHi © Codebox Plus

GetTomDoc(HRE) {
; TextDocument Objekt für ein RichEdit Control abrufen
Static IID_ITextDocument := "{8CC497C0-A1DF-11CE-8098-00AA0047BE5D}"
DocObj := 0
If DllCall("SendMessage", "Ptr", HRE, "UInt", 0x043C, "Ptr", 0, "PtrP", IRichEditOle, "UInt") { ; EM_GETOLEINTERFACE
DocObj := ComObject(9, ComObjQuery(IRichEditOle, IID_ITextDocument), 1) ; ITextDocument
Return DocObj

Step 4:

Now we've got a RichEdit control and its TextDocument object. This object has the Open method, used to read files into the RichEdit control. The parameter Flags determines what content the file has. For files with RTF text, the flag tomRTF (0x01) is displayed. You can also specify that the file content being read in should a) completely replace the content of the RichEdit control or b) be inserted (tomPasteFile (0x1000).) That's all that's needed to display the file:

Code: [Select all] [Download] GeSHi © Codebox Plus

DocObj.Open("MeineDatei.rtf", 0x01, 0)

Putting it all together

Back to work. Start Microsoft WordPad and create a RichText file. Save it with the name MyRTF.rtf in the same folder as the following script:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus

Additional considerations for Win 8+

With Win 8, Microsoft distributed a significantly updated RichEdit control. For one thing, the display of 'embedded objects' like images is greatly simplified. For RTF files created and displayed under Win 8, no further action is required. However, per my tests, the RichEdit control must not be ReadOnly when the file is read. Why? Because you can't just isolate and remove this style, you have to use the EM_SETOPTIONS message after the control has been created and populated:

Code: [Select all] [Download] GeSHi © Codebox Plus

DllCall("SendMessage", "Ptr", HRE, "UInt", 0x044D, "Ptr", 0x02, "Ptr", 0x0800) ; EM_SETOPTIONS: ECOOP_OR, ECO_READONLY

Return to “Tutorials”

Who is online

Users browsing this forum: No registered users and 4 guests