Sign in to follow this  
Followers 0

RichEdit UDF

99 posts in this topic

Posted (edited)

Finally, i got the IRichEditOle interface implemented, so that you can use OLE objects :mellow: (Not completely implemented and no good style, but hey, it works!)

The other functions are from GaryFrost, grham, Kip, me and some functions from the forum (collected by Kip)

I put the Functiosn descriptions on PASTEBIN, becuase it's too long to post.

For proper freeing of memory when an error occurs in the OLE interface, you need MemoryDLL.au3. But if you don't include it, the UDF will work, too.

Download located HERE

Example:

;~ Opt("MustDeclareVars", 1)

#include <Misc.au3>
#include <GuiRichEdit.au3>
#include <GuiMENU.au3>
#include <GuiEdit.au3>

Global $FileStreamCallBack = DllCallbackRegister("_EditStreamCallbackFile", "dword", "long_ptr;ptr;long;ptr")
Global $FileStreamStruct = DllStructCreate($tagEDITSTREAM)
DllStructSetData($FileStreamStruct, 3, DllCallbackGetPtr($FileStreamCallBack))

Global $FileStreamInCallBack = DllCallbackRegister("_EditStreamInCallbackFile", "dword", "long_ptr;ptr;long;ptr")
Global $FileStreamInStruct = DllStructCreate($tagEDITSTREAM)
DllStructSetData($FileStreamInStruct, 3, DllCallbackGetPtr($FileStreamInCallBack))

Global $EDITSTREAM_RTFVariable
Global $VariableStreamCallBack = DllCallbackRegister("_EditStreamCallbackVariable", "dword", "long_ptr;ptr;long;ptr")
Global $VariableStreamStruct = DllStructCreate($tagEDITSTREAM)
DllStructSetData($VariableStreamStruct, 3, DllCallbackGetPtr($VariableStreamCallBack))

Global $h_RichEdit, $RichMENU[10]

_Main()

Func _Main()
	Local $msg, $hgui, $button, $bt2, $btFromFile
	Local $mnuOptions, $mnuBKColor, $mnuResetBKColor
	Local $bkcolor, $bkcolor_save = 16777215, $lResult
	Local $btToVariable
	
	$hgui = GUICreate("Rich Edit Example", 500, 550, -1, -1, BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU, $WS_SIZEBOX))
	GUIRegisterMsg($WM_SIZING, "WM_SIZING")
	$h_RichEdit = _GUICtrlRichEdit_Create($hgui, 10, 10, 480, 420, BitOR($ES_WANTRETURN, $WS_HSCROLL, $ES_SUNKEN, $ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL))
;~ 	GUICtrlSetResizing($h_RichEdit, $GUI_DOCKAUTO)
	_GUICtrlRichEdit_SetOLECallback($h_RichEdit)
	$lResult = _SendMessage($h_RichEdit, $EM_SETEVENTMASK, 0, BitOR($ENM_REQUESTRESIZE, $ENM_LINK, $ENM_DROPFILES, $ENM_KEYEVENTS, $ENM_MOUSEEVENTS))
	__GCR_DebugPrint("$h_RichEdit handle: " & $h_RichEdit)
	$lResult = _SendMessage($h_RichEdit, $EM_AUTOURLDETECT, True)
	_GUICtrlRichEdit_InsertText($h_RichEdit, 'Testing' & @CRLF)
	
	$button = GUICtrlCreateButton("Exit", 100, 460, 100, 25)
	$btToVariable = GUICtrlCreateButton("MsgBox RTF", 310, 460, 90, 25)
	$btFromFile = GUICtrlCreateButton("ReadFile", 410, 460, 90, 25)
	$bt2 = GUICtrlCreateButton("Save to File", 200, 460, 100, 25)
	GUICtrlSetTip(-1, "The target-File is: " & @DesktopDir & "\AutoIt_testrtf.rtf")
	GUISetState(@SW_SHOW)
	GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
	HotKeySet("{F8}", "_CharFromPos")
	
	_GUICtrlRichEdit_SetText($h_RichEdit, "This is a test" & @CRLF)
	_GUICtrlRichEdit_AppendText($h_RichEdit, 'http://www.autoitscript.com/forum' & @CRLF)
	_GUICtrlRichEdit_SetSel($h_RichEdit, 0, 15)
	_GUICtrlRichEdit_InsertText($h_RichEdit, "Welcome to AutoIt" & @CRLF)
	_GUICtrlRichEdit_AppendText($h_RichEdit, 'mailto:yourmail@your.com' & @CRLF)
	_GUICtrlRichEdit_AppendText($h_RichEdit, '{\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard' & @CRLF & 'This is some {\b bold} text.\par' & @CRLF & '}' & @CRLF)
	
	_GUICtrlRichEdit_AppendText($h_RichEdit, _RTF_GetBMPRTF(_FindFirstBMP()) & @CRLF)
	
	_GUICtrlRichEdit_SetSel($h_RichEdit, 0, 17)
	__GCR_DebugPrint( "new Undo-Limit: " & _GUICtrlRichEdit_SetUndoLimit($h_RichEdit, 100))
	$RichMENU[0] = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
	$RichMENU[1] = GUICtrlCreateMenuItem("Undo	Ctrl-Z", $RichMENU[0])
	$RichMENU[2] = GUICtrlCreateMenuItem("Redo	Ctrl-Y", $RichMENU[0])
	GUICtrlCreateMenuItem("", $RichMENU[0])
	$RichMENU[3] = GUICtrlCreateMenuItem("Cut	Ctrl-X", $RichMENU[0])
	$RichMENU[4] = GUICtrlCreateMenuItem("Copy	Ctrl-C", $RichMENU[0])
	$RichMENU[5] = GUICtrlCreateMenuItem("Paste	Ctrl-V", $RichMENU[0])
	
	While 1
		$msg = GUIGetMsg()

		Select

			Case $msg = $GUI_EVENT_CLOSE Or $msg = $button ; controls commands don't work here if using wm_command
				Exit
			Case $msg = $bt2
				Local $RTFFile = FileOpen(@DesktopDir & "\AutoIt_testrtf.rtf", 2)
				DllStructSetData($FileStreamStruct, 1, $RTFFile) ; -> Send handle to CallbackFunc
				Local $send = _GUICtrlRichEdit_StreamOut($h_RichEdit, $SF_RTF, $FileStreamStruct)
				FileClose($RTFFile)
				ConsoleWrite($send & @CRLF)
			Case $msg = $btToVariable
				Global $EDITSTREAM_RTFVariable = ""
				Local $send = _GUICtrlRichEdit_StreamOut($h_RichEdit, $SF_RTFNOOBJS, $VariableStreamStruct)
				MsgBox(0, '', $EDITSTREAM_RTFVariable)
				$EDITSTREAM_RTFVariable = ""
			Case $msg = $btFromFile
				Local $RTFFile = FileOpen(@DesktopDir & "\AutoIt_testrtf.rtf", 0)
				DllStructSetData($FileStreamInStruct, 1, $RTFFile) ; -> Send handle to CallbackFunc
				_GUICtrlRichEdit_SetText($h_RichEdit, "")
				Local $send = _GUICtrlRichEdit_StreamIn($h_RichEdit, $SF_RTF, $FileStreamInStruct)
				FileClose($RTFFile)
				ConsoleWrite($send & @CRLF)
			Case $msg = $RichMENU[1]
				_GUICtrlRichEdit_Undo($h_RichEdit)
			Case $msg = $RichMENU[2]
				_GUICtrlRichEdit_Redo($h_RichEdit)
			Case $msg = $RichMENU[3]
				_GUICtrlRichEdit_Cut($h_RichEdit)
			Case $msg = $RichMENU[4]
				_GUICtrlRichEdit_Copy($h_RichEdit)
			Case $msg = $RichMENU[5]
				_GUICtrlRichEdit_Paste($h_RichEdit)
		EndSelect
	WEnd
EndFunc   ;==>_Main

; for PopupMenu
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
	Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR

	$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
	$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
	$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
	$iCode = DllStructGetData($tNMHDR, "Code")
	Switch $hWndFrom
		Case $h_RichEdit
			Select
				Case $iCode = $EN_MSGFILTER
					Local $tMsgFilter = DllStructCreate($tagEN_MSGFILTER, $ilParam)
					If DllStructGetData($tMsgFilter, 4) = $WM_RBUTTONUP Then ; WM_RBUTTONUP
						Local $hMenu = GUICtrlGetHandle($RichMENU[0])
						_SetMenuTexts($hWndFrom, $RichMENU)
						_GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd)
					EndIf
			EndSelect
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func WM_SIZING($hWnd, $uMsg, $wParam, $lParam)
	Local $wh = WinGetClientSize($hWnd)
	ControlMove($h_RichEdit, "", "", Default, Default, $wh[0] - 20, $wh[1] - 130)
EndFunc   ;==>WM_SIZING


;Prog@ndy
Func _FindFirstBMP($dir = @WindowsDir)
	Local $find = FileFindFirstFile($dir & "\*.bmp")
	Local $BMPFile = FileFindNextFile($find)
	FileClose($find)
	Return $dir & "\" & $BMPFile
EndFunc   ;==>_FindFirstBMP

;Prog@ndy
Func _CharFromPos()
	Local $pos = MouseGetPos()
	Local $winpos = WinGetPos($h_RichEdit)
	Local $Char = _GUICtrlRichEdit_CharFromPos($h_RichEdit, $pos[0] - $winpos[0], $pos[1] - $winpos[1])
	MsgBox(0, @error, $Char)
EndFunc   ;==>_CharFromPos

;Prog@ndy
Func _RTF_GetBMPRTF($BMPFile)
	If Not (StringRight($BMPFile,4) = ".bmp") Then Return SetError(1, 0, "")
	Local $Data = FileOpen($BMPFile, 16)
	If FileRead($Data, 2) <> "0x424D" Then Return SetError(1, 0, "")
	FileRead($Data, 12)
	Local $RTF = '{\rtf1{\pict\dibitmap ' & Hex(FileRead($Data)) & '}}'
	FileClose($Data)
	Return $RTF
EndFunc   ;==>_RTF_GetBMPRTF

;Prog@ndy, set thze states of the Context-Menu Items :)
Func _SetMenuTexts($h_RichEdit, $RichMENU)
	Local $hMenu = GUICtrlGetHandle($RichMENU[0])
	; Undo:
	If _GUICtrlRichEdit_CanUndo($h_RichEdit) Then
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[1], 0, 0)
		_GUICtrlMenu_SetItemText($hMenu, $RichMENU[1], "Undo: " & _GUICtrlRichEdit_UndoID2Text(_GUICtrlRichEdit_GetUndoName($h_RichEdit)) & "	Ctrl-Z", 0)
	Else
		_GUICtrlMenu_SetItemText($hMenu, $RichMENU[1], "Undo" & "	Ctrl-Z", 0)
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[1], 1, 0)
	EndIf
	;Redo
	If _GUICtrlRichEdit_CanRedo($h_RichEdit) Then
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[2], 0, 0)
		_GUICtrlMenu_SetItemText($hMenu, $RichMENU[2], "Redo: " & _GUICtrlRichEdit_UndoID2Text(_GUICtrlRichEdit_GetRedoName($h_RichEdit)) & "	Ctrl-Y", 0)
	Else
		_GUICtrlMenu_SetItemText($hMenu, $RichMENU[2], "Redo" & "	Ctrl-Y", 0)
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[2], 1, 0)
	EndIf
	; Cut / Copy:
	Local $sel = _GUICtrlRichEdit_GetSel($h_RichEdit)
	If UBound($sel) = 3 And $sel[1] <> $sel[2] Then
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[3], 0, 0)
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[4], 0, 0)
	Else
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[3], 1, 0)
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[4], 1, 0)
	EndIf
	;Paste
	If _GUICtrlRichEdit_CanPaste($h_RichEdit) Then
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[5], 0, 0)
	Else
		_GUICtrlMenu_SetItemDisabled($hMenu, $RichMENU[5], 1, 0)
	EndIf
EndFunc   ;==>_SetMenuTexts
;~ DWORD EditStreamCallback(
;~     DWORD_PTR dwCookie,
;~     LPBYTE pbBuff,
;~     LONG cb,
;~     LONG *pcb
;~ );

Func _EditStreamCallbackVariable($dwCookie, $pbBuff, $cb, $pcb)
	Local $pcb_Struct = DllStructCreate("long", $pcb)
;~ 	If @AutoItUnicode Then
;~ 		Local $buufs = DllStructCreate("wchar[" & $cb & "]", $pbBuff)
;~ 	Else
	Local $buufs = DllStructCreate("char[" & $cb & "]", $pbBuff)
;~ 	EndIf
	$EDITSTREAM_RTFVariable &= DllStructGetData($buufs, 1)
	DllStructSetData($pcb_Struct, 1, $cb)
	Return 0
EndFunc   ;==>_EditStreamCallbackVariable
Func _EditStreamCallbackFile($dwCookie, $pbBuff, $cb, $pcb)
	Local $pcb_Struct = DllStructCreate("long", $pcb)
	Local $FileHandle = $dwCookie
;~ 	If @AutoItUnicode Then
;~ 		Local $buufs = DllStructCreate("wchar[" & $cb & "]", $pbBuff)
;~ 	Else
	Local $buufs = DllStructCreate("char[" & $cb & "]", $pbBuff)
;~ 	EndIf
	; Write To File :), could also append to a variable ....
	FileWrite($FileHandle, DllStructGetData($buufs, 1))
	DllStructSetData($pcb_Struct, 1, $cb)
	Return 0
EndFunc   ;==>_EditStreamCallbackFile

Func _EditStreamInCallbackFile($dwCookie, $pbBuff, $cb, $pcb)
	Local $pcb_Struct = DllStructCreate("long", $pcb)
	DllStructSetData($pcb_Struct, 1, 0)
	Local $FileHandle = $dwCookie
;~ 	If @AutoItUnicode Then
;~ 		Local $buufs = DllStructCreate("wchar[" & $cb & "]", $pbBuff)
;~ 	Else
	Local $buufs = DllStructCreate("char[" & ($cb + 1) & "]", $pbBuff)
;~ 	EndIf
	Local $read = FileRead($FileHandle, $cb)
	Local $error = @error
	If $error <> 0 Then Return 1
	DllStructSetData($buufs, 1, $read)
	DllStructSetData($pcb_Struct, 1, StringLen($read))
	Return 0
EndFunc   ;==>_EditStreamInCallbackFile

//Edit: Download located HERE Downloads: Posted Image Not updated anymore since it's part of AutoIt now.

Hey, the file on pastebin has exactly 1001 lines :(

Edited by ProgAndy

Share this post


Link to post
Share on other sites



Posted

Nice! One thing though, the @AutoItUnicode macro is removed in v3.2.13.1+, so your UDF errors. I removed the references and it works nicely.

Share this post


Link to post
Share on other sites

Posted

Well, in 3.2.13.1 there eill be no ANSI anymore... But the stable can still be compiled to ANSI, and then Ansi should used in the funcs, too :mellow:

Share this post


Link to post
Share on other sites

Posted

Point taken. Maybe put together a unicode only version then for users of the beta AutoIt so they don't have to mess around with your UDF and possibly break something to get it to compile.

Share this post


Link to post
Share on other sites

Posted

OK, made it :mellow:

Share this post


Link to post
Share on other sites

Posted

Awesome, thanks!

Share this post


Link to post
Share on other sites

Posted

Great.

Only a thing, testing your example, I put a small image from the clipboard, it works good. Then I saved the file, but reading the file saved, Windows close inmediately the GUI and display the classic error when searching a solution. Only with an image inside. Weird.

btw: under Vista.

Share this post


Link to post
Share on other sites

Posted (edited)

I know. Sometimes, it will work, sometimes not, but couldn't find out the reason ...

Try to write some text in the box after adding the picture, click on MsgBoxRTF, delete the text again and possibly it will work then :mellow:

Edited by ProgAndy

Share this post


Link to post
Share on other sites

Posted

I'm sure you will find the solution.

Is there any chance of getting html instead of rtf?

Share this post


Link to post
Share on other sites

Posted

The other functions are from GaryFrost, grham, KIP, me and some functions from the forum (collected by KIP)

It's just Kip. It doesnt stand for anything, so only 1 capital letter would be enough. :(

Just to let you know. :mellow:

Share this post


Link to post
Share on other sites

Posted (edited)

Well, when i iwrite short words with a capital letter, I often forget to release SHIFT :(

Btw: do you have a solution for the crashes when reloading and saving?

@trancexx: For conversion, ust write a converter :mellow:http://www.codeguru.com/cpp/controls/riche...icle.php/c5377/

Edited by ProgAndy

Share this post


Link to post
Share on other sites

Posted

About f**king time. :mellow:

Thanks ProgAndy.

Share this post


Link to post
Share on other sites

Posted (edited)

Hello, this is amazing :mellow:

Very nice...

...just one thing, hyperlinks don't works ;0

Edited by n3nE

Share this post


Link to post
Share on other sites

Posted

You have to catch the message sent when clicking on a hyperkink in WM_NOTIFY:

; for PopupMenu
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
	Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR

	$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
	$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
	$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
	$iCode = DllStructGetData($tNMHDR, "Code")
	Switch $hWndFrom
		Case $h_RichEdit
			Select
				Case $iCode = $EN_LINK
					Local $ENLINK = DllStructCreate($tagENLINK,$ilParam)
					Local $Link_Msg = DllStructGetData($ENLINK,4)
					If $Link_Msg = $WM_LBUTTONUP Then
						Local $Link = _GUICtrlRichEdit_GetTextRange($hWndFrom,DllStructGetData($ENLINK,7),DllStructGetData($ENLINK,8))
						MsgBox(0, '', $Link)
					EndIf
				Case $iCode = $EN_MSGFILTER
					Local $tMsgFilter = DllStructCreate($tagEN_MSGFILTER, $ilParam)
					If DllStructGetData($tMsgFilter, 4) = $WM_RBUTTONUP Then ; WM_RBUTTONUP
						Local $hMenu = GUICtrlGetHandle($RichMENU[0])
						_SetMenuTexts($hWndFrom, $RichMENU)
						_GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd)
					EndIf
			EndSelect
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Share this post


Link to post
Share on other sites

Posted (edited)

Ola, than... this RichEdit is almost perfect ^^

Edit: I have one more thing to ask: Is possible to set background picture or RichEdit background transparency? :mellow:

Edited by n3nE

Share this post


Link to post
Share on other sites

Posted

Very nice...

Very Good

Share this post


Link to post
Share on other sites

Posted

You can easily change the background color with _SendMessage and EM_SETBKGNDCOLOR

To use a image, i didn't find a solution yet

Share this post


Link to post
Share on other sites

Posted

GREAT! TNX!! :mellow:

But how i can load in $h_RichEdit my rtf file?

Share this post


Link to post
Share on other sites

Posted

You need a Stream Cllback, as ii used in my example :mellow:

Global $FileStreamInCallBack = DllCallbackRegister("_EditStreamCallbackFile", "dword", "long_ptr;ptr;long;ptr") ; the Callback
Global $FileStreamInStruct = DllStructCreate($tagEDITSTREAM) ; the Struct for CallbackInit
DllStructSetData($FileStreamInStruct, 3, DllCallbackGetPtr($FileStreamInCallBack)) ; put the CallbackPtr in the struct
...
Local $RTFFile = FileOpen(@DesktopDir & "\AutoIt_testrtf.rtf", 0) ; open File as Text
DllStructSetData($FileStreamInStruct, 1, $RTFFile) ; -> Send handle to CallbackFunc
_GUICtrlRichEdit_SetText($h_RichEdit, "") ; empty RichEdit
Local $send = _GUICtrlRichEdit_StreamIn($h_RichEdit, $SF_RTF, $FileStreamInStruct) ; call StreamIn with StreamStruct and SF_RTF (send RTF text)
FileClose($RTFFile) ; Close RTF File
...
Func _EditStreamInCallbackFile($dwCookie, $pbBuff, $cb, $pcb)
    Local $pcb_Struct = DllStructCreate("long", $pcb) ; we have to send read length to this variable
    DllStructSetData($pcb_Struct, 1, 0) ; first, set them to 0
    Local $FileHandle = $dwCookie ; this is the Cookie set before in FileStreamStruct
    Local $buufs = DllStructCreate("char[" & ($cb + 1) & "]", $pbBuff); create a struct in size of buff
    Local $read = FileRead($FileHandle, $cb) ; read the text from the file
    If @error <> 0 Then Return 1 ; don't send text on error ( e.g. end of file)
    DllStructSetData($buufs, 1, $read) ; set read text to buffer
    DllStructSetData($pcb_Struct, 1, StringLen($read)) ; set read text len to the param
    Return 0 ; return success ($S_OK)
EndFunc   ;==>_EditStreamInCallbackFile

Share this post


Link to post
Share on other sites

Posted (edited)

sorry! I have already found :(

beautiful work! I very pleased, and pictures :mellow: ... GREAT!!!

Edited by scon

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0