Sign in to follow this  
Followers 0
jmon

Example : Avoid RichEdit stealing focus from other controls

5 posts in this topic

#1 ·  Posted (edited)

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.

Edited by jmon

Share this post


Link to post
Share on other sites



Thanks very much for that solution. Scrolling does not work properly. Every line typed by human causing some scroll offset... This problem arises from a different fonts I think. How to solve this?

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

you maybe need to set the _GUICtrlRichEdit_ScrollLines to a higher value than 1. If you use bigger font maybe a value of 1 isn't enough.

I am actually working on an improved version of this bugfix as there are still issues with other functions of richedit.

Does anyone has any other workaround for this problem?

[EDIT]

Ok now I see what you mean, and I guess that according to the font size, the _GUICtrlRichEdit_ScrollLines (line 61) needs to be adjusted. So if the font is 8, then scroll 1 line, and if it's 12, scroll 2 ...etc...

Edited by jmon

Share this post


Link to post
Share on other sites

Your solution is very important and very useful for anyone who works with multiple GUIs and RichEdit. For my application standard behavior of RichEdit is not acceptable, it causes fast switching between two windows at all time. We need to solve how to define line numbers for scrolling, now each line that is to long casuses wrong scrolling.

Share this post


Link to post
Share on other sites

Hai.. thnx for your code which helped me a lot.

I am facing one problem.

When the cursor is moved somewhere away from the "endofline of last line" within the richeditbox, the newline added in the richeditbox ALWAYS carries the "black color". How to avoid this?. Please help.

Thanks.

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

  • Similar Content

    • loganizzi
      By loganizzi
      If you look at the help file for the above command, you'll see that it states that it only works for certain zoom values (100 and 200 to 6400).   I assume that this is due to an issue in an MSDN library that the command relies on.
      After doing some investigating, I noticed that the GUIRichEdit.au3 library file contains the following code:
      ; #FUNCTION# ==================================================================================================================== ; Authors........: Chris Haslam (c.haslam) ; Modified ......: ; =============================================================================================================================== Func _GUICtrlRichEdit_SetZoom($hWnd, $iPercent) If Not _WinAPI_IsClassName($hWnd, $__g_sRTFClassName) Then Return SetError(101, 0, False) If Not __GCR_IsNumeric($iPercent, ">0") Then Return SetError(1021, 0, False) Local $iNumerator, $iDenominator Select Case Not ($iPercent = 100 Or ($iPercent >= 200 And $iPercent < 6400)) Return SetError(1022, 0, False) Case $iPercent >= 100 $iNumerator = 10000 $iDenominator = 10000 / ($iPercent / 100) Case Else $iNumerator = 10000 * ($iPercent / 100) $iDenominator = 10000 EndSelect Return _SendMessage($hWnd, $EM_SETZOOM, $iNumerator, $iDenominator) <> 0 EndFunc ;==>_GUICtrlRichEdit_SetZoom Which ensures that values are only within the bounds specified in the help file.    I found that if I comment out the portion of the code that limits the values, the function works fine for most (if not all) values.   I changed the code in the library file to this by simply commenting out the restricting lines of code:
      ; #FUNCTION# ==================================================================================================================== ; Authors........: Chris Haslam (c.haslam) ; Modified ......: ; =============================================================================================================================== Func _GUICtrlRichEdit_SetZoom($hWnd, $iPercent) If Not _WinAPI_IsClassName($hWnd, $__g_sRTFClassName) Then Return SetError(101, 0, False) If Not __GCR_IsNumeric($iPercent, ">0") Then Return SetError(1021, 0, False) Local $iNumerator, $iDenominator Select ; Case Not ($iPercent = 100 Or ($iPercent >= 200 And $iPercent < 6400)) ; Return SetError(1022, 0, False) Case $iPercent >= 100 $iNumerator = 10000 $iDenominator = 10000 / ($iPercent / 100) Case Else $iNumerator = 10000 * ($iPercent / 100) $iDenominator = 10000 EndSelect Return _SendMessage($hWnd, $EM_SETZOOM, $iNumerator, $iDenominator) <> 0 EndFunc ;==>_GUICtrlRichEdit_SetZoom  
      I assume whatever windows bug existed at the time this was created, no longer exists so there is no need to restrict the values.   
      Just wanted to point this out if anyone else is using this part of the library and required this functionality like I did.
       
    • AndreyS
      By AndreyS
      Tell me, please, how to set / change the cursor over RichEdit (created with _GUICtrlRichEdit_Create)?
    • StMaSi
      By StMaSi
      Two questions...
      When presenting a form containing a richedit control, is there any way to make the displayed text, within said richedit control, non-selectable?
      In addition, is there any way to hide the vertical line cursor, within said richedit control?
      Thanx.
    • TheSaint
      By TheSaint
      I've finally come up with some simple solutions for dragging & dropping a URL onto a control.
      There have been many requests here for this over the years.
      I do have an issue though, with my second code example solution as is mentioned here.
      The issue relates to working in Win 7 (and no doubt newer Windows).
      As I state there, failure is no doubt due to 'MSCOMCT2.OCX' missing from the System32 folder, at the very least.
      Not sure if it would be wise to just dump 'MSCOMCT2.OCX' from WinXP into the Win 7 System32 folder. I expect not.
      I imagine there is a better solution available in Win 7. Maybe a different OCX file, and perhaps a different Class of object etc.
      Any help would be greatly appreciated.
      Code is here (second example).
      EDIT
      Okay, I have rediscovered that 'MSCOMCT2.OCX' is a VB6 ActiveX control. So while I could dig up a copy and register it, that would probably not be helpful to everyone.
      And registering it didn't help. Possibly other dependencies are also needed?
      When running the script, it is clear going by the error reported, that Object is not being created.
    • AndreyS
      By AndreyS
      Please tell me, who knows how to apply and cancel styles in RTF?
      The following code does not work:
      #include <GuiRichEdit.au3> #include <WindowsConstants.au3> $hGUI = GUICreate("RichEdit Style", 500, 500, -1, -1) $hRichEdit = _GUICtrlRichEdit_Create($hGui, "Test", 20,40,460,400) GUISetState(@SW_SHOW, $hGUI) Sleep(3000) GUICtrlSetStyle($hRichEdit, $ES_RIGHT) Sleep(3000) GUICtrlSetStyle($hRichEdit, -1) Sleep(3000) Thanks!