Jump to content

Header Filter Bar Questions


buymeapc
 Share

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
Global $g__iLV_EXStyle_GridChecks = BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_DOUBLEBUFFER, $LVS_EX_CHECKBOXES, $LVS_EX_HEADERDRAGDROP)

Example()

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")
    
    GUISetState(@SW_SHOW)
    
    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
                ExitLoop
            Case $cDummy
                WriteStuff($g__hHeader, GUICtrlRead($cDummy))
        EndSwitch
    WEnd
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, "")
    Sleep(200)
    ; 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???
EndFunc

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
            EndSwitch
    EndSwitch
EndFunc

 

Link to comment
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:

Case $HDN_FILTERBTNCLICK, $HDN_FILTERCHANGE

 

Edited by buymeapc
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...