EDIT: This is based on code from just me's TOM tutorial.
EDIT: The errors described in the first edit were due to corrupted source RTF. Copying from just about anywhere seems to work (including images from browsers). I'm leaving the other scripts in just in case someone finds them useful. Also, I now have a version of "Poor Man's Rich Edit" that opens rich text files, and accepts pasted rich text, on Win7 64-bit. I don't have Win10 available at the moment to test "Poor Man's Rich Edit" with a mod, but I believe the newer version of "msftedit.dll" provided in Win8.1+ may obviate the need for the mod I've made. If there is any interest, I'll post the modded "Poor Man's Rich Edit" and supporting #Includes. I have, though, added a screenshot.
RE1.1.ahk:
Spoiler
Version 3.0, context menu added, redundant code removed.
Code: Select all
#Include RichEdit OleCallback.ahk
RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")
Gui, +hwndhGui
Gui +LastFound
;Winset, Trans, 100
Gui, Margin, 10, 10
Gui, Font, s10, Arial
Gui, Add, Custom, ClassRICHEDIT50W w400 h500 vRE hwndHRE +VScroll +0x1004 ; ES_MULTILINE | ES_WANTRETURN
RE_SetOleCallback(HRE) ; Thanks to DigiDon and just me. This uses a function from RichEdit OleCallback.ahk
RE_GetDocObj(HRE)
GetTomDoc(HRE)
Gui, Show, , RichEdit
return
Escape::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
}
RE_GetDocObj(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
}
Spoiler
Here's RichEdit OleCallback.ahk, so you don't have to spelunk for it.
Code: Select all
#NoEnv
#Warn
SendMode Input
#SingleInstance force
#Include RichEdit OleCallback.ahk
RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")
Gui, +hwndhGui
Gui +LastFound
Gui, Margin, 10, 10
Gui, Font, s10, Arial
;Gui, Add,Edit, h200 w200
Gui, Add, Custom, ClassRICHEDIT50W w400 h500 vRE hwndHRE +VScroll +0x1004 ; ES_MULTILINE | ES_WANTRETURN
RE_SetOleCallback(HRE) ; Thanks to DigiDon and just me. This uses a function from RichEdit OleCallback.ahk
GetTomDoc(HRE)
OnMessage(0x204, "RightClick") ; WM_RIGHTBUTTONDOWN
Gui, Show, , RichEdit
return
RightClick(wParam, lParam)
{
X := lParam & 0xFFFF
Y := lParam >> 16
Gosub, MakeMenu
return
}
^!m::
GuiContextMenu:
gosub, MakeMenu
;MsgBox Context Menu: %A_ThisLabel%
return
Escape::
GuiClose:
ExitApp
MakeMenu:
Menu, RTE_Menu, Add, &Copy, Copy ; Simple context menu
Menu, RTE_Menu, Add, &Paste, Paste ;
Menu, RTE_Menu, Add, Cu&t, Cut ;
Menu, RTE_Menu, Add, Select &All, All ;
Menu, RTE_Menu, Add, &Undo, Undo ;
Menu, RTE_Menu, Show
return
Copy:
Send, ^c
return
Paste:
Send, ^v
return
Cut:
Send, ^x
return
All:
Send, ^a
return
Undo:
Send, ^z
return
return
GetTomDoc(HRE) {
; Get the document object of the specified RichEdit control
IRichEditOle := "" ;Added to stop warning messages
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
}
Code: Select all
;=========================================
; Name: RichEdit OleCallback
; Namespace: RichEdit
; Authors: just me & DigiDon
; Description: IRichEditOleCallback interface AHK implementation for the RichEdit control
;=========================================
;
;=========================================
;RE_SetOleCallback
;Need to call this function just after creation of the RichEdit control
;HRE - Handle of the RichEdit Control
;ex: RE_SetOleCallback(RE2.HWND)
;Specify your contextmenu in IREOleCB_GetContextMenu() if you have one because it won't be called otherwise
;and disable existing dropfiles special GUI label for the RichEdit Control
;Then you can start dragging and dropping any document into the RichEdit field.
;=========================================
RE_SetOleCallback(HRE) {
; EM_SETOLECALLBACK = 0x0446
SendMessage, 0x0446 , 0, % IREOleCB_Create() , , ahk_id %HRE%
If (ErrorLevel = "FAIL") || (ErrorLevel = 0) {
MsgBox, 16, %A_ThisFunc%, ERROR: %ErrorLevel%!
Return False
}
Return True
}
; ================================================================================================================================
; IRichEditOleCallback -> msdn.microsoft.com/en-us/library/windows/desktop/bb774308(v=vs.85).aspx
; ================================================================================================================================
IREOleCB_Create() {
Static VTBL := [RegisterCallback("IREOleCB_QueryInterface")
, RegisterCallback("IREOleCB_AddRef")
, RegisterCallback("IREOleCB_Release")
, RegisterCallback("IREOleCB_GetNewStorage")
, RegisterCallback("IREOleCB_GetInPlaceContext")
, RegisterCallback("IREOleCB_ShowContainerUI")
, RegisterCallback("IREOleCB_QueryInsertObject")
, RegisterCallback("IREOleCB_DeleteObject")
, RegisterCallback("IREOleCB_QueryAcceptData")
, RegisterCallback("IREOleCB_ContextSensitiveHelp")
, RegisterCallback("IREOleCB_GetClipboardData")
, RegisterCallback("IREOleCB_GetDragDropEffect")
, RegisterCallback("IREOleCB_GetContextMenu")]
Static HeapSize := A_PtrSize * 20 ; VTBL pointer + 13 method pointers + 4 unused pointers + reference count + HEAP handle
Static HeapOffset := A_PtrSize * 19 ; offset to store the heap handle within the heap
Heap := DllCall("HeapCreate", "UInt", 0x05, "Ptr", 0, "Ptr", 0, "UPtr")
IREOleCB := DllCall("HeapAlloc", "Ptr", Heap, "UInt", 0x08, "Ptr", HeapSize, "UPtr")
Addr := IREOleCB
Addr := NumPut(Addr + A_PtrSize, Addr + 0, "UPtr")
For Each, CB In VTBL
Addr := NumPut(CB, Addr + 0, "UPtr")
NumPut(Heap, IREOleCB + HeapOffset, "UPtr")
Return IREOleCB
}
; --------------------------------------------------------------------------------------------------------------------------------
; IUnknown::QueryInterface
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_QueryInterface(IREOleCB, REFIID, ByRef IFPtr) {
OutputDebug, %A_ThisFunc%
Return 0 ; S_OK
}
; --------------------------------------------------------------------------------------------------------------------------------
; IUnknown::AddRef
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_AddRef(IREOleCB) {
Static RefOffset := A_PtrSize * 18
OutputDebug, %A_ThisFunc%
NumPut(RefCount := NumGet(IREOleCB + RefOffset, "UInt") + 1, IREOleCB + RefOffset, "UInt")
Return RefCount
}
; --------------------------------------------------------------------------------------------------------------------------------
; IUnknown::Release
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_Release(IREOleCB) {
Static RefOffset := A_PtrSize * 18
, HeapOffset := A_PtrSize * 19
OutputDebug, %A_ThisFunc%
NumPut(RefCount := NumGet(IREOleCB + RefOffset, "UInt") - 1, IREOleCB + RefOffset, "UInt")
If (RefCount = 0) {
Heap := NumGet(IREOleCB + HeapOffset, "UPtr")
DllCall("HeapDestroy", "Ptr", Heap)
}
Return RefCount
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::GetNewStorage
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_GetNewStorage(IREOleCB, IStoragePtr) {
OutputDebug, %A_ThisFunc%
; msdn.microsoft.com/en-us/library/windows/desktop/aa378977(v=vs.85).aspx
If !(HR := DllCall("Ole32.dll\CreateILockBytesOnHGlobal", "Ptr", 0, "Int", 1, "PtrP", ILockBytes)) {
; msdn.microsoft.com/en-us/library/windows/desktop/aa380324(v=vs.85).aspx
; STGM_READWRITE = 0x02, STGM_SHARE_EXCLUSIVE = 0x10, STGM_CREATE = 0x1000
If (HR := DllCall("Ole32.dll\StgCreateDocfileOnILockBytes", "Ptr", ILockBytes, "UInt", 0x1012, "UInt", 0, "PtrP", IStorage))
ObjRelease(ILockBytes)
Else
NumPut(IStorage, IStoragePtr + 0, "UPtr")
}
Return HR
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::GetInPlaceContext - not implemented
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_GetInPlaceContext(IREOleCB, Frame, Doc, FrameInfo) {
OutputDebug, %A_ThisFunc%
Return 0x80004001 ; E_NOTIMPL
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::ShowContainerUI - not implemented
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_ShowContainerUI(IREOleCB, Show) {
OutputDebug, %A_ThisFunc%
Return 0x80004001 ; E_NOTIMPL
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::QueryInsertObject - returns S_OK
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_QueryInsertObject(IREOleCB, CLSID, STG, CP) {
OutputDebug, %A_ThisFunc%
Return 0 ; S_OK
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::DeleteObject - returns S_OK
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_DeleteObject(IREOleCB, OleObj) {
OutputDebug, %A_ThisFunc%
Return 0 ; S_OK
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::QueryAcceptData - returns S_OK
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_QueryAcceptData(IREOleCB, DataObj, Format, Operation, Really, MetaPic) {
OutputDebug, %A_ThisFunc%
Return 0 ; S_OK
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::ContextSensitiveHelp - not implemented
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_ContextSensitiveHelp(IREOleCB, EnterMode) {
OutputDebug, %A_ThisFunc%
Return 0x80004001 ; E_NOTIMPL
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::GetClipboardData - not implemented
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_GetClipboardData(IREOleCB, CharRange, Operation, DataObj) {
OutputDebug, %A_ThisFunc%
Return 0x80004001 ; E_NOTIMPL
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::GetDragDropEffect - returns S_OK
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_GetDragDropEffect(IREOleCB, Drag, KeyState, Effect) {
OutputDebug, %A_ThisFunc%
Return 0 ; S_OK
}
; --------------------------------------------------------------------------------------------------------------------------------
; IRichEditOleCallback::GetContextMenu - not implemented
; --------------------------------------------------------------------------------------------------------------------------------
IREOleCB_GetContextMenu(IREOleCB, SelType, OleObj, CharRange, HMENU) {
;PUT YOUR CONTEXT MNU HERE
;Menu, RN_ContextMenu, Show
; OutputDebug, %A_ThisFunc%
Return 0x80004001 ; E_NOTIMPL
}
The attachment RichEditTests.7z is no longer available
If you get RTF into the clipboard with this, it can paste onto the script above.
Spoiler
This requires, in turn, RTFtoClipCallback.ahk:
Code: Select all
SetWorkingDir, %A_ScriptDir%
#Include RTFtoClipCallback.ahk
#Persistent
SetWorkingDir, %A_ScriptDir%
FileSelectFile, rtfFile,,,,RichText Files (*.rtf)
If(rtffile<>"")
RTFtoClip(rtfFile)
else {
msgbox You did not pick a file!`nThe script will exit.
ExitApp
}
ExitApp
Spoiler
That's a lot of hoops to jump through.Code: Select all
#Include RichEdit OleCallback.ahk
SetWorkingDir, %A_ScriptDir%
global rtffile := ""
global TomDoc := ""
global TomFile := ""
global RE := ""
RTFtoClip(rtffile) {
;msgbox %rtffile%
DetectHiddenWindows, On
clipboard =
RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")
Gui, +hwndhGui
Gui +LastFound
Winset, Transparent
Gui, Margin, 10, 10
Gui, Font, s10, Arial
Gui, Add, Custom, ClassRICHEDIT50W w400 h400 vRE hwndHRE +VScroll +0x0804 ; ES_MULTILINE | ES_READONLY
RE_SetOleCallback(HRE) ; Thanks to DigiDon and just me. This uses a function from RichEdit OleCallback.ahk
Gui, Show, , RichEdit
TomDoc := GetTomDoc(hRE)
TomFile := rtffile
TomDoc.Open(TomFile, 0x01, 0)
ControlFocus, ahk_class RICHEDIT50W1
Send, ^a^c
ControlClick, RICHEDIT50W1, RichEdit
}
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
}
And an animated GIF of its function, impoverished though it may be:
- RE.gif (20.12 KiB) Viewed 911 times
Regards,
burque505
- pmrte.png (53.24 KiB) Viewed 849 times