Jump to content
Sign in to follow this  

Header Filter Bar Questions

Recommended Posts


I'm trying to figure out how to better work with the header filter bar. I want to be able to do two things:

  • If possible, change the filter icon/image to use my own
  • Submit the filtered text on the selected column when the user presses the ENTER key

It seems that the handle of the filter text bar changes each time when I switch from column to column and the hit test doesn't exactly get the column correct either. So, if I give focus to column 0 and hit ENTER, I receive a handle from WinAPI_GetHandle(), then do the same for column 1, then 0 again, a different handle is sent back for column 0 and the item displayed stays as 1, no matter the column.

Any help would be appreciated. Thanks.

#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>

Global $cDummy
Global $g_idMemo
Global $g__hHeader


Func Example()
    Local $hGUI

    ; Create GUI
    $hGUI = GUICreate("Header", 404, 400)
    $cDummy = GUICtrlCreateDummy()
    $idListView = GUICtrlCreateListView("Col1|Col2|Col3|Col4", 2, 4, 400, 140)
    _GUICtrlListView_SetColumnWidth($idListView, 0, 95)
    _GUICtrlListView_SetColumnWidth($idListView, 1, 95)
    _GUICtrlListView_SetColumnWidth($idListView, 2, 95)
    _GUICtrlListView_SetColumnWidth($idListView, 3, 95)
    $g__hHeader = _GUICtrlListView_GetHeader(GUICtrlGetHandle($idListView))
    $iStyles = _WinAPI_GetWindowLong($g__hHeader, $GWL_STYLE)
    _WinAPI_SetWindowLong($g__hHeader, $GWL_STYLE, BitOR($iStyles, $HDS_FILTERBAR)); Set the filter header
    _GUICtrlListView_SetExtendedListViewStyle($idListView, $g__iLV_EXStyle_GridChecks)
    $g_idMemo = GUICtrlCreateEdit("", 2, 154, 396, 254, 0)
    GUICtrlSetFont($g_idMemo, 9, 400, 0, "Courier New")
    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

    Dim $aAccelKeys[1][2] = [["{ENTER}", $cDummy]]
    GUISetAccelerators($aAccelKeys, $hGUI)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
            Case $cDummy
                WriteStuff($g__hHeader, GUICtrlRead($cDummy))
EndFunc   ;==>Example

; Write a line to the memo control
Func MemoWrite($sMessage)
    GUICtrlSetData($g_idMemo, $sMessage & @CRLF, 1)
EndFunc   ;==>MemoWrite

Func WriteStuff($hHdr, $sDummyText)
    GUICtrlSetData($g_idMemo, "")
    ; Do a hit test on column 2
    Local $aHT = _GUICtrlHeader_HitTest($hHdr, 110, 20)
    MemoWrite("Item index ...................: " & $aHT[0])
    MemoWrite("In client window .............: " & $aHT[1])
    MemoWrite("In control rectangle .........: " & $aHT[2])
    MemoWrite("On divider ...................: " & $aHT[3])
    MemoWrite("On zero width divider ........: " & $aHT[4])
    MemoWrite("Over filter area .............: " & $aHT[5])
    MemoWrite("Over filter button ...........: " & $aHT[6])
    MemoWrite("Above bounding rectangle .....: " & $aHT[7])
    MemoWrite("Below bounding rectangle .....: " & $aHT[8])
    MemoWrite("To right of bounding rectangle: " & $aHT[9])
    MemoWrite("To left of bounding rectangle : " & $aHT[10])
    MemoWrite("Filter Text Read : " & $sDummyText)
    MemoWrite("Handle reported : " & _WinAPI_GetFocus()); <<<< Where is this handle coming from???

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Local $tNMLISTVIEW, $iItemId, $iItem
    Local $tNMHDR =   DllStructCreate($tagNMHDR, $lParam)
    Local $HwndFrom = DllStructGetData($tNMHDR, "HwndFrom")
    Local $iCode =    DllStructGetData($tNMHDR, "Code")
    Switch $HwndFrom
        Case $g__hHeader
            Switch $iCode
                Case $HDN_FILTERBTNCLICK
                    $tNMHDFILTERBTNCLICK = DllStructCreate($tagNMHDFILTERBTNCLICK, $lParam)
                    Local $iColumn = DllStructGetData($tNMHDFILTERBTNCLICK, "Item")
                    Local $tText = DllStructCreate("wchar[64]")
                    Local $pText = DllStructGetPtr($tText)
                    $tHDTEXTFILTER = DllStructCreate($tagHDTEXTFILTER)
                    $pHDTEXTFILTER = DllStructGetPtr($tHDTEXTFILTER)
                    DllStructSetData($tHDTEXTFILTER, "Text", $pText)
                    DllStructSetData($tHDTEXTFILTER, "TextMax", 64)

                    $tHDITEM = DllStructCreate($tagHDITEM)
                    DllStructSetData($tHDITEM, "Mask", $HDI_FILTER)
                    DllStructSetData($tHDITEM, "Type", 0)
                    DllStructSetData($tHDITEM, "pFilter", $pHDTEXTFILTER)
                    $pHDITEM = DllStructGetPtr($tHDITEM)

                    _SendMessage($g__hHeader, $HDM_GETITEMW, $iColumn, $pHDITEM)

                    ; Send column and filter text to dummy
                    GUICtrlSendToDummy($cDummy, $iColumn & "|" & DllStructGetData($tText, 1))

                    Return True


Share this post

Link to post
Share on other sites

Is there maybe a better solution than the one I am implementing for filtering listviews on multiple columns?

Edit: I just found the solution. Simply adding $HDN_FILTERCHANGE to the WM_NOTIFY switch allows the enter key to send the filter on the column that has the focus.

So the case statement would now look like this:



Edited by buymeapc

Share this post

Link to post
Share on other sites

Any ideas on how to change the filter button icon/bitmap?

Or how about changing the color of the filter input field?

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this