Code: Select all
;ListIcon Search and Select matching text
;PB 4.02 - Windows only
;By einander
;Based on Sparkie's Multicolor ListIcon Gadget
;http://www.purebasic.fr/english/viewtopic.php?T=19237&highlight=multicolor+listicon
Structure LIGSearch
Row.l
Column.l
TextRGB.l
BackRGB.l
SearchString.S
Info.l
Input.l
EndStructure
#LVM_GETSUBITEMRECT = $1038
Global _LIGSearch.LIGSearch
Global _LIG , NewList _Searched.l(), NewList _Aux.l()
_LIGSearch\TextRGB=$FF0033
_LIGSearch\BackRGB=$EBF2D8
Procedure$ RandomStr(Maxlen=20) ; make martian text
For i= 0 To Random(Maxlen)+1
A$+Chr(Random(25)+97)
If i=5 :A$+" ":EndIf
Next
ProcedureReturn A$
EndProcedure
Procedure ApiGetTextWidth(A$)
ProcedureReturn SendMessage_(GadgetID(_LIG), #LVM_GETSTRINGWIDTH, 0, @A$)
EndProcedure
Procedure APIGetCharPos(A$,POS)
ProcedureReturn ApiGetTextWidth(Left(A$,POS-1))
EndProcedure
Procedure APIDetachText(DC,*rc.RECT,A$,B$,TextRGB,BackRGB)
SetBkMode_(DC,#OPAQUE)
SetTextColor_(DC,TextRGB): SetBkColor_(DC,BackRGB)
DrawText_(DC,A$,-1,*rc,#DT_NOCLIP) ;detach whole item
FS=1
SetTextColor_(DC,BackRGB):SetBkColor_(DC,TextRGB) ; invert colors
x=*rc\left
Repeat
FS=FindString(A$,B$,FS)
If FS=0:Break:EndIf
*rc\left =x+APIGetCharPos(A$,FS)
DrawText_(DC,B$,-1,*rc,#DT_NOCLIP) ; detach B$
FS+Len(B$)
ForEver
EndProcedure
Procedure CallBack(hwnd, msg, wParam, lParam)
RESULT = #PB_ProcessPureBasicEvents
Select msg
Case #WM_NOTIFY
*nmhdr.NMHDR = lParam
If *nmhdr\code = #NM_CUSTOMDRAW And *nmhdr\hwndFrom = GadgetID(_LIG)
*lvCD.NMLVCUSTOMDRAW = lParam
Select *lvCD\nmcd\dwDrawStage
Case #CDDS_PREPAINT : RESULT = #CDRF_NOTIFYITEMDRAW
Case #CDDS_ITEMPREPAINT : RESULT = #CDRF_NOTIFYSUBITEMDRAW
Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM : RESULT = #CDRF_NOTIFYPOSTPAINT
Case #CDDS_ITEMPOSTPAINT | #CDDS_SUBITEM
ForEach _Aux()
If *lvCD\nmcd\dwItemSpec =_Aux() And *lvCD\iSubItem =_LIGSearch\Column ;If Row & Column
Item$ = GetGadgetItemText(_LIG,_Aux(), *lvCD\iSubItem) ; --> item text
ColumnRc.RECT\left = #LVIR_LABEL+_LIGSearch\Column=0 ; --> item rect
DC=*lvCD\nmcd\hdc
ColumnRc\top = *lvCD\iSubItem
SendMessage_(*lvCD\nmcd\hdr\hwndFrom, #LVM_GETSUBITEMRECT, *lvCD\nmcd\dwItemSpec, @ColumnRc)
If *lvCD\iSubItem = 0 : ColumnRc\left + (GetSystemMetrics_(#SM_CXEDGE) * 3) - 2 ; --> Adjust left margin
Else : ColumnRc\left + GetSystemMetrics_(#SM_CXEDGE) * 3
EndIf
SearchString.S=_LIGSearch\SearchString
APIDetachText(DC,@ColumnRc,Item$,SearchString,_LIGSearch\TextRGB,_LIGSearch\BackRGB)
EndIf
Next
RESULT= #CDRF_SKIPDEFAULT
EndSelect
EndIf
EndSelect
ProcedureReturn RESULT
EndProcedure
Macro RedrawLIG(LIG) ;- RedrawLIG(LIG) ; redraw lListIconGadget
SendMessage_(GadgetID(LIG), #LVM_REDRAWITEMS, 0, CountGadgetItems(LIG)-1)
EndMacro
Macro GadgetBottom(GAD) : GadgetY(GAD)+GadgetHeight(GAD) : EndMacro
Macro GadgetRight(GAD) : GadgetX(GAD)+GadgetWidth(GAD) : EndMacro
Procedure SearchRow(Row)
If CountList(_Searched())
SelectElement(_Searched(),Row)
SendMessage_(GadgetID(_LIG), #LVM_GETITEMPOSITION, _Searched(), pt.POINT) ; get item position
SendMessage_(GadgetID(_LIG), #LVM_SCROLL, pt\x, pt\y - 150) ; scroll to item position
sItem.LVITEM\mask = #LVIF_STATE
sItem\state = #LVIS_SELECTED
sItem\stateMask = #LVIS_SELECTED
SendMessage_(GadgetID(_LIG), #LVM_SETITEMSTATE, _Searched() , sItem) ; set item state as selected
SelectElement(_Searched(),Row) : SetGadgetText(_LIGSearch\Info,Str(ListIndex(_Searched())+1)+" of "+Str(CountList(_Searched()))+ " Matches Found")
Else : SetGadgetText(_LIGSearch\Info,"No Matches")
EndIf
RedrawLIG(_LIG)
SetActiveGadget(_LIGSearch\Input)
EndProcedure
Procedure SearchLIGString(Row=1)
ClearList(_Aux()) : ClearList (_Searched())
For i = 0 To CountGadgetItems(_LIG) - 1
If FindString(GetGadgetItemText(_LIG, i, _LIGSearch\Column),_LIGSearch\SearchString,1)
AddElement(_Aux()):AddElement(_Searched())
_Aux()=i:_Searched()=i
EndIf
Next
SearchRow(Row)
EndProcedure
;Test it <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
hwnd=OpenWindow(0, 100, 100,800,500 ,"Search Matching text",#WS_OVERLAPPEDWINDOW| #PB_Window_ScreenCentered)
StickyWindow(0,1)
CreateGadgetList(hwnd)
_LIG=ListIconGadget(-1, 5, 5, 710, WindowHeight(0)*0.75, "Column 0", 200, #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_FullRowSelect)
SetGadgetFont(_LIG, _MyFontMedium)
AddGadgetColumn(_LIG, 1, "Column 1", 200)
AddGadgetColumn(_LIG, 2, "Column 2", 200)
TextTitle=TextGadget(-1,10,GadgetBottom(_LIG)+10,200,16,"Search text")
FG=Frame3DGadget(-1,GadgetRight(TextTitle)+10,GadgetBottom(_LIG)+20,100,84,"Search in")
_LIGSearch\Input=StringGadget(-1, 10, GadgetBottom(TextTitle), 200, 30, "" )
ColGad0=OptionGadget(-1,GadgetX(FG)+5,GadgetY(FG)+20,90,20,"Column 0"): SetGadgetData(ColGad0,0)
ColGad1=OptionGadget(-1,GadgetX(FG)+5,GadgetY(ColGad0)+20,90,20,"Column 1"):SetGadgetData(ColGad1,1)
ColGad2=OptionGadget(-1,GadgetX(FG)+5,GadgetY(ColGad1)+20,90,20,"Column 2"):SetGadgetData(ColGad2,2)
SetGadgetState(ColGad0,1)
_LIGSearch\Info=TextGadget(-1, 10, GadgetBottom(_LIGSearch\Input)+4, 200, 18, "", #PB_Text_Border )
BtnPrev=ButtonGadget(-1,10,GadgetBottom(_LIGSearch\Info)+4,95,20,"Prev")
BtnNext=ButtonGadget(-1,110,GadgetBottom(_LIGSearch\Info)+4,95,20,"Next")
SetGadgetFont(_LIGSearch\Input, _MyFontMediumBig)
For i = 0 To 13000 ; Fill the ListiconGadget
AddGadgetItem(_LIG, -1, Str(i)+" "+RandomStr(50) + Chr(10) + RandomStr(50) +Chr(10)+RandomStr(50))
Next
SetWindowCallback(@CallBack())
SetActiveGadget(_LIGSearch\Input)
Repeat
EV = WaitWindowEvent()
Select EV
Case #PB_Event_Gadget
Eventgadget=EventGadget()
Select Eventgadget
Case _LIGSearch\Input
_LIGSearch\SearchString=GetGadgetText(_LIGSearch\Input)
If Len(_LIGSearch\SearchString)
If _LIGSearch\SearchString<>OldSearch.S
SearchLIGString(0)
OldSearch=_LIGSearch\SearchString
EndIf
Else
ClearList(_Searched()):ClearList(_Aux())
Selected=1
EndIf
Case ColGad0 To ColGad2
_LIGSearch\Column=GetGadgetData(Eventgadget)
SearchLIGString(0)
SetActiveGadget(_LIGSearch\Input)
Case BtnPrev
If PreviousElement(_Searched())=0 : LastElement(_Searched()) : EndIf
SearchRow(ListIndex(_Searched()))
Case BtnNext
If NextElement(_Searched())=0 : FirstElement(_Searched()) : EndIf
SearchRow(ListIndex(_Searched()))
EndSelect
EndSelect
If CountList(_Searched())=0 And Selected
Selected=0
SetGadgetState(_LIG,-1)
SetGadgetText(_LIGSearch\Info,"")
OldSearch.S=""
EndIf
Until EV = #WM_CLOSE
End