Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Find and highlight text in other app using regular expresion
#1
How can I find a string in notepad using regular expresions?
#2
Code:
Copy      Help
str rx="find this"
int flags=1 ;;1 insens, 2 whole word

int h=id(15 "Notepad")
int i length
int+ g_newsearch
str s.getwintext(h); if(!s.len) ret ;;get all text
if(!g_newsearch) SendMessage(h EM_GETSEL 0 &i) ;;get caret pos
i=findrx(s rx i flags|8 length)
if(i<0) g_newsearch=1; mes- "Not found."
g_newsearch=0
SendMessage(h EM_SETSEL i i+length)
#3
Thanks.

Is it possible highlight all ocurrences?
#4
No, but I think in wordpad it is possible.
#5
using the same code?
#6
Using EM_SETCHARFORMAT messages. Use share for CHARFORMAT2 structure.
#7
I found this:

#CFM_BACKCOLOR = $4000000
#SCF_ALL = 4
; --> Structure for formatting EditorGadget
Structure myCHARFORMAT2
cbSize.l
dwMask.l
dwEffects.l
yHeight.l
yOffset.l
crTextColor.l
bCharSet.b
bPitchAndFamily.b
szFaceName.b[#LF_FACESIZE]
nullPad.w
wWeight.w
sSpacing.w
crBackColor.l
LCID.l
dwReserved.l
sStyle.w
wKerning.w
bUnderlineType.b
bAnimation.b
bRevAuthor.b
bReserved1.b
EndStructure
; --> Find text from start to end of text
editFind.FINDTEXT
editFind\chrg\cpMin = 0 ; this will change in procedure as text is found
editFind\chrg\cpMax = -1
; --> Our found text background
editFormat.myCHARFORMAT2
editFormat\cbSize = SizeOf(myCHARFORMAT2)
editFormat\dwMask = #CFM_BACKCOLOR
editFormat\crBackColor = RGB(128, 200, 200)
; --> Our default EditorGdaget background color
defaultFormat.myCHARFORMAT2
defaultFormat\cbSize = SizeOf(myCHARFORMAT2)
defaultFormat\dwMask = #CFM_BACKCOLOR
defaultFormat\crBackColor = RGB(255, 255, 223)

Global defaultFormat, editFind, editFormat

Procedure findtext(textToFind$)
; --> Reset search to beginnng
SendMessage_(GadgetID(0), #EM_SETSEL, 0, 0)
; --> For resetting to default text
SendMessage_(GadgetID(0), #EM_SETCHARFORMAT, #SCF_ALL, defaultFormat)
; --> Split the seaarch words
spaces = CountString(textToFind$, " ")
For i = 1 To spaces+1
editFind\chrg\cpMin = 0
thisFind$ = StringField(textToFind$, i, " ")
editFind\lpstrText = @thisFind$
Repeat
found = SendMessage_(GadgetID(0), #EM_FINDTEXT, #FR_DOWN, editFind)
If found > -1
editFind\chrg\cpMin = found+1
; --> Set the selection to colorize
SendMessage_(GadgetID(0), #EM_SETSEL, found, found + Len(thisFind$))
; --> Colorize selection background
SendMessage_(GadgetID(0), #EM_SETCHARFORMAT, #SCF_SELECTION | #SCF_WORD, editFormat)
EndIf
Until found = -1
Next i
SendMessage_(GadgetID(0), #EM_SETSEL, 0, 0)
EndProcedure

If OpenWindow(0, 0, 0, 300, 150, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "EditorGadget Find Text") And CreateGadgetList(WindowID(0))
EditorGadget (0, 0, 40, 300, 120)
StringGadget(1, 10, 10, 150, 20, "of three")
ButtonGadget(2, 170, 10, 50, 20, "Find")
AddGadgetItem(0, -1, "Line one of three")
AddGadgetItem(0, -1, "This is the next line of three.")
AddGadgetItem(0, -1, "End line is here")
CreatePopupMenu(0)
MenuItem(1, "Copy")
MenuBar()
MenuItem(2, "Select All")
ActivateGadget(0)
SendMessage_(GadgetID(0), #EM_SETREADONLY, 1, 0)
SendMessage_(GadgetID(0), #EM_SETBKGNDCOLOR, 0, RGB(255, 255, 223))
Repeat
event = WaitWindowEvent()
Select event
Case #PB_EventGadget
Select EventGadgetID()
Case 2
ActivateGadget(0)
findtext(GetGadgetText(1))
ActivateGadget(1)
EndSelect
Case #WM_RBUTTONDOWN
If EventGadgetID() = 0
selStart = 0
selEnd = 0
SendMessage_(GadgetID(0), #EM_GETSEL, @selStart, @selEnd)
If selStart = selEnd
DisableMenuItem(1,1)
Else
DisableMenuItem(1,0)
EndIf
GetCursorPos_(mouseP.POINT)
DisplayPopupMenu(0,WindowID(),mouseP\x, mouseP\y)
EndIf
Case #PB_EventMenu
Select EventMenuID() ; get the clicked menu item...
Case 1
SendMessage_(GadgetID(0), #WM_COPY, 0, 0)
SendMessage_(GadgetID(0), #EM_SETSEL, -1, 0)
Case 2
editSel.CHARRANGE\cpMin = 0
editSel.CHARRANGE\cpMax = -1
SendMessage_(GadgetID(0), #EM_EXSETSEL, 0, @editSel)
EndSelect
EndSelect
Until event = #PB_Event_CloseWindow
EndIf
End

Can you convert it in QM code?
#8
How: Use share for CHARFORMAT2 structure?

I tried

found=SendMessage(share(re) EM_FINDTEXT FR_DOWN &editfind)

and Wordpad crash.
#9
Something like this:

Code:
Copy      Help
CHARFORMAT2W* sm_in_wordpad=+share(worpad_edit_control_handle)
CHARFORMAT2W* sm_in_qm=+share
sm_in_qm.some_member=some_value
;...
SendMessage worpad_edit_control_handle EM_SETCHARFORMAT SCF_SELECTION sm_in_wordpad)

I don't think you need EM_FINDTEXT if you use regular expressions. I don't think you should convert the sample as it is.
#10
Maybe better open the text in a web browser and use a bookmarklet capable to find/highlight text using regular expressions. You'll find such bookmarklets on the Internet. Search for bookmarklet highlight regular expression.
#11
I was looking for a function that worked with any editbox...

case 5 works
case 6 crash

Code:
Copy      Help
\Dialog_Editor
function# hDlg message wParam lParam
if(hDlg) goto messages

def EN_LINK 0x070b
def ENM_LINK 0x04000000
def CFM_COLOR 0x40000000
def CFM_BACKCOLOR 0x4000000
def CFE_BOLD 0x1
def CFM_BOLD 0x1
def CFM_LINK 0x20
def CFE_LINK 0x00000020
def SCF_SELECTION 1
def SCF_WORD 0x2
def SCF_ALL 0x4
def FR_DOWN 0x1



type CHARFORMAT2 cbSize dwMask dwEffects yHeight yOffset crTextColor !bCharSet !bPitchAndFamily !szFaceName[LF_FACESIZE] @wWeight @sSpacing crBackColor lcid dwReserved @sStyle @wKerning !bUnderlineType !bAnimation !bRevAuthor !bReserved1

;BEGIN DIALOG
;0 "" 0x90C80A44 0x100 0 0 201 56 "BuscaEditBox"
;1 Button 0x54030001 0x4 126 42 32 10 "OK"
;2 Button 0x54030000 0x4 162 42 32 10 "Cancel"
;3 Edit 0x54030080 0x200 6 6 172 12 ""
;4 Button 0x54032000 0x0 180 6 18 12 "RX"
;5 Button 0x54032001 0x0 64 22 66 14 "Buscar/siguiente"
;6 Button 0x54032000 0x0 150 22 48 14 "Buscar todo"
;END DIALOG
;DIALOG EDITOR: "" 0x2010804 "" ""


str controls = "3"
str e3
int+ i2(0) g_newsearch(0) h=child
;mes h
if(!ShowDialog("findeditbox3" &findeditbox3 &controls)) ret



ret
;messages
sel message
,case WM_INITDIALOG DT_Init(hDlg lParam); act id(3 hDlg);mov 5 0.5 hDlg;ont hDlg;ret 1
,case WM_DESTROY DT_DeleteData(hDlg)
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case 5
,str rx.getwintext(id(3 hDlg))
,
,int flags=1 ;;1 insens, 2 whole word
,int i length
,;int+ g_newsearch
,str s.getwintext(h); if(!s.len) ret ;;get all text
,if(!g_newsearch)
,,SendMessage(h EM_GETSEL 0 &i) ;;get caret pos
,,i+i2
,i=findrx(s rx i flags|8 length)
,if(i<0) g_newsearch=1; mes- "No se encuentra." "Fin"
,g_newsearch=0
,_s.getwinclass(h)
,if(find(_s "Rich")>=0)
,,_s.get(s 0 i)
,,;out _s
,,;out i
,,ARRAY(str) b
,,int ii=findrx(_s "\r\n" 0 4 b)
,,;escribir_toolbar(ii)
,,i-ii
,,i2+1
,SendMessage(h EM_SETSEL i i+length)
,SendMessage(h EM_SCROLLCARET 0 0)
,
,case 6
,rx.getwintext(id(3 hDlg))
,int found re=h
,CHARRANGE cr
,CHARFORMAT2 cf.cbSize=sizeof(CHARFORMAT2)
,TEXTRANGE editfind
,editfind.chrg.cpMin=0
,editfind.chrg.cpMax=-1
,editfind.lpstrText=rx    
,cf.dwMask=CFM_COLOR|CFM_BACKCOLOR|CFM_BOLD
,cf.dwEffects=CFE_BOLD
,cf.crTextColor=ColorFromRGB(255 0 0);; rojo
,cf.crBackColor=ColorFromRGB(255 255 128);; amarillo
,SendMessage(re EM_SETSEL 0 0)
,rep
,,found=SendMessage(share(re) EM_FINDTEXT FR_DOWN &editfind)
,,if(found=-1) break
,,editfind.chrg.cpMin=found+1
,,SendMessage(re EM_SETSEL found found+len(editfind.lpstrText))
,,SendMessage(re EM_SETCHARFORMAT SCF_SELECTION &cf)
,
,case 4
,RegExpMenu id(3 hDlg)
,case IDOK DT_Ok hDlg
,case IDCANCEL DT_Cancel hDlg
ret 1
#12
Why do you use share(re) where window handle mus be Confusedhock:
Never pass address of a variable to other applications. Use
VARIABLETYPE* variable=+share
variable.member=value
...
SendMessage re ... share(re)
#13
On Windows XP, wordpad edit control class is richedit50w. The w at the end means that you must use wide character versions of structures, eg CHARFORMATW.

Note 2:
If you use EM_FINDTEXT, FINDTEXT lpstrText member must point to string that is in shared memory.
#14
I never had been used SHARE, and in the help:

Return pointer to shared memory
Syntax
int* share([window])

can you help me in the case 6 to highlight all find words in any editbox?
#15
New version: Find and highlight text in other app using regular expresion

Function RichEditHighlight
Code:
Copy      Help
;/
function hwndre ~findthis [flags] [color] [textcolor] ;;flags: 1 insens, 2 word, 4 regex, 128 bold, 0x100 version 1

;Highlights all occurences of findthis in a rich edit control. Works in any application.
;hwndre - rich edit control handle.
;findthis - text or regular expression to find.
;flags - combination of these values:
;;;1 - case insensitive
;;;2 - whole word
;;;4 - findthis is regular expression
;;;128 - make bold
;;;0x100 - rich edit control version 1. Version 1 class usually is RICHEDIT. For other versions, class is like RichEdit20A.
;color - highlight color. Not used for version 1 controls.
;textcolor - text color.


;EXAMPLE
;str rx="\bfind this\b"
;int n=RichEditHighlight(id(59648 "WordPad") rx 1|4|128 ColorFromRGB(255 255 128) ColorFromRGB(255 0 0))
;out "Found %i instances" n



def CFM_COLOR 0x40000000
def CFM_BACKCOLOR 0x4000000
def CFM_BOLD 0x1
def CFE_BOLD 0x1
def SCF_SELECTION 1
def EM_GETTEXTMODE (WM_USER + 90)
type CHARFORMATA cbSize dwMask dwEffects yHeight yOffset crTextColor !bCharSet !bPitchAndFamily !szFaceName[LF_FACESIZE]
type CHARFORMAT2A :CHARFORMATA'v1 @wWeight @sSpacing crBackColor lcid dwReserved @sStyle @wKerning !bUnderlineType !bAnimation !bRevAuthor
type CHARFORMATW cbSize dwMask dwEffects yHeight yOffset crTextColor !bCharSet !bPitchAndFamily @szFaceName[LF_FACESIZE]
type CHARFORMAT2W :CHARFORMATW'v1 @wWeight @sSpacing crBackColor lcid dwReserved @sStyle @wKerning !bUnderlineType !bAnimation !bRevAuthor
dll user32 #IsWindowUnicode hWnd

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

if(flags&4)
,if(findrx(s findthis 0 flags&3|4|8|16 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

int ver1=flags&0x100 and !SendMessage(hwndre EM_GETTEXTMODE 0 0)
memset(share 0 sizeof(CHARFORMAT2W))
if(IsWindowUnicode(hwndre))
,CHARFORMAT2W& cfw=+share
,if(ver1) cfw.cbSize=sizeof(CHARFORMATW)
,else cfw.cbSize=sizeof(CHARFORMAT2W); if(color) cfw.dwMask|CFM_BACKCOLOR; cfw.crBackColor=color
,if(textcolor) cfw.dwMask|CFM_COLOR; cfw.crTextColor=textcolor
,if(flags&128) cfw.dwMask|CFM_BOLD; cfw.dwEffects=CFE_BOLD
else
,CHARFORMAT2A& cfa=+share
,if(ver1) cfa.cbSize=sizeof(CHARFORMATA)
,else cfa.cbSize=sizeof(CHARFORMAT2A); if(color) cfa.dwMask|CFM_BACKCOLOR; cfa.crBackColor=color
,if(textcolor) cfa.dwMask|CFM_COLOR; cfa.crTextColor=textcolor
,if(flags&128) cfa.dwMask|CFM_BOLD; cfa.dwEffects=CFE_BOLD

for i 0 a.len
,SendMessage hwndre EM_SETSEL a[0 i].cpMin a[0 i].cpMax
,SendMessage hwndre EM_SETCHARFORMAT SCF_SELECTION share(hwndre)

SendMessage hwndre EM_SETSEL 0 0
ret a.len
#16
Thank you.

It's perfect.
#17
The first version fas not perfect. For example, did not clear shared memory before using it. I converted the code to function.
#18
Is it possible in "+Scintilla"?. http://www.flos-freeware.ch/notepad2.html
#19
Don't know, probably not.
#20
Hi,
I would like to highlight text within a RichEdit20W field. After highlighting it, I would like to delete it - i.e. I am only highlighting it to be able to send a delete keystroke.


Code:
Copy      Help
int handw=GetWinId(child("" "WindowsForms10.RichEdit20W.app.0.378734a" win("Sample App" "WindowsForms10.Window.8.app.0.378734a") 0x5))
RichEditHighlight handw "find this"


Anyway, everytime I do it, the appropriate text gets highlighted but then I get the following errors:


Quote:An Unexpected Error Occurred:
Exception has been thrown by the target of the invocation.
Click Retry or Cancel to terminate the application


If I click "Retry", the text becomes unhighlighted and the dialog disappears. If I hit "Cancel", I get the following message:

Quote:A fatal error occurred and the application will now terminate:
COM returned an unexpected error code: Details are RPC_E_CANTCALLOUT_ININPUTSYNCCALL


When I press OK, the dialog goes away but the application of the RichEdit field doesn't close, though the text remains unhighlighted.

I hope this explanation helps and that there is a solution. In the meantime, I will research what Richedit20W means - I see you have previously referred to RichEdit and RichEdit20 but not RichEdit20.

Thanks,
Stuart
#21
The function works with RichEditXXW too. Don't know why the target app crashes. I tested with Wordpad on XP and Vista. But if you need to select text for deleting or replacing, this function does not do it. It only changes colors. See this:

Selecting text within a text field
#22
Hi Gintaras,
I have a complex dialog that uses RichEditHighlight and would lilke to make exe out of it. It works when I comment out all the RichEditHighlight lines but when they are in place I get this error:

Error in SampleDialog: cannot be used in exe.
Cannot make exe. Error 4, failed to compile.

The location of the error is in the following line of the RichEditHighlight function:

Function RichEditHighlight_RefsManager
Code:
Copy      Help
memset(share 0 sizeof(CHARFORMAT2W))

This is such a great function that I hope it will be incorporated into the main version of QM and supported in the exe.

Thanks for any thoughts on this! As always, DEEPLY grateful for all your help!!

Stuart
#23
This works in exe too.
Also can remove highlighting - use color -1.

Function RichEditHighlight
Code:
Copy      Help
;/
function hwndre ~findthis [flags] [color] [textcolor] ;;flags: 1 insens, 2 word, 4 regex, 128 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
;;;128 - make bold
;color - highlight color. Not used for version 1 controls. Use -1 to reset to default.
;textcolor - text color. Use -1 to reset to default.

;EXAMPLE
;str rx="\bfind this\b"
;int n=RichEditHighlight(id(59648 "WordPad") rx 1|4|128 ColorFromRGB(255 255 128) ColorFromRGB(255 0 0))
;out "Found %i instances" n


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|16 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)

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))

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
#24
Thanks!!! Will test in my app when I get back to work tomorrow!! Merry Christmas Gintaras!!
S
#25
Hi Gintaras,
Thanks for the update on RichEditHighlight. It no longer is stopping the creation of the exe. However the dialog specified in my folder of macros is still not launching. At time of exe creation, I get this message:

Quote:Warning: Cannot find function GetProcessHandleFromHwnd in dll oleacc. Make sure it is available when the code runs. Make sure the declaration contains true function name.
Created C:\Documents and Settings\xxx\My Documents\My QM\SampleProgram.exe, 735 KB. Run Find


When I attempt to run the exe, I get this:
Quote:Error (RT) in SampleProgram: cannot show dialog

I know this is very generic and it may be hard for you to help me with such little to go on. The dialog and associated user-defined functions it calls are very complex so it will be a challenge for me to rebuild it piece by piece confirming working exe each time (but I will do it that way if necessary). I was just wondering if there were some typical things that may cause a dialog to not launch in an exe.

The issue with GetProcessHandleFromHwnd in dll oleacc did not stop a much simpler function from running properly after converted into an .exe so I don't think it is just that.


Thanks so much for any help you can give me,

Stuart
#26
Hi Gintaras,
I realized that the main dialog uses the splitters which required InitSplitter to create the QM_Splitter class. Is this something that is incompatible with exe. Is there a way to place to register the window class "QM_Splitter" when launching an exe?

Thanks..I hope this is helpful in answering my previous question.

Stuart
#27
Yes, it was definitely the splitters. I took them out of the dialog, made the exe and it ran fine!!
Hope there is a solution to including this class into exe
Thanks!!!
Stuart
#28
Call InitSplitter in your main exe function.

-------------

Ignore the GetProcessHandleFromHwnd warning. Exe will find and use it on Windows Vista/7.
#29
Next QM will not show such warnings for dll functions declared in System.
#30
It's a QM world and I'm just happy to be living in it! Big Grin Thanks for your fantastic assistance!
S


Forum Jump:


Users browsing this thread: 7 Guest(s)