Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Find and highlight text in other app using regular expresion
#31
In QM 2.3.4.6 the function RichEditHighlight doesn't work properly if text contains characters like "á,ñ"...

test in RichEdit20A.
#32
Actually it is more serious bug. QM always runs in Unicode mode. Fixed in QM 2.3.4.7. Thank you.
#33
Hi Gintaras,
I have been trying to combine the two functions from the forum: RichEditHighlight and EditControlSelectReplace.

It works except for a few things:

1) It will select and apply the format bold/italic/underline to either the original text or to the replaced text but it will only apply the colors to the original text not if there is a replacement. I think it is because the bold/italic/underline apply to the spot where the highlight occurred and will transfer to the next text swapped in however for the color it has to have the exact start and stop characters. I tried to therefore make the replace first and then do the CHARRANGE step after (see version 2 but that really doesn't work!)



Function SelectReplaceHighlightFormat
Code:
Copy      Help
;/
function hwndre ~findthis [$replacetext] [flags] [format] [color] [textcolor] ;;flags: 1 insens, 2 word 4 regex, format: 1 italics, 2 underline, 4 bold,

;Highlights all occurences of findthis in a rich edit control.
;Works with any application.

;hwndre - rich edit control handle.
;findthis - text or regular expression to find.
;flags:
;;;1 - case insensitive
;;;2 - whole word
;;;4 - findthis is regular expression

;format
;;;0 - remove underline, bold & italics,
;;;1 - italicize
;;;2 - underline
;;;4 - make bold
;;;
;color - highlight color. Not used for version 1 controls.
;textcolor - text color.
;;
;replacetext - text that will replace the selection. Can be "" to remove the selected text. If omitted or 0, does not replace.

;EXAMPLE

;SelectReplaceHighlightFormat(TextCid "skin" "skin and bones" 0 2 ColorFromRGB(255 255 255) ColorFromRGB(0 0 0))
;;;will be underlined replacement



def CFM_ITALIC 0x00000002
def CFM_UNDERLINE    0x00000004
def CFE_BOLD 0x0001
def CFE_ITALIC 0x0002
def CFE_UNDERLINE    0x0004



ARRAY(CHARRANGE) a; int i
str s.getwintext(hwndre); if(!s.len) ret
s.findreplace("[]" "[10]")

if(flags&4)
,if(findrx(s findthis 0 flags&3|4|8 a)<0) ret
else
,a.create(1 0)
,rep
,,if(flags&2) i=findw(s findthis i 0 flags&1); else i=find(s findthis i flags&1)
,,if(i<0) break
,,CHARRANGE& cr=a[0 a.redim(-1)]
,,cr.cpMin=i; i+findthis.len; cr.cpMax=i
,if(!a.len) ret

__ProcessMemory m.Alloc(hwndre 1000)

if(IsWindowUnicode(hwndre))
,CHARFORMAT2W cfw.cbSize=sizeof(cfw)
,if(color) cfw.dwMask|CFM_BACKCOLOR; cfw.crBackColor=color
,if(textcolor) cfw.dwMask|CFM_COLOR; cfw.crTextColor=textcolor
,sel format
,,case 7
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD;cfw.dwEffects=CFE_ITALIC|CFE_UNDERLINE|CFM_BOLD;
,,case 6
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD; cfw.dwEffects=CFE_UNDERLINE|CFM_BOLD
,,case 5
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD; cfw.dwEffects=CFE_ITALIC|CFM_BOLD
,,case 4
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD; cfw.dwEffects=CFE_BOLD
,,case 3
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD;cfw.dwEffects=CFE_ITALIC|CFE_UNDERLINE
,,case 2
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD ;cfw.dwEffects= CFE_UNDERLINE
,,case 1
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD; cfw.dwEffects=CFE_ITALIC
,,case 0
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD;
,,,
,,,;Remarks: To turn off a formatting attribute, set the appropriate value in dwMask but do not set the corresponding value in dwEffects. For example, to turn off italics, set CFM_ITALIC but do not set CFE_ITALIC.

,,,
,m.Write(&cfw sizeof(cfw))
else
,CHARFORMAT2A cfa.cbSize=sizeof(cfa)
,if(color) cfa.dwMask|CFM_BACKCOLOR; cfa.crBackColor=color
,if(textcolor) cfa.dwMask|CFM_COLOR; cfa.crTextColor=textcolor
,sel format
,,case 7
,,,cfa.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD;cfa.dwEffects=CFE_ITALIC|CFE_UNDERLINE|CFM_BOLD;
,,case 6
,,,cfa.dwMask|CFM_UNDERLINE|CFM_BOLD; cfa.dwEffects=CFE_UNDERLINE|CFM_BOLD
,,case 5
,,,cfa.dwMask|CFM_ITALIC|CFM_BOLD; cfa.dwEffects=CFE_ITALIC|CFM_BOLD
,,case 4
,,,cfa.dwMask|CFM_BOLD; cfa.dwEffects=CFE_BOLD
,,case 3
,,,cfa.dwMask|CFM_ITALIC|CFM_UNDERLINE;cfa.dwEffects=CFE_ITALIC|CFE_UNDERLINE
,,case 2
,,,cfa.dwMask|CFM_UNDERLINE ;cfa.dwEffects= CFE_UNDERLINE
,,case 1
,,,cfa.dwMask|CFM_ITALIC; cfa.dwEffects=CFE_ITALIC
,,,;Remarks: To turn off a formatting attribute, set the appropriate value in dwMask but do not set the corresponding value in dwEffects. For example, to turn off italics, set CFM_ITALIC but do not set CFE_ITALIC.
,m.Write(&cfa sizeof(cfa))




if(replacetext)
,if(!replacetext[0]) SendMessage hwndre EM_REPLACESEL 0 0 ;;this works in other process too
,else
,,GetWindowThreadProcessId hwndre &_i
,,if(_i=GetCurrentProcessId)
,,,SendMessage hwndre EM_REPLACESEL 0 replacetext
,,else
,,,for(_i 0 len(replacetext)) SendMessage hwndre WM_CHAR replacetext[_i] 0

else
,for i 0 a.len
,,SendMessage hwndre EM_SETSEL a[0 i].cpMin a[0 i].cpMax
,,SendMessage hwndre EM_SETCHARFORMAT SCF_SELECTION m.address    

SendMessage hwndre EM_SETSEL 0 0
ret a.len


Version 2 (doesn't work)

Function SelectReplaceHighlightFormat
Code:
Copy      Help
;/
function hwndre ~findthis [$replacetext] [flags] [format] [color] [textcolor] ;;flags: 1 insens, 2 word 4 regex, format: 1 italics, 2 underline, 4 bold,

;Highlights all occurences of findthis in a rich edit control.
;Works with any application.

;hwndre - rich edit control handle.
;findthis - text or regular expression to find.
;flags:
;;;1 - case insensitive
;;;2 - whole word
;;;4 - findthis is regular expression

;format
;;;0 - remove underline, bold & italics,
;;;1 - italicize
;;;2 - underline
;;;4 - make bold
;;;
;color - highlight color. Not used for version 1 controls.
;textcolor - text color.
;;
;replacetext - text that will replace the selection. Can be "" to remove the selected text. If omitted or 0, does not replace.

;EXAMPLE

;SelectReplaceHighlightFormat(TextCid "skin" "skin and bones" 0 2 ColorFromRGB(255 255 255) ColorFromRGB(0 0 0))
;;;will be underlined replacement



def CFM_ITALIC 0x00000002
def CFM_UNDERLINE    0x00000004
def CFE_BOLD 0x0001
def CFE_ITALIC 0x0002
def CFE_UNDERLINE    0x0004



ARRAY(CHARRANGE) a; int i
str s.getwintext(hwndre); if(!s.len) ret
s.findreplace("[]" "[10]")
CHARRANGE& cr

if(replacetext)
,if(!replacetext[0]) SendMessage hwndre EM_REPLACESEL 0 0 ;;this works in other process too
,else
,,GetWindowThreadProcessId hwndre &_i
,,if(_i=GetCurrentProcessId)
,,,SendMessage hwndre EM_REPLACESEL 0 replacetext
,,else
,,,for(_i 0 len(replacetext)) SendMessage hwndre WM_CHAR replacetext[_i] 0
,,,
,s.getwintext(hwndre); if(!s.len) ret
,s.findreplace("[]" "[10]")        

,,,
,if(flags&4)
,,if(findrx(s replacetext 0 flags&3|4|8 a)<0) ret
,else
,,a.create(1 0)
,,rep
,,,if(flags&2) i=findw(s replacetext i 0 flags&1); else i=find(s replacetext i flags&1)
,,,if(i<0) break
,,,cr=a[0 a.redim(-1)]
,,,cr.cpMin=i; i+len(replacetext); cr.cpMax=i
,,if(!a.len) ret
else
,if(flags&4)
,,if(findrx(s findthis 0 flags&3|4|8 a)<0) ret
,else
,,a.create(1 0)
,,rep
,,,if(flags&2) i=findw(s findthis i 0 flags&1); else i=find(s findthis i flags&1)
,,,if(i<0) break
,,,cr=a[0 a.redim(-1)]
,,,cr.cpMin=i; i+findthis.len; cr.cpMax=i
,,if(!a.len) ret

__ProcessMemory m.Alloc(hwndre 1000)

if(IsWindowUnicode(hwndre))
,CHARFORMAT2W cfw.cbSize=sizeof(cfw)
,if(color) cfw.dwMask|CFM_BACKCOLOR; cfw.crBackColor=color
,if(textcolor) cfw.dwMask|CFM_COLOR; cfw.crTextColor=textcolor
,sel format
,,case 7
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD;cfw.dwEffects=CFE_ITALIC|CFE_UNDERLINE|CFM_BOLD;
,,case 6
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD; cfw.dwEffects=CFE_UNDERLINE|CFM_BOLD
,,case 5
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD; cfw.dwEffects=CFE_ITALIC|CFM_BOLD
,,case 4
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD; cfw.dwEffects=CFE_BOLD
,,case 3
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD;cfw.dwEffects=CFE_ITALIC|CFE_UNDERLINE
,,case 2
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD ;cfw.dwEffects= CFE_UNDERLINE
,,case 1
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD; cfw.dwEffects=CFE_ITALIC
,,case 0
,,,cfw.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD;
,,,
,,,;Remarks: To turn off a formatting attribute, set the appropriate value in dwMask but do not set the corresponding value in dwEffects. For example, to turn off italics, set CFM_ITALIC but do not set CFE_ITALIC.

,,,
,m.Write(&cfw sizeof(cfw))
else
,CHARFORMAT2A cfa.cbSize=sizeof(cfa)
,if(color) cfa.dwMask|CFM_BACKCOLOR; cfa.crBackColor=color
,if(textcolor) cfa.dwMask|CFM_COLOR; cfa.crTextColor=textcolor
,sel format
,,case 7
,,,cfa.dwMask|CFM_ITALIC|CFM_UNDERLINE|CFM_BOLD;cfa.dwEffects=CFE_ITALIC|CFE_UNDERLINE|CFM_BOLD;
,,case 6
,,,cfa.dwMask|CFM_UNDERLINE|CFM_BOLD; cfa.dwEffects=CFE_UNDERLINE|CFM_BOLD
,,case 5
,,,cfa.dwMask|CFM_ITALIC|CFM_BOLD; cfa.dwEffects=CFE_ITALIC|CFM_BOLD
,,case 4
,,,cfa.dwMask|CFM_BOLD; cfa.dwEffects=CFE_BOLD
,,case 3
,,,cfa.dwMask|CFM_ITALIC|CFM_UNDERLINE;cfa.dwEffects=CFE_ITALIC|CFE_UNDERLINE
,,case 2
,,,cfa.dwMask|CFM_UNDERLINE ;cfa.dwEffects= CFE_UNDERLINE
,,case 1
,,,cfa.dwMask|CFM_ITALIC; cfa.dwEffects=CFE_ITALIC
,,,;Remarks: To turn off a formatting attribute, set the appropriate value in dwMask but do not set the corresponding value in dwEffects. For example, to turn off italics, set CFM_ITALIC but do not set CFE_ITALIC.
,m.Write(&cfa sizeof(cfa))


for i 0 a.len
,SendMessage hwndre EM_SETSEL a[0 i].cpMin a[0 i].cpMax
,SendMessage hwndre EM_SETCHARFORMAT SCF_SELECTION m.address    

SendMessage hwndre EM_SETSEL 0 0
ret a.len

Also even in when works (version 1), it seems you can only colorize one time. Subsequent attempts on the same text to apply different color/background don't work. It doesn't seem like the way of turning off a formatting attribute, by setting the appropriate value in dwMask but do not set the corresponding value in dwEffects works for colors - went to black-on-black. I believe this was true of the RichEditHighlight function that I based this on.

Thanks for any thoughts or help in this!

S

ps. I know that my handling of the combination of the flags and format codes couldn't have been handled in one combination 1|2|4|8|16|32|64|128, etc but it seemed like when I combined them, it would always take the last formatting option, instead of combining them so I split and did sel case structure, but I know this isn't most optimal/elegant.

Anyways thanks so much again!!!
S
#34
The first version either does single replacement without highlight, or multiple highlight. If it's the purpose of the combo function, it is probably correct.
Version 2... difficult to understand. It seems also single replacement. Shouldn't be multiple? Then, when you have a, call EditControlSelectReplace for each a[0 i], then set a[0 i]=calculate_new_range, then highlight. But maybe calculating new range is difficult. Maybe then just call RichEditHighlight for the replacement string.
#35
Thanks for looking into this. The second version had my attempt to calculate the range if(replacetext) as well as else (not replacing text) but it probably needs some more tweaking, as you suggest. Also I could just call RichEditHighlight as you also suggest.

One thing is that if RichEditHighlight applied one set of colors to text/background, it seems it won't work a second time. I know how to turn off bold/underline/italics in order to reapply formatting, but couldn't achieve the same with colors (it just went to black on black). Any thoughts?
Thanks again!!!
S
#36
To reset color:
In RichEditHighlight replace if/else code starting from if(IsWindowUnicode(hwndre)). In my version it was 12 lines to replace.
Code:
Copy      Help
CHARFORMAT2W cfw.cbSize=sizeof(cfw)
if(color) cfw.dwMask|CFM_BACKCOLOR; if(color=-1) cfw.dwEffects=CFE_AUTOBACKCOLOR; else cfw.crBackColor=color
if(textcolor) cfw.dwMask|CFM_COLOR; if(textcolor=-1) cfw.dwEffects=CFE_AUTOCOLOR; else cfw.crTextColor=textcolor
if(flags&128) cfw.dwMask|CFM_BOLD; cfw.dwEffects=CFE_BOLD
if(IsWindowUnicode(hwndre))
,m.Write(&cfw sizeof(cfw))
else
,CHARFORMAT2A cfa.cbSize=sizeof(cfa)
,cfa.dwMask=cfw.dwMask; cfa.crBackColor=cfw.crBackColor; cfa.crTextColor=cfw.crTextColor; cfa.dwEffects=cfw.dwEffects
,m.Write(&cfa sizeof(cfa))
Then can use -1 for color or textcolor to reset to default color.
Updated here: Find and highlight text in other app using regular expresion

Updated EditControlSelectReplace: Selecting text within a text field
#37
Thanks. I tried but if you use -1 for background color, it goes to entirely black. So I had better luck using -1 for text color to reset to black and then use ColorFromRGB(255 255 255) for background color to get it to back to white.

One thing about update to EditControlSelectReplace, you have to supply the start and stop point, whereas in RichEditHighlight, it is figured out. So I tried to merge the code so I could have a text replace based on supplying pre-existing string (either straight or regex).

I am getting close with fusing these two or even calling RichEditHighlight out of EditControlSelectReplace, after the swap has occurred but having problem with carriage returns throwing off the start and stop points.

Thanks for any help!,
S
#38
Thank you Gintaras, Stuart and other contributors for this smart routine. It facilitates a lot. I am wondering whether there exists a version for unicode characters. I will appreciate any relevant information, before trying myself to expand it. Best regards.
#39
Maybe I did something wrong or understood something wrong but I can get the colors to reset back to it's default in a QM richedit control. See below example:

As an alternative, is there a way to so set the full background color (highlighted text and rich-edit-field background) back to white?

Function re_highlight
Code:
Copy      Help
str dd=
;BEGIN DIALOG
;0 "" 0x90C80AC8 0x0 0 0 224 136 "Dialog"
;3 RichEdit20A 0x54233044 0x200 0 26 223 109 ""
;4 Button 0x54032000 0x0 1 5 48 14 "find"
;5 Button 0x54032000 0x4 55 5 98 14 "reset colors"
;END DIALOG
;DIALOG EDITOR: "" 0x2040601 "*" "" "" ""

str controls = "3"
str re3
re3=
;{\rtf1\ansi\ansicpg1252\deff0\deflang1043{\fonttbl{\f0\fnil\fcharset0 Courier New;}}
;{\colortbl ;\red255\green0\blue0;}
;\viewkind4\uc1\pard\cf1\lang1033\b\f0\fs17 1234567\cf0\lang1043\b0\par
;\viewkind4\uc1\pard\cf1\lang1033\b\f0\fs17 123\cf0\lang1043\b0\par
;}
if(!ShowDialog(dd &sub.DlgProc &controls)) ret


#sub DlgProc
function# hDlg message wParam lParam

sel message
,case WM_INITDIALOG
,case WM_DESTROY
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
,case 4    
,,str rx="\b123\b"        
,,int n=RichEditHighlight(id(3 hDlg) rx 1|4|128 ColorFromRGB(255 255 128) ColorFromRGB(255 0 0))
,,;; When using the below commented code and the below case 5 green commented 'n=RichEditHighlight' it only set's the background color to black
,,;; int n=RichEditHighlight(id(3 hDlg) rx 1|4|128 ColorFromRGB(255 255 128))
,case 5
,,;; This code set's background AND text to black of the selected text
,
,,rx="\b123\b"
,,n=RichEditHighlight(id(3 hDlg) rx 1|4|128 -1 -1)
,,;; When using the below commented code and the above case 4 green commented 'n=RichEditHighlight' it only set's the background color to black
,,;; n=RichEditHighlight(id(3 hDlg) rx 1|4|128 -1)
ret 1
#40
workaround white bg and red text since your starting with white bg and red text
Code:
Copy      Help
,case 5
,,rx="\b123\b"
,,n=RichEditHighlight(id(3 hDlg) rx 1|4|128 ColorFromRGB(255 255 255) ColorFromRGB(255 0 0))
#41
Yes, that's method I am using right now.


Forum Jump:


Users browsing this thread: 3 Guest(s)