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.
Regards,
burque505 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
RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")
Once you've done that, you can add your RichEdit control to the GUI as a custom control:
Code: Select all
Gui, Add, Custom, ClassRICHEDIT50W vRE hwndHRE
Code: Select all
Gui, Add, Custom, ClassRICHEDIT50W w400 h400 vRE hwndHRE +VScroll +0x0804 ; ES_MULTILINE | ES_READONLY
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
DllCall("SendMessage", "Ptr", HRE, "UInt", 0x043C, "Ptr", 0, "PtrP", IRichEditOle, "UInt") ; EM_GETOLEINTERFACE
Code: Select all
ITextDocument := ComObjQuery(IRichEditOle, IID_ITextDocument)
Code: Select all
DocObject := ComObject(9, ITextDocument, 1)
Code: Select all
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
ObjRelease(IRichEditOle)
}
Return DocObj
}
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
DocObj.Open("MeineDatei.rtf", 0x01, 0)
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
#NoEnv
SetWorkingDir, %A_ScriptDir%
RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")
Gui, +hwndhGui
Gui, Margin, 10, 10
Gui, Font, s10, Arial
Gui, Add, Custom, ClassRICHEDIT50W w400 h400 vRE hwndHRE +VScroll +0x0804 ; ES_MULTILINE | ES_READONLY
Gui, Show, , RichEdit
TomDoc := GetTomDoc(hRE)
TomFile := "MyRTF.rtf"
TomDoc.Open(TomFile, 0x01, 0)
Return
GuiClose:
ExitApp
GetTomDoc(HRE) {
; Get the document object of the specified RichEdit control
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
ObjRelease(IRichEditOle)
}
Return DocObj
}
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
DllCall("SendMessage", "Ptr", HRE, "UInt", 0x044D, "Ptr", 0x02, "Ptr", 0x0800) ; EM_SETOPTIONS: ECOOP_OR, ECO_READONLY