Page 1 of 2

Incremental Search in BROWSE

Posted: Thu Jun 26, 2014 8:37 am
by Clip2Mania
I would like to implement an incremental search in a BROWSE.
E.g. When typing a character, 'seek' to the first occurrence in the indexed table - when typing a second character, seeking further in the index, and so on. "Clearing" the seek-string by means of a Ctrl-Key combination.
A bit like the example GridIncrementalSearch in \SAMPLES\Controls\Grid.
Is this possible in a BROWSE ? How can I do that?

Best Regards,

Re: Incremental Search in BROWSE

Posted: Thu Jun 26, 2014 9:45 am
by mol
You can do it with events.
I can post you my functions, but have no time to translate it to English (code is rather "clear")
If you are interested in it, please post.

Re: Incremental Search in BROWSE

Posted: Thu Jun 26, 2014 9:57 am
by mol
a piece of code:

Code: Select all

DEFINE BROWSE B_Towary 
		parent OknoTabTowarow
        ROW    20
        COL    10
        WIDTH  900
        HEIGHT 370
        VALUE Nil
        WIDTHS aLocalWidths
        HEADERS aLocalHeaders
        WORKAREA towary
        FIELDS aLocalFields
        FONTNAME "Arial"
        FONTSIZE 9
        TOOLTIP ""
        ONCHANGE OknoSzybkaTabelaTowarow_AktualizujPodglad()
        ONGOTFOCUS Nil
        ONLOSTFOCUS Nil
        FONTBOLD .F.
        FONTITALIC .F.
        FONTUNDERLINE .F.
        FONTSTRIKEOUT .F.
        ONDBLCLICK if(JakoSlownik, OknoSzybkaTabelaTowarow_ZwrocKodTowaru(), NIL)
		MULTISELECT .F.
        ALLOWEDIT .F.
        ALLOWAPPEND .F.
        ONHEADCLICK {{||ZmienKluczTowaru(1)},{||ZmienKluczTowaru(2)},{||ZmienKluczTowaru(3)},{||ZmienKluczTowaru(4)}}
        ALLOWDELETE .F.
        HELPID Nil
        VALID Nil
        VALIDMESSAGES Nil
        LOCK Nil
        VSCROLLBAR .T.
        DYNAMICBACKCOLOR aLocalBackColors
        DYNAMICFORECOLOR Nil
        INPUTMASK Nil
        FORMAT Nil
        WHEN Nil
        INPUTITEMS Nil
        DISPLAYITEMS Nil
        BACKCOLOR NIL
        FONTCOLOR NIL
        IMAGE Nil
        JUSTIFY aLocalJust
        NOLINES .F.
        READONLYFIELDS Nil
        HEADERIMAGES Nil
    END BROWSE

define Search textbox

Code: Select all

 DEFINE TEXTBOX T_Wyszukaj
        ROW    498
        COL    130
        WIDTH  240
        HEIGHT 30
        FONTNAME "Arial"
        FONTSIZE 12
        TOOLTIP "Type characters to search..."
        ONCHANGE WyszukajTowar()
        ONGOTFOCUS NIL
        ONLOSTFOCUS Nil
        FONTBOLD .T.
        FONTITALIC .F.
        FONTUNDERLINE .F.
        FONTSTRIKEOUT .F.
        ONENTER OknoTabTowarow.B_Towary.SetFocus
        HELPID Nil
        TABSTOP .T.
        VISIBLE .T.
        READONLY .F.
        RIGHTALIGN .F.
        DISABLEDBACKCOLOR Nil
        DISABLEDFONTCOLOR Nil
        CASECONVERT UPPER
        BACKCOLOR NIL
        FONTCOLOR {255,0,0}
        INPUTMASK Nil
        FORMAT Nil
        VALUE ""
    END TEXTBOX
define event for keys pressed in focused BROWSE:

Code: Select all

	CREATE EVENT PROCNAME WyszukiwanieWTabeli('OknoTabTowarow', 'B_Towary','T_Wyszukaj', 'WyszukajTowar()') HWND OknoTabTowarow.B_Towary.HANDLE MSG WM_CHAR
Event handlie function:

Code: Select all

Function WyszukiwanieWTabeli 
	param cNazwaOkna, cNazwaTabeli, cNazwaPolaWyszukaj, cFunkcjaSzukajaca
	
	STATIC flag := .F.
	LOCAL hWnd, ch
	local lFound := .f.
	local cCzegoSzukac := ""

	if flag == .t.
		return nil  // avoid re-entry
	endif

	flag := .T.
	ch := HMG_GetLastCharacter(@hWnd)
	IF hWnd == GetControlHandle (cNazwaTabeli,cNazwaOkna)
		
		cCzegoSzukac := GetProperty(cNazwaOkna,cNazwaPolaWyszukaj,"Value")
		
		if (asc(ch)>31 .and. asc(ch)<128) .or. at(upper(ch),"ĄĆĘŁŃÓŚŻŹ")>0
			HMG_CleanLastCharacter(.t.)   //   avoid re-entry
			cCzegoSzukac += HMG_Upper(ch)
			hPolaWyszukaj := GetControlHandle (cNazwaPolaWyszukaj,cNazwaOkna)
			SetWindowText(hPolaWyszukaj, cCzegoSzukac)
			lFound := &cFunkcjaSzukajaca
			DoMethod(cNazwaOkna, cNazwaTabeli,"SetFocus")
		endif
	
		if asc(ch) == 8 // backspace
			hPolaWyszukaj := GetControlHandle (cNazwaPolaWyszukaj,cNazwaOkna)
			cCzegoSzukac := left(cCzegoSzukac,max(len(cCzegoSzukac)-1,0))
			SetWindowText(hPolaWyszukaj, cCzegoSzukac)
			HMG_CleanLastCharacter()   //   avoid re-entry
			DoMethod(cNazwaOkna, cNazwaTabeli,"SetFocus")
		endif
	endif
	flag := .F.
//Return if(lFound,1,NIL)
Return 1
And, proper search function, triggered by changes in Search textbox:

Code: Select all

*-------------------------
function WyszukajTowar
	local cTekstSzukany := '', cKodSzukany := ''
	local nOrder := towary->(Indexord()), i, lCyfrowy := .f., lFound := .f., sel := select()
	local nIndeksTowarow := 5
	//local nOdszukanyIndeks := 1
	// czasem przy złej kolejności kontrolek trzeba sprawdzić, czy już można działać na kontrolce
	private lAktywneSzukanieTowarow := .t.
	cOkno := ThisWindow.name
	
	if type("nOdszukanyIndeks") <> "N"
		private nOdszukanyIndeks := 1
	endif
	
	if IsControlDefined(R_IndeksTowarow, &cOkno)
		nIndeksTowarow := GetProperty(cOkno, "R_IndeksTowarow","Value")
	endif

	if  !IsControlDefined(T_Wyszukaj,&cOkno)
		return
	endif
	
	if empty(cTekstSzukany := upper(GetProperty(cOkno,"T_Wyszukaj","Value")))
		return
	endif

	select("towary")

	if nIndeksTowarow == 5
		for i:=1 to len(cTekstSzukany)
			lCyfrowy := isDigit(substr(cTekstSzukany,i,1))
			if !lCyfrowy
				exit
			endif
		next i
		if lCyfrowy
			if len(cTekstSzukany)<=len(towary->towar)
				towary->(DBSetOrder(1))
				cTekstSzukany := strzero(val(cTekstSzukany),len(towary->towar))
				nOdszukanyIndeks := 1
			endif
			lFound := towary->(DBSeek(cTekstSzukany,.t.))
			if !lFound
				// szukamy w KKresk
				cTekstSzukany := GetProperty(cOkno,"T_Wyszukaj","Value")
				towary->(DBSetOrder(4))
				lFound := towary->(DBSeek(cTekstSzukany,.t.))
				nOdszukanyIndeks := 4
			endif
			if !lFound
				cTekstSzukany := GetProperty(cOkno,"T_Wyszukaj","Value")
				// szukamy w symbolu
				towary->(DBSetOrder(3))
				lFound := towary->(DBSeek(cTekstSzukany,.t.))
				nOdszukanyIndeks := 3
			endif

		endif

		if !lFound
			cTekstSzukany := GetProperty(cOkno,"T_Wyszukaj","Value")
			towary->(DBSetOrder(2))
			lFound := towary->(DBSeek(cTekstSzukany,.t.))
			if lFound
				nOdszukanyIndeks := 2
			else
				towary->(DBSetOrder(3))
				lFound := towary->(DBSeek(cTekstSzukany,.t.))
				if lFound
					nOdszukanyIndeks := 3
				else
					//if !lSzybkaTabelaTowarow
						locate for cTekstSzukany $ nazwa
						lFound := towary->(found())
						if lFound
							nOdszukanyIndeks := -2
						//msgbox(if(lFound,"znaleziono","Nie znaleziono"))
						else
							locate for cTekstSzukany $ symbol
							lFound := towary->(found())
							if lFound
								nOdszukanyIndeks := -3
							else
								nOdszukanyIndeks := 0
							endif
						endif
					//endif
				endif
			endif
		endif
	else
		i:= GetProperty(cOkno,"R_IndeksTowarow","Value")
		towary->(DBSetOrder(i))
		nOdszukanyIndeks := i
		if i = 1
			//cTekstSzukany := StrZero(val(cTekstSzukany),len(towary->towar))
			cTekstSzukany := StrZero(val(cTekstSzukany),len(towary->towar))
		endif
		lFound := towary->(DBSeek(cTekstSzukany,.t.))
		if !lFound .and. i == 2
			locate for cTekstSzukany $ nazwa
			lFound := towary->(found())
			//MsgBox("Szukałem: "+cTekstSzukany +" w indeksie: "+str(towary->(IndexOrd()),1)+if(towary->(found())," i znalazłem", " i nie znalazłem"))
		endif
	endif
	// ten fragment trzeba poprawić
	// żeby sprawdzał czy początek pola z bazy jest równy temu, co szukam
	do case
		case nOdszukanyIndeks  == 1
			//lFound := towary->towar = cTekstSzukany
		case nOdszukanyIndeks  == 2
			// rezygnuję, bo mogłem szukać po fragmencie nazwy
			//lFound := cTekstSzukany == left(towary->nazwa,len(cTekstSzukany))
		case nOdszukanyIndeks  == 3
			lFound := cTekstSzukany == left(towary->symbol,len(cTekstSzukany))
		case i == 4
			lFound := cTekstSzukany == left(towary->kodkresk,len(cTekstSzukany))
	endcase

	towary->(DBSetOrder(nOrder))

	if lFound
		SetProperty(cOkno,"B_Towary","Value", towary->(Recno()))
		
	else
		PlayBeep()
		nPos := (len(GetProperty(cOkno,"T_Wyszukaj","Value"))-1)
		SetProperty(cOkno,"T_Wyszukaj","Value", left(GetProperty(cOkno,"T_Wyszukaj","Value"), nPos))
		SetProperty(cOkno,"T_Wyszukaj","CaretPos",nPos)
	endif

 return

Re: Incremental Search in BROWSE

Posted: Thu Jun 26, 2014 10:04 am
by Clip2Mania
Thanks Marek! I'll try this.
Still learning event handlers... :)

Re: Incremental Search in BROWSE

Posted: Thu Jun 26, 2014 11:53 am
by esgici
Clip2Mania wrote:I would like to implement an incremental search in a BROWSE.
E.g. When typing a character, 'seek' to the first occurrence in the indexed table - when typing a second character, seeking further in the index, and so on. "Clearing" the seek-string by means of a Ctrl-Key combination.
A bit like the example GridIncrementalSearch in \SAMPLES\Controls\Grid.
Is this possible in a BROWSE ? How can I do that?

Best Regards,
Hi

Have you ever seen this ( QuickSearch.zip ) ?

( Older and simpler ;) )

Regards

--

Re: Incremental Search in BROWSE

Posted: Thu Jun 26, 2014 2:25 pm
by Clip2Mania
That is a VERY nice and simple one indeed! ;)

I derived my own "simple one" from Marek's code
CREATE EVENT PROCNAME QuickSearch() HWND MainForm.br_Main.HANDLE MSG WM_CHAR
Then did a simple seek

Code: Select all

function QuickSearch()
local ch, hWnd

ch := HMG_GetLastCharacter(@hWnd)
if asc(ch) = 8
  cStr:=if(len(cStr)>1,left(cStr,len(cStr)-1),"")
else
	cStr:=cStr+upper(ch)
endif

if !DBSEEK(cStr,.T.)
  DBSKIP(-1)
endif

HMG_CleanLastCharacter()   
MainForm.Statusbar.Item(1):=cStr
MainForm.br_Main.Value:=recno()
MainForm.br_Main.Setfocus
return 1
Thanks also for your contribution esgici!

Re: Incremental Search in BROWSE

Posted: Fri Jun 27, 2014 8:19 am
by Clip2Mania
Can anybody help me what I have to change in the above code to also be able to trap the TAB and Function keys?
Thanks

(Please discard - found solution to the above changing WM_CHAR to WM_KEYDOWN)

Re: Incremental Search in BROWSE

Posted: Fri Jun 27, 2014 10:14 am
by Rathinagiri
You can check using

if HMG_VirtualKeyIsPressed ( VK_F1 )

Re: Incremental Search in BROWSE

Posted: Fri Jun 27, 2014 10:30 am
by Clip2Mania
Hi Rathinagiri,

I get a "Referenced, missing, but unknown function(s): MSG()" when I do that..
Something include I need to add?

Re: Incremental Search in BROWSE

Posted: Fri Jun 27, 2014 2:39 pm
by Rathinagiri
Your HMG version?