Hi jeeswg, thanks for the links and the scripts. The main idea here for me was, when copying formatted text, to be able to get what Ctrl-C does under the hood onto the clipboard. The reason is that ( besides whatever else the Windows clipboard does) it allows pasting the content in either formatted or unformatted text with just Ctrl-V, depending on the application. My previous efforts allowed getting RTF from a file into the clipboard, but only the RTF would paste with Ctrl-V. In other words, whatever I copied wouldn't transfer with just Ctrl-V as unformatted text to, for example, Notepad.
A couple of hours ago I found
this thread with DigiDon's RichEdit OleCallback.ahk function. Now I can pull RTF that contains images directly out of a file and paste it.
RTFtoClipCallback.ahk
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
}
RTFtoClipExampleCB (Includes the script above)
Code: Select all
SetWorkingDir, %A_ScriptDir%
#Include RTFtoClipCallback.ahk
#Persistent
SetWorkingDir, %A_ScriptDir%
;~ RTFtoClip("MyRTF.rtf")
FileSelectFile, rtfFile,,,,RichText Files (*.rtf)
If(rtffile<>"")
RTFtoClip(rtfFile)
else {
msgbox You did not pick a file!`nThe script will exit.
ExitApp
}
ExitApp
and DigiDon and just me's RichEdit OleCallback.ahk:
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
}
I run the script, which pulls the content of the RTF file into the transparent GUI, copies it to the clipboard, and exits.
The pasting is done manually with Ctrl-V.
The only thing the script does is get the RTF content (not code) of the RTF file onto the clipboard.
Regards,
burque505