Jump to content
corgano

How to send formatted "RTF text" to richedit directly?

Recommended Posts

corgano

Trying to enter colored text into a rich edit is a pain in the ass and complicated, and after searching for a few hours I always end up in the help file staring at this text:

 

_GUICtrlRichEdit_SetText ( $hWnd, $sText )


Parameters
$hWnd Handle to the control 
$sText Plain or RTF text to put into the control

What is this RTF text it speaks of? What I am THINKING of is how if you copy bold text from a page, and paste it into wordpad, it is bold. But if you paste that text into notepad and then copy it and paste it into wordpad it will have no formatting. There is some kind of extra formatting that can be on the text in clipboard

In the same way if you _GUICtrlRichEdit_SetText with plain text it sends it in the richedit as plain text. How do I send pre-formatted "RTF text" to a richedit using _GUICtrlRichEdit_SetText?

Edited by corgano

0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e

Share this post


Link to post
Share on other sites
AutoBert

RichTextFormat save the format options with the text. When you copy the text from wordpad and then insert into your RichEditControl the inserted text is also formated. You must use pre-formated Text with _GUICtrlRichEdit_SetText. Have a look on https://en.wikipedia.org/wiki/Rich_Text_Format#Code_example or open a RTF-File with notepad.

#include <GUIConstantsEx.au3>
#include <GuiRichEdit.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    Local $hGui, $iMsg, $hRichEdit
    $hGui = GUICreate("Example (" & StringTrimRight(@ScriptName, 4) & ")", 320, 350, -1, -1)
    $hRichEdit = _GUICtrlRichEdit_Create($hGui, "This is a test.", 10, 10, 300, 220, _
            BitOR($ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL))
    GUISetState(@SW_SHOW)

    _GUICtrlRichEdit_SetText($hRichEdit, "{\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard This is some {\b bold} text.\par}This is some {\b bold} text.\par}")
    While True
        $iMsg = GUIGetMsg()
        Select
            Case $iMsg = $GUI_EVENT_CLOSE
                _GUICtrlRichEdit_Destroy($hRichEdit) ; needed unless script crashes
                ; GUIDelete()   ; is OK too
                Exit
        EndSelect
    WEnd
EndFunc   ;==>Example

 

Share this post


Link to post
Share on other sites
corgano

Oh. Thanks, at least I now know what to google.

Using this info and this tutorial here, I was able to come up with this:

Func _GUICtrlRichEdit_AppendTextEx($RichEdit, $text, $font="Arial", $color="000000", $size=12, $spacing=-1, $bold=0, $italic=0, $underline=0, $strike=0)
  Local $command = "{\rtf1\ansi"
  Local $r, $g, $b, $ul[9] = ["8", '\ul', '\uldb', '\ulth', '\ulw', '\ulwave', '\uld', '\uldash', '\uldashd']
  If $spacing = -1 Then $spacing = $size

  If $font <> "" Then $command &= "{\fonttbl\f0\f"&$font&";}"
  If $color <> "" Then
    If StringLen($color) <> 6 And StringLen($color) = 8 Then Return SetError(1)
    $b = dec(StringRight($color,2))
    if @error Then seterror(1, 1)
    $color = StringTrimRight($color,2)
    $g = dec(StringRight($color,2))
    if @error Then seterror(1, 2)
    $color = StringTrimRight($color,2)
    $r = dec(StringRight($color,2))
    if @error Then seterror(1, 3)
    If $r+$b+$g > 0 Then
      $command &= "{\colortbl;\red"&$r&"\green"&$g&"\blue"&$b&";}\cf1"
    EndIf
  EndIf

  If $size Then $command &= "\fs"&round($size*2)&" "
  If $spacing <> $size Then $command &= "\sl"&round($spacing*2)&""
  If $strike Then $command &= "\strike "
  If $italic Then $command &= "\i "
  If $bold Then $command &= "\b "
  If $underline > 0 and $underline < 9 Then $command &= $ul[$underline]&" "
  ConsoleWrite($command&$text&"}"&@CRLF)
   _GUICtrlRichEdit_AppendText($RichEdit, $command&StringReplace($text,@CRLF,"\line")&"}" )
EndFunc

And it works for pretty much everything you could need from a rich edit, ecpt I cannot figure out how to get line spacing working. According to the first page I linked, \sl should give me the line spacing, but nothing I try works and I cannot find an example for it.

Could someone who knows RTF provide an example for using \sl? I want to be able to set the spacing between lines.

Edited by corgano

0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e

Share this post


Link to post
Share on other sites
corgano

Update:

All attempts to try and set the distance between lines as line spacing (Like in the paragraph menu of word) has failed to give me the desired effect, since they REQUIRE you create a new paragraph and end it to apply the spacing. If you wanted to have 

Some regular text with some bold text

and then a line under it with 1.5x spacing between

You would need to have some kind of patterns or \flag things to specify when to have the bold text / other formatting.

I worked around this by keeping things simple. Instead of some kind of phraser, I just use the function multiple times, which I guess is lazy but it works really well. For instance

The quick brown fox
jumped over

the lazy dog.

It would look like

Func QuickBrownFox()
    _GUICtrlRichEdit_AppendTextEx($RichEdit, "The quick ", "Arial", "000000", 12)
    ;Color code for brown
    _GUICtrlRichEdit_AppendTextEx($RichEdit, "brown", "Arial", "A57954", 12)
    ;CRLF's turn into \line's in the func anyways
    _GUICtrlRichEdit_AppendTextEx($RichEdit, " fox"&@CRLF, "Arial", "000000", 12)
    ;the 1 denotes bold, all line styles in the func
    _GUICtrlRichEdit_AppendTextEx($RichEdit, "jumped over", "Arial", "000000", 12, 1)
    ;add a space at the end of the line with a bigger size. Works well enough to set spacing in most cases.
    _GUICtrlRichEdit_AppendTextEx($RichEdit, " "&@CRLF, "Arial", "000000", 18)
    _GUICtrlRichEdit_AppendTextEx($RichEdit, "the lazy dog", "Arial", "000000", 12, 1)
endfunc

Definitely not optimal for all cases, where the text is very dynamic, but it works. I think I'm going to patch this up a bit more and post in example scripts for those who want it.

Edited by corgano

0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e

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

  • Similar Content

    • Skitty
      By Skitty
      I found this example by zedna, it worked perfectly (entering text into the control with specified color), that is until you add any form of line break (@CR, @LF or @CRLF).

      If the line breaks aren't there, the text entered is colored correctly, but when they are, the colors gets off and I can't figure out why, anyone know what's the matter?



      #include <GUIConstants.au3> #include <GuiRichEdit.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> $Form1 = GUICreate("Form1", 448, 269, 192, 124) $Edit1 = _GUICtrlRichEdit_Create($Form1,"", 16, 24, 417, 225) GUISetState(@SW_SHOW) _GUICtrlRichEdit_AppendTextColor($Edit1, "Hello "& @CR, "0x00FF00") _GUICtrlRichEdit_AppendTextColor($Edit1, "Autoit "& @CR, "0xFF0000") _GUICtrlRichEdit_AppendTextColor($Edit1, "World", "0x000000") ;~ _GUICtrlRichEdit_AppendText($Edit1, "World") While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE _GUICtrlRichEdit_Destroy($Edit1) Exit EndSwitch WEnd Func _GUICtrlRichEdit_AppendTextColor($hWnd, $sText, $iColor) Local $iLength = Int(_GUICtrlRichEdit_GetTextLength($hWnd)/2) ; RichEdit stores text as 2 Byte Unicode chars _GUICtrlRichEdit_AppendText($hWnd, $sText) _GUICtrlRichEdit_SetSel($hWnd, $iLength, $iLength + StringLen($sText)*2) ; position in 2 Byte "Unicode" _GUICtrlRichEdit_SetCharColor($hWnd, $iColor) _GuiCtrlRichEdit_Deselect($hWnd) EndFunc
    • jmon
      By jmon
      This is an example script, showing how to avoid having Richedit control stealing focus from other controls.

      I have seen several person on the forum having the same issue as me. When using a RichEdit Control in a chat software, RichEdit steals focus from the Input everytime a user posts a message.

      I think I found a work around : find a way to append the text without making a text selection, because the selection moves the caret in the richedit control.

      Problems and solutions I found :
      1 - "_GUICtrlRichEdit_AppendText" Steals focus because there is "_GuiCtrlRichEdit_SetSel" in the function ( "_GuiCtrlRichEdit_SetSel" is used to input the text at the end of the richedit control, and also used to scroll the page to the last line ).
      --- > AppendText Solution = I use "_GUICtrlEdit_AppendText" from "GuiEdit.au3". It appends the text at the end of the Richedit Control, without moving the caret to the richedit control.
      --- > Scrolling Solution = I used "_GUICtrlRichEdit_ScrollLines" to scroll one line down. Later I'll try to find how many lines really need to be scrolled ( if multiline text ).

      2 - "_GUICtrlRichEdit_SetCharColor" Also needs a selection to apply the color. ( _GUICtrlRichEdit_SetFont Doesn't need a selection )
      --- > Color solution = I edited the "_GUICtrlRichEdit_SetCharColor" by Jpm ( and named it "_GUICtrlRichEdit_SetCharColor_No_Selection" ) and commented the _GuiCtrlRichEdit_GetSel lines. So the color needs to be chosen before appending the text.

      Here is an example script showing the problem ( I tried to simulate a chat situation ) :

      ;INCLUDES #include <GuiRichEdit.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> ;OPT Opt("GUIOnEventMode", 1) ;VARIABLES GUI Global $GUI_SIZE_X = 600 Global $GUI_SIZE_Y = 600 Global $GUI_RICHEDIT_SIZE_X = $GUI_SIZE_X Global $GUI_RICHEDIT_SIZE_Y = $GUI_SIZE_Y / 3 ;GUI Global $GUI = GUICreate("Test", $GUI_SIZE_X, $GUI_SIZE_Y) ;RICHEDIT Global $GUI_RICHEDIT = _GUICtrlRichEdit_Create($GUI, "", 0, 0, $GUI_RICHEDIT_SIZE_X, $GUI_RICHEDIT_SIZE_Y * 2, BitOR($ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL, $ES_READONLY)) ;INPUT Global $sINPUT_TEXT = "Try to Type some text here ! (Then press ENTER to send)" & @CRLF & @CRLF & _ "It's IMPOSSIBLE !" & @CRLF & @CRLF & _ "the _GUICtrlRichEdit_AppendText steals focus from the input all the time, making RichEdit almost unusable in a chat software (Even if you use !" & @CRLF & @CRLF & _ "Also, _GUICtrlRichEdit_SetCharColor needs to have a selection to apply the color on the incoming text. If no Selection, then the color is applied on the whole control" & @CRLF & @CRLF & _ "Even with 'GUICtrlSetState ( $GUI_INPUT, $GUI_FOCUS )' it doesn't help" Global $GUI_INPUT = GUICtrlCreateInput($sINPUT_TEXT, 0, $GUI_RICHEDIT_SIZE_Y * 2, $GUI_SIZE_X, $GUI_RICHEDIT_SIZE_Y, $ES_MULTILINE) GUISetState() GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit") HotKeySet("{ENTER}", "_Send") ;LOOP While 1 ;HERE WE ADD RANDOM TEXT WITH RANDOM COLOR EVERY 'Random' ms (TRY TO SIMULATE A CHAT SITUATION) _Chat_Add_Line($GUI_RICHEDIT, _ "Chat Line " & Random(0, 999999), _ "0x" & StringFormat("%02d", Random(0, 99, 1)) & StringFormat("%02d", Random(0, 99, 1)) & StringFormat("%02d", Random(0, 99, 1)), _ 8) Sleep(Random(50, 2000, 1)) WEnd Func _Send() _Chat_Add_Line($GUI_RICHEDIT, "You Said : " & GUICtrlRead($GUI_INPUT), 0xFF0000, 12) GUICtrlSetState($GUI_INPUT, $GUI_FOCUS) GUICtrlSetData($GUI_INPUT, "") Return 1 EndFunc ;==>_Send Func _Chat_Add_Line($hWnd, $sMessage, $sColor, $iFont) StringReplace(_GUICtrlRichEdit_GetText($hWnd, True), @CRLF, "") Local $iLines = @extended Local $iStart = _GUICtrlRichEdit_GetTextLength($hWnd, True, True) - $iLines _GUICtrlRichEdit_PauseRedraw($hWnd) _GUICtrlRichEdit_AppendText($hWnd, $sMessage & @CRLF) _GUICtrlRichEdit_SetSel($hWnd, $iStart, -1, False) _GUICtrlRichEdit_SetCharColor($hWnd, $sColor) _GUICtrlRichEdit_SetFont($hWnd, $iFont) _GUICtrlRichEdit_Deselect($hWnd) _GUICtrlRichEdit_ResumeRedraw($hWnd) ;---> ( TRY TO UN-COMMENT THE NEXT LINE ) ; HERE WE EVEN TRY TO GIVE BACK THE FOCUS TO THE INPUT, BUT IT DOESN'T HELP ;~ GUICtrlSetState ( $GUI_INPUT, $GUI_FOCUS ) Return 1 EndFunc ;==>_Chat_Add_Line Func _Exit() _GUICtrlRichEdit_Destroy($GUI_RICHEDIT) Exit EndFunc ;==>_Exit And Here is my modified version :

      ;INCLUDES #include <GuiEdit.au3> #include <GuiRichEdit.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> ;OPT Opt("GUIOnEventMode", 1) ;VARIABLES GUI Global $GUI_SIZE_X = 600 Global $GUI_SIZE_Y = 600 Global $GUI_RICHEDIT_SIZE_X = $GUI_SIZE_X Global $GUI_RICHEDIT_SIZE_Y = $GUI_SIZE_Y / 3 ;GUI Global $GUI = GUICreate("Test", $GUI_SIZE_X, $GUI_SIZE_Y) ;RICHEDIT Global $GUI_RICHEDIT = _GUICtrlRichEdit_Create($GUI, "", 0, 0, $GUI_RICHEDIT_SIZE_X, $GUI_RICHEDIT_SIZE_Y * 2, BitOR($ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL, $ES_READONLY)) ;INPUT Global $GUI_INPUT = GUICtrlCreateInput("Type some text here, then press Enter", 0, $GUI_RICHEDIT_SIZE_Y * 2, $GUI_SIZE_X, $GUI_RICHEDIT_SIZE_Y, $ES_MULTILINE) GUISetState() GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit") HotKeySet("{ENTER}", "_Send") ;LOOP While 1 ;HERE WE ADD RANDOM TEXT WITH RANDOM COLOR EVERY 'Random' ms (TRY TO SIMULATE A CHAT SITUATION) _Chat_Add_Line($GUI_RICHEDIT, _ "Chat Line " & Random(0, 999999), _ "0x" & StringFormat("%02d", Random(0, 99, 1)) & StringFormat("%02d", Random(0, 99, 1)) & StringFormat("%02d", Random(0, 99, 1)), _ 8) Sleep(Random(50, 1000, 1)) WEnd Func _Send() _Chat_Add_Line($GUI_RICHEDIT, "You Said : " & GUICtrlRead($GUI_INPUT), 0xFF0000, 12) GUICtrlSetState($GUI_INPUT, $GUI_FOCUS) GUICtrlSetData($GUI_INPUT, "") Return 1 EndFunc ;==>_Send Func _Chat_Add_Line($hWnd, $sMessage, $sColor, $iFont) _GUICtrlRichEdit_PauseRedraw($hWnd) ;SET THE COLOR FOR THE INCOMING TEXT USING THE MODIFIED _GUICtrlRichEdit_SetCharColor THAT DOESN'T STEAL INPUT FOCUS _GUICtrlRichEdit_SetCharColor_No_Selection($hWnd, $sColor) _GUICtrlRichEdit_SetFont($hWnd, $iFont) ;THE "_GUICtrlRichEdit_AppendText" STEALS FOCUS FROM THE INPUT (Because there is a _GuiCtrlRichEdit_SetSel in the function). ;SO I APPEND THE TEXT USING "_GUICtrlEdit_AppendText" FROM "GuiEdit.au3". _GUICtrlEdit_AppendText($hWnd, $sMessage & @CRLF) _GUICtrlRichEdit_ScrollLines($hWnd, 1) _GUICtrlRichEdit_ResumeRedraw($hWnd) Return 1 EndFunc ;==>_Chat_Add_Line ; #FUNCTION# ==================================================================================================================== ; Name ..........: _GUICtrlRichEdit_SetCharColor ; Description....: Sets the color of incoming text inserted at the insertion point ; Syntax ........: _GUICtrlRichEdit_SetCharColor($hWnd[, $iColor]) ; Parameters.....: $hWnd - Handle to the control ; $iColor - one of the following: (Optional) ; |a number - a COLORREF value ; |Default keyword - the system color (default) ; Return values..: Success - True ; Failure - False and sets @error: ; |101 - $hWnd is not a handle ; |1022 - $iColor is invalid ; Authors........: Chris Haslam (c.haslam) ; Modified ......: Jpm, Jmon ; Remarks .......: This Function has been modified to avoid stealing focus from another control ; Related .......: _GUICtrlRichEdit_GetCharColor, _GUICtrlRichEdit_SetCharColor ; Link ..........: @@MsdnLink@@ EM_SETCHARFORMAT ; Example .......: Yes ; =============================================================================================================================== Func _GUICtrlRichEdit_SetCharColor_No_Selection($hWnd, $iColor = Default) If Not IsHWnd($hWnd) Then Return SetError(101, 0, False) Local $tCharFormat = DllStructCreate($tagCHARFORMAT) DllStructSetData($tCharFormat, 1, DllStructGetSize($tCharFormat)) If IsKeyword($iColor) Then DllStructSetData($tCharFormat, 3, $CFE_AUTOCOLOR) $iColor = 0 Else If BitAND($iColor, 0xff000000) Then Return SetError(1022, 0, False) EndIf DllStructSetData($tCharFormat, 2, $CFM_COLOR) DllStructSetData($tCharFormat, 6, $iColor) ;I COMMENTED THOSE NEXT LINES, OTHERWISE THE COLOR WOULD BE APPLIED TO THE WHOLE CONTROL ;~ Local $ai = _GuiCtrlRichEdit_GetSel($hWnd) ;~ If $ai[0] = $ai[1] Then ;~ Return _SendMessage($hWnd, $EM_SETCHARFORMAT, $SCF_ALL, DllStructGetPtr($tCharFormat)) <> 0 ;~ Else Return _SendMessage($hWnd, $EM_SETCHARFORMAT, $SCF_SELECTION, DllStructGetPtr($tCharFormat)) <> 0 ;~ EndIf EndFunc ;==>_GUICtrlRichEdit_SetCharColor_No_Selection Func _Exit() _GUICtrlRichEdit_Destroy($GUI_RICHEDIT) Exit EndFunc ;==>_Exit
      In Both Example, you can try to type some text in the Input, at the bottom. Use "Enter" to send the text in the Richedit control.

      Well I hope that solves the problems that others had before.

      [EDIT1] I ran "tidy" on the scripts for better formatting.
×