Just want to know if we have ability to search text on a Clarion Window. because if we have multiple textbox controls on a window and we want to search specific control, then instead of manually checking that, Can we search for it?
Thanks.
I am not completely sure I understand you but if you click on the ellipsis (…) button next to the window button you can then see the “code view” of the window and you can certainly do control-F there to search for a given control.
hth
edit: or are you talking about at runtime?
Thanks for replying but I am not talking at code level search. I am asking about runtime search. once the exe is generated and we have many controls on some window, but if want to search for some label in that window. we generally do CTRL + F to find text on web browsers to search for a text.
There is no inbuilt feature for this and it’s not something I have done, however I guess it would be possible by looping over the window controls and performing the search on values of properties for that field and perform your search and then do what you like
A very simple example to get you going
PROGRAM
MAP
END
Window WINDOW('Caption'),AT(,,395,224),GRAY,FONT('Segoe UI',9)
BUTTON('&OK'),AT(291,201,41,14),USE(?OkButton),DEFAULT
BUTTON('Search'),AT(2,201),USE(?btnSearch)
PROMPT('Prompt1'),AT(39,52),USE(?PROMPT1)
PROMPT('Prompt2'),AT(166,52),USE(?PROMPT2)
END
feq Signed
CODE
OPEN(Window)
ACCEPT
Case ACCEPTED()
of ?OkButton
post(EVENT:CloseWindow)
of ?btnSearch
Do Search
END
END
CLOSE(Window)
Search ROUTINE
feq = 0
LOOP
feq = 0{Prop:NextField, feq}
if feq = 0
break
end
CASE feq{PROP:Type}
OF CREATE:prompt
!value of prop:text will be the prompts text
if feq{prop:text} = 'Prompt1'
feq{PROP:Color} = COLOR:Red
END
END
I hope that helps.
Mark
You can use a LOOP with Prop:NextField to scan all controls and use PROP:Type to find TEXT or ENTRY. The CONTENTS(Feq) function or PROP:Value or PROP:ScreenText to get the value without knowing the USE() variable. With a TEXT you can use PROP:LineCount and PROP:Line,# to scan individual line’s text.
Feq LONG
CODE
Feq=0
LOOP
FEQ=0{PROP:NextField,FEQ}
IF ~FEQ THEN BREAK.
CASE FEQ{PROP:Type}
OF CREATE:Text
IF INSTRING('FIND THIS',UPPER(CONTENTS(FEQ)),1) THEN
SELECT(FEQ)
Message('The control containing "FIND THIS" has been selected','Find Text')
BREAK
END
END
END
I’m assuming you’re thinking of behavior in a browser
where you can search for any text, which is to say content of entry controls, but also for prompts.
NOTE: in this code, I’m starting at the next control from the one that currently has focus, and wrapping around if necessary. Much like a CTRL+F in an editor.
Notice that while this searches content of controls
It also searches the controls themselves
like the text of a prompt, or a button etc.
How about something like this.
SelectMatchingControl PROCEDURE(STRING xSearchFor)
Controls QUEUE
FEQ SIGNED
END
OrigPtr
QPtr LONG
CODE
DO FillControls
Controls.FEQ = FOCUS()
GET( Controls, Controls.FEQ )
QPtr = POINTER( Controls ) + 1
LOOP
IF QPtr > RECORDS( Controls )
QPtr = 1
END
GET( Controls, QPtr )
IF Controls.FEQ = FOCUS()
BREAK ! did not find a match
END
IF INSTRING( SearchFor, Controls.FEQ{PROP:ScreenText}, 1, 1) > 0 |
OR INSTRING( SearchFor, Controls.FEQ{PROP:Text }, 1, 1) > 0 |
THEN
SELECT( Controls.FEQ )
BREAK
END
END
FillControls ROUTINE
DATA
CurrFEQ SIGNED(0)
CODE
LOOP
CurrFEQ=0{PROP:NextField,CurrFEQ}
IF CurrFEQ = 0
BREAK
ELSIF CurrFEQ > 0 ! ignore toolbar and menu controls
Controls.FEQ = CurrFEQ
ADD( Controls )
END
END
When I woke up this morning, I realized there was no need for a queue, the code could be written in one pass - duh.
SelectMatchingControl PROCEDURE(STRING xSearchFor)
CurrFEQ SIGNED,AUTO
Found LONG,AUTO
CODE
CurrFEQ = FOCUS()
LOOP
CurrFEQ = 0{PROP:NextField,CurrFEQ}
IF CurrFEQ = FOCUS() THEN BREAK ! no match as we have wrapped around
ELSIF CurrFEQ <= 0 THEN CYCLE ! < 0 : ignore toolbar, menu controls
! = 0 : ignore current window as well
END
Found = INSTRING( xSearchFor, CurrFEQ{PROP:ScreenText}, 1, 1)
IF Found
SELECT( CurrFEQ, Found, Found + LEN(xSearchFor) - 1 )
BREAK
END
IF INSTRING( xSearchFor, CurrFEQ{PROP:Text}, 1, 1)
! could limit this to certain PROP:TYPE
! but it would be nice to search text of all sorts of controls
! prompts, buttons, checkboxes & radio options etc.
! TODO: confirm that prop:text is the correct property for each of those
SELECT( CurrFEQ )
BREAK
END
END
NOTE: due to an issue @jslarve pointed out. I have changed the code to check for CurrFEQ = Focus() prior to chcking CurrFEQ <= 0
Would you not want to BREAK if CurrFEQ = 0?
OIC, you’re wrapping.
What if FOCUS() = 0?
or less than zero, which is possible.
Jeff - In response to your observation
I have altered the code above
checking CurrFEQ = FOCUS ()
prior to CurrFEQ <= 0
PROMPT and STRING controls contain text (Prop:ScreenText and Prop:Text) but cannot be Select() and given focus. You could create a Box around to highlight them, or color them.
An an ENTRY the PROP:Text returns the Picture. The earlier search of PROP:ScreenText would scan the CONTENTS() or Prop:Value.
One tip is PROP:Value on PROMPT, BUTTON, OPTION, RADIO, CHECK, TAB, GROUP controls returns the same as PROP:ScreenText and Prop:Text, but without the “&” prefixing the Alt+Key. E.g.
?Cus:Name{PROP:Text}='&Name:' ! has &
?Cus:Name{PROP:Value}='Name:' ! without &
That certainly makes sense.
But IF I write SELECT(?SomePrompt),
won’t the next selectable control be selected, so it would still function as desired.
Another example of scanning controls. I find the Drop LIST hard to see typically being a White Box below the ENTRY control
This procedure finds all the Drop Lists on the Window and does this:
- Colors the LIST Yellow like a Tooltip (Info Text) so they stand out
- Increases the Line Height by 1 so more space between
- Adds a Format with an L(2) Margin so 2 on the Left allows more margin between line and text
DropListPretty PROCEDURE()
Fld LONG,AUTO
LstFEQ LONG,AUTO
CODE
Fld=0
LOOP
Fld=0{PROP:NextField,Fld}
IF Fld=0 THEN BREAK.
CASE Fld{PROP:Type}
OF CREATE:List
OROF CREATE:Combo
LstFEQ = Fld{PROP:ListFEQ}
IF LstFEQ AND Fld{PROP:Drop}>0 THEN !Only if Drop List
LstFEQ{PROP:LineHeight}=1 + LstFEQ{PROP:LineHeight} ! +1 more line space easier to read
IF LstFEQ{PROP:Background}=COLOR:None THEN
LstFEQ{PROP:Background}=COLOR:InfoBackground !Yellow like tip
LstFEQ{PROP:FontColor} =COLOR:InfoText !font color like tip should be black
END
IF ~LstFEQ{PROP:FORMAT} THEN
LstFEQ{PROP:FORMAT}='999L(2)@s255@' !Margin of 2 else tight to line
END
END
END
END
RETURN