Filterbar in a ListIcon Header EXAMPLE

Share your advanced PureBasic knowledge/code with the community.
nicolaus
Enthusiast
Enthusiast
Posts: 456
Joined: Tue Aug 05, 2003 11:30 pm
Contact:

Filterbar in a ListIcon Header EXAMPLE

Post by nicolaus »

Code updated For 5.20+

Hello,

Here is a example to add a filterbar into a listicon header and search wirth the string of the filterbar.

Please go to this link
FilterBar ListiconGadget Example

Code: Select all

    ;ListIcon Filter example
    ;by nicolaus in the german and english PureBasic board
    ; 10.06.2006
    ;..............................
    ;in this example you see in the header of the listicon a filterbar.
    ;in this bar you can type a string and after 3 secs the filter will search the string in
    ;the listicon items. after you type a string in the filterbar you can also click the button at the
    ;right side of the filterbar.
    ;after click the button or wait 3 secs the function "SearchInLI()" will search the string in the listicon
    ;and select it if the string is found.
    ;
    ;hope you like it.
    ;
    ;regards nico

    #LVM_FIRST = $1000
    #HDM_LAYOUT = (#HDM_FIRST+5)
    #LVM_GETHEADER = (#LVM_FIRST+31)
    #HDS_BUTTONS = $0002
    #HDS_FLAT = $0200
    #HDS_FILTERBAR = $0100
    #HDN_FILTERBTNCLICK = (#HDN_FIRST-13)
    #HDN_FILTERCHANGE = (#HDN_FIRST-12)
    #LVM_SETEXTENDEDLISTVIEWSTYLE = (#LVM_FIRST+54)
    #LVS_EX_FLATSB = $100
    #LVS_EX_HEADERDRAGDROP = $00000010
    #LVS_EX_FULLROWSELECT = $00000020
    #HDI_FILTER = $0100
    #HDFT_ISSTRING = $0000
    #HDM_SETFILTERCHANGETIMEOUT = (#HDM_FIRST+22)

    Global oldproc, newheight, hListIcon, hHeader
; 
;     Structure HDITEM
;       mask
;       cxy
;       pszText
;       hbm
;       cchTextMax
;       fmt
;       lParam
;       iImage
;       iOrder
;       type
;       pvFilter
;     EndStructure
    Structure HDTEXTFILTER Align #PB_Structure_AlignC
      *pszText
      cchTextMax.l
    EndStructure

    Procedure SearchInLI(gadget.l,String.s) ; search in the listicon for the givend string
      SendMessage_(GadgetID(gadget), #LVM_FIRST + $54, $8, 1)
      fItem.LV_FINDINFO
      fItem\flags   = #LVFI_STRING
      fItem\psz     = @String
      itemNumber = SendMessage_(GadgetID(gadget), #LVM_FINDITEM, -1, fItem) ; find Item
      If itemNumber > -1
        Goto SCROLL_AND_SELECT
      Else
        For I = 0 To CountGadgetItems(gadget) - 1
          If String = GetGadgetItemText(gadget, I, 1)
            itemNumber = I
            Goto SCROLL_AND_SELECT
          EndIf
        Next
      EndIf
      Goto PROC_ERROR
      SCROLL_AND_SELECT:
      pItem.POINT
      SendMessage_(GadgetID(gadget), #LVM_GETITEMPOSITION, itemNumber , pItem) ; get item position
      SendMessage_(GadgetID(gadget), #LVM_SCROLL, pItem\x, pItem\y - 150)     ; scroll to item position
      sItem.LV_ITEM
      sItem\mask      = #LVIF_STATE
      sItem\state     = #LVIS_SELECTED
      sItem\stateMask = #LVIS_SELECTED
      SendMessage_(GadgetID(gadget), #LVM_SETITEMSTATE, itemNumber , sItem)    ; set item state as selected     
      Goto PROC_END
      PROC_ERROR:
      MessageRequester("Error", "Can´t finde'" + String + "' in the list", #MB_ICONEXCLAMATION | #MB_OK) 
      PROC_END:
    EndProcedure
    Procedure.l WinProc(hwnd.l, msg.l, wParam.l, lParam.l)
      Result.l = 0
      If msg = #HDM_LAYOUT
        Result = CallWindowProc_(oldproc, hwnd, msg, wParam, lParam)
        *hdlayout.HD_LAYOUT = lParam
        If *hdlayout\prc <> 0
          *rect.RECT = *hdlayout\prc
          *rect\Top = newheight
        EndIf
        If *hdlayout\pwpos <> 0
          *windowpos.WINDOWPOS = *hdlayout\pwpos
          *windowpos\cy = newheight
        EndIf
      Else
        Result = CallWindowProc_(oldproc, hwnd, msg, wParam, lParam)
      EndIf
      ProcedureReturn Result
    EndProcedure
    Procedure CallBack(hwnd.l, msg.l, wParam.l, lParam.l)
      Result = #PB_ProcessPureBasicEvents
      hHDItem.HDITEM
      TFilter.HDTEXTFILTER
      If msg = #WM_NOTIFY
        *pNMHdr.NMHEADER = lParam
        If *pNMHdr\hdr\code = #HDN_FILTERCHANGE 
          TFilter\pszText = AllocateMemory(256)
          TFilter\cchTextMax = 256
          hHDItem\mask = #HDI_FILTER
          hHDItem\type = #HDFT_ISSTRING
          hHDItem\pvFilter = @TFilter
          SendMessage_(hHeader,#HDM_GETITEM,*pNMHdr\iItem,@hHDItem)
          SearchInLI(1,PeekS(TFilter\pszText,256))
        ElseIf *pNMHdr\hdr\code = #HDN_FILTERBTNCLICK
          TFilter\pszText = AllocateMemory(256)
          TFilter\cchTextMax = 256
          hHDItem\mask = #HDI_FILTER
          hHDItem\type = #HDFT_ISSTRING
          hHDItem\pvFilter = @TFilter
          SendMessage_(hHeader,#HDM_GETITEM,*pNMHdr\iItem,@hHDItem)
          SearchInLI(1,PeekS(TFilter\pszText,256))
        EndIf
      EndIf
      ProcedureReturn Result
    EndProcedure

    OpenWindow(0,0,0,400,200,"ListIcon-FilterTest",#PB_Window_SystemMenu)


    hListIcon = ListIconGadget(1,0,0,400,195,"Name",200,#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
    ; next we set the ext-style of the listicon
    SendMessage_(hListIcon,#LVM_SETEXTENDEDLISTVIEWSTYLE,#LVS_EX_FLATSB|#LVS_EX_HEADERDRAGDROP,#LVS_EX_FLATSB|#LVS_EX_HEADERDRAGDROP)
    ; now we look for the handle of the listicon header....
    hHeader = SendMessage_(hListIcon,#LVM_GETHEADER,0,0)
    ; and look for the winproc of the header
    oldproc = SetWindowLong_(hHeader, #GWL_WNDPROC, @WinProc())
    newheight = 35
    ; we set a new height of the listicon header so that we can set the filterbar into the header
    SetWindowPos_(hHeader, 0, 0, 0, GadgetWidth(1), newheight, #SWP_NOZORDER | #SWP_NOMOVE)
    hdItem.HDITEM
    hdItem\mask = #HDI_FILTER
    hdItem\type = #HDFT_ISSTRING
    ; now we set the timeout for the retur of the filter
    SendMessage_(hHeader,#HDM_SETFILTERCHANGETIMEOUT, 0, 3000)
    ; we retrieves the actuall style of the listicon header....
    lStyle = GetWindowLong_(hHeader,#GWL_STYLE)
    ; and add the style #HDS_FILTERBAR to the retrievet style
    lStyle = lStyle | #HDS_FILTERBAR
    ; ok we set the new style to the listicon header
    SetWindowLong_(hHeader,#GWL_STYLE, lStyle)
    AddGadgetColumn(1,1,"City",180)
    SetWindowCallback(@CallBack())

    AddGadgetItem(1, -1, "Andreas" +Chr(10)+ "New York")
    AddGadgetItem(1, -1, "Martin" +Chr(10)+ "Suhl")
    AddGadgetItem(1, -1, "Fred" +Chr(10)+ "Paris")
    AddGadgetItem(1, -1, "Andre" +Chr(10)+ "Erfurt")
    AddGadgetItem(1, -1, "Rene" +Chr(10)+ "Leipzig")
    AddGadgetItem(1, -1, "Sven" +Chr(10)+ "Emden")
    AddGadgetItem(1, -1, "Mischael" +Chr(10)+ "Dresden")
    AddGadgetItem(1, -1, "Marc" +Chr(10)+ "Rom")
    AddGadgetItem(1, -1, "Nico" +Chr(10)+ "Bern")
    AddGadgetItem(1, -1, "Karsten" +Chr(10)+ "Wien")
    AddGadgetItem(1, -1, "Thomas" +Chr(10)+ "Hamburg")
    AddGadgetItem(1, -1, "Bill" +Chr(10)+ "Gera")
    AddGadgetItem(1, -1, "John" +Chr(10)+ "Tokyo")
    AddGadgetItem(1, -1, "Elke" +Chr(10)+ "Miami")
    AddGadgetItem(1, -1, "Sandra" +Chr(10)+ "Moskau")
    AddGadgetItem(1, -1, "Sina" +Chr(10)+ "Jena")
    AddGadgetItem(1, -1, "Liesa" +Chr(10)+ "Berlin")
    AddGadgetItem(1, -1, "Laura" +Chr(10)+ "Lobenstein")
    AddGadgetItem(1, -1, "Terry" +Chr(10)+ "Las Vegas")
    AddGadgetItem(1, -1, "Dave" +Chr(10)+ "London")

    Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow
i can´t post here with code. alltimes i have a errormessage if i want post a message with PB code inside.

regards,
nico
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Great example. I didn't know such a thing was possible. :)

Thanks, I'll be using that sometime.
I may look like a mule, but I'm not a complete ass.
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

Very nice example.

I have some problems when using it with PureLVSORT : see the header colors.
Image
I am using this code to change the header bitmaps :

Code: Select all

Procedure SetHeaderImage(GadgetHandle.l, ImageHandle.l, Column.l, Align.l) ; Set ListIcon Header Image [Align = #HDF_BITMAP_ON_LEFT/RIGHT]
  Protected Var.LVCOLUMN, VarHeader.HDITEM, TextColumn.s, HwndHeader.l
  HwndHeader = SendMessage_(GadgetHandle, #LVM_GETHEADER, 0, 0)
  TextColumn = Space(#MAX_pszText + 1)
  Var\mask = #LVCF_TEXT | #LVCF_FMT
  Var\pszText = @TextColumn
  Var\cchTextMax = #MAX_pszText
  SendMessage_(GadgetHandle, #LVM_GETCOLUMN, Column, @Var)
  VarHeader\mask = #HDI_BITMAP | #HDI_FORMAT | #HDI_TEXT
  VarHeader\fmt = #HDF_BITMAP | Align | #HDF_STRING | Var\fmt
  VarHeader\hbm = ImageHandle
  VarHeader\pszText = @TextColumn
  VarHeader\cchTextMax = Len(TextColumn)
  SendMessage_(HwndHeader, #HDM_SETITEM, Column, @VarHeader)
EndProcedure
Any idea how to fix this ?
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
Dare
Addict
Addict
Posts: 1965
Joined: Mon May 29, 2006 1:01 am
Location: Outback

Post by Dare »

Very nifty. Thank you!
Dare2 cut down to size
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Very good. Another lesson in "possibilities" :)

Thanks for sharing.

cheers
nicolaus
Enthusiast
Enthusiast
Posts: 456
Joined: Tue Aug 05, 2003 11:30 pm
Contact:

Post by nicolaus »

gnozal wrote:Very nice example.

I have some problems when using it with PureLVSORT : see the header colors.
...
Any idea how to fix this ?
I have the same prob here (i work many with your lib) and momently i can´t find a way to fix this prob.

I hope we can fix this prob the next time.
nicolaus
Enthusiast
Enthusiast
Posts: 456
Joined: Tue Aug 05, 2003 11:30 pm
Contact:

Post by nicolaus »

@gnozal

i hafe a idea
if you add the image (with the procedure wat you have post) can you also set the color vor the header to the default color from windows?

if you have test it please write it here ;)
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

nicolaus wrote:@gnozal
i hafe a idea
if you add the image (with the procedure wat you have post) can you also set the color vor the header to the default color from windows?
if you have test it please write it here ;)
It's the first thing I tried : subclassing the listicon to color the headers ; but it don't work. The header is colored but the white zone remains.
I tried #HDI_BITMAP (posted code) and #HDI_IMAGE (with an image index from an image list), same problem.
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
nicolaus
Enthusiast
Enthusiast
Posts: 456
Joined: Tue Aug 05, 2003 11:30 pm
Contact:

Post by nicolaus »

hm now i have test also to add a image in the colum header with your procedure but it is a little bit bad, look at the image

Image

the image and the colum have the same width but it looks not right (the white edge at the left and right site).

i don´t know wat is the prob... :shock:
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

that's cool...

i've adapted this piece of code for my use :

Code: Select all

;#################################
;##### LISTICONGADGET FILTER #####
;#################################

#LVM_GETHEADER = (#LVM_FIRST+31) 
#HDI_FILTER = $0100 
#HDFT_ISSTRING = $0000 
#HDS_FILTERBAR = $0100 
#HDM_SETFILTERCHANGETIMEOUT = #HDM_FIRST+22
#HDM_EDITFILTER = #HDM_FIRST+23
#HDM_CLEARFILTER = #HDM_FIRST+24
#HDN_FILTERCHANGE = #HDN_FIRST-12
#HDN_FILTERBTNCLICK = #HDN_FIRST-13

Structure HDITEM 
  mask.l 
  cxy.l 
  pszText.l 
  hbm.l 
  cchTextMax.l 
  fmt.l 
  lParam.l 
  iImage.l 
  iOrder.l 
  type.l 
  pvFilter.l 
EndStructure 
Structure HDTEXTFILTER 
  pszText.s
  cchTextMax.l 
EndStructure 

Procedure.l ListIconGadget_CallBack(hwnd.l, msg.l, wParam.l, *lParam.NMHDFILTERBTNCLICK) 
  
  Protected Result.l, item.HDITEM, filter.HDTEXTFILTER 
  
  Result = CallWindowProc_(GetProp_(hwnd, "USER_OLDPROC"), hwnd, msg, wParam, *lParam)
  
  If msg = #WM_NOTIFY 
    Select *lParam\hdr\code
      Case #HDN_FILTERCHANGE, #HDN_FILTERBTNCLICK
        filter\pszText = Space(256) 
        filter\cchTextMax = 256 
        item\mask = #HDI_FILTER 
        item\type = #HDFT_ISSTRING 
        item\pvFilter = @filter 
        SendMessage_(GetProp_(hwnd, "USER_HEADER"), #HDM_GETITEM, *lParam\iItem, @item) 
        If GetProp_(hwnd, "USER_HPROC")
          CallFunctionFast(GetProp_(hwnd, "USER_HPROC"), filter\pszText, *lParam\iItem)
        EndIf
    EndSelect 
  EndIf 
  
  ProcedureReturn Result
  
EndProcedure 
Procedure.l ListIconGadget_Filter(gadget.l, *window, *hProc, timeOut.l = 50)
  
  Protected *header, hdItem.HDITEM 
  
  *header = SendMessage_(GadgetID(gadget), #LVM_GETHEADER, #Null, #Null)
  
  If *header
    hdItem\mask = #HDI_FILTER 
    hdItem\type = #HDFT_ISSTRING 
    SendMessage_(*header, #HDM_SETFILTERCHANGETIMEOUT, 0, timeOut) 
    SetWindowLong_(*header, #GWL_STYLE, GetWindowLong_(*header, #GWL_STYLE) | #HDS_FILTERBAR )
    SetProp_(*window, "USER_OLDPROC", SetWindowLong_(*window, #GWL_WNDPROC, @ListIconGadget_CallBack()))
    SetProp_(*window, "USER_HEADER", *header)
    SetProp_(*window, "USER_HPROC", *hProc)
  EndIf
  
EndProcedure

;###################
;##### EXAMPLE #####
;###################

Procedure.l search(text.s, column.l)
  
  If ExamineEnvironmentVariables()
    
    ClearGadgetItemList(1)
    
    While NextEnvironmentVariable()
      Select column
        Case 0: EnvironmentVariable$ = EnvironmentVariableName()
        Case 1: EnvironmentVariable$ = EnvironmentVariableValue()
      EndSelect
      If text = #Null$ Or FindString(LCase(EnvironmentVariable$), LCase(text), 1)
        AddGadgetItem(1, -1, EnvironmentVariableName() + #LF$ + EnvironmentVariableValue()) 
      EndIf
    Wend
    
  EndIf
  
  StatusBarText(0, 0, "Search for '" + text + "' returns " + Str(CountGadgetItems(1)) + " result(s).")
  
EndProcedure

If OpenWindow(0, 0, 0, 640, 400, "EnvironmentVariable", #PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
  
  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(800)
  EndIf
  
  If CreateGadgetList(WindowID(0)) 
    ListIconGadget(1, 5, 5, WindowWidth(0)-10, 370, "Name", 180, #PB_ListIcon_FullRowSelect) 
    AddGadgetColumn(1, 1, "Value", WindowWidth(0)-215)
    ListIconGadget_Filter(1, WindowID(0), @search())
  EndIf
  
  search(#Null$, #Null)
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
  
EndIf
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
nicolaus
Enthusiast
Enthusiast
Posts: 456
Joined: Tue Aug 05, 2003 11:30 pm
Contact:

Post by nicolaus »

@gnozal

Have you found a way to draw it without the probs?
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

nicolaus wrote:@gnozal
Have you found a way to draw it without the probs?
No.
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
User avatar
bbanelli
Enthusiast
Enthusiast
Posts: 543
Joined: Tue May 28, 2013 10:51 pm
Location: Europe
Contact:

Re: Filterbar in a ListIcon Header EXAMPLE

Post by bbanelli »

Sorry to update a thread this old, but this example doesn't work on x64 Windows - it doesn't even triggers debugger error (W7 x64) but crashes whole program.

Reason is in HDTEXTFILTERstructure which should be defined differently, for example:

Code: Select all

Structure HDTEXTFILTER
  pszText.i
  cchTextMax.i
EndStructure
After that change it works with PB 5.4 (b8, x64) like a charm!
"If you lie to the compiler, it will get its revenge."
Henry Spencer
https://www.pci-z.com/
User avatar
bbanelli
Enthusiast
Enthusiast
Posts: 543
Joined: Tue May 28, 2013 10:51 pm
Location: Europe
Contact:

Re: Filterbar in a ListIcon Header EXAMPLE

Post by bbanelli »

In case anyone will need to handle trigger focus on certain filter column, here's a short snippet:

Code: Select all

hListViewHeader = SendMessage_(GadgetID(0), #LVM_GETHEADER, #Null, #Null)
SendMessage_(hListViewHeader, #HDM_EDITFILTER, 0, #True) ;https://msdn.microsoft.com/en-us/library/windows/desktop/bb775312(v=vs.85).aspx
"If you lie to the compiler, it will get its revenge."
Henry Spencer
https://www.pci-z.com/
camille
User
User
Posts: 66
Joined: Tue Nov 19, 2019 12:52 pm

Re: Filterbar in a ListIcon Header EXAMPLE

Post by camille »

Regarding Flypes code from here: viewtopic.php?p=149777#p149777

I get this error (after removing the HDITEM structure):

Code: Select all

Bad parameter type, number expected instead of string.
The line highlighted in the PB gui is:

Code: Select all

CallFunctionFast(GetProp_(hwnd, "USER_HPROC"), filter\pszText, *lParam\iItem)
I've tried to compile it with PB 5.72 LTS Beta 1 (x64).

Does anybody know how to fix it?
Post Reply