Jump to content
VAN0

[SOLVED] HDN_TRACK notification in listview?

Recommended Posts

Posted (edited)

Hello.

Am I doing something wrong or HDN_TRACK notification only available for header element created via _GUICtrlHeader_Create() and not available for listview?

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

Opt( "MustDeclareVars", 1 )

Global $hGui, $hLV
Global $rowNum = 100000000 ;number of rows
Global $charNum = 20 ;number of characters

Example()

Func Example()
    $hGui = GUICreate( "Virtual ListViews", 850, 400 )

    Local $idLV = GUICtrlCreateListView( "Col1|Col2|Col3", 20, 40, 850-40, 400-60, $LVS_OWNERDATA, BitOR( $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT ) )
    $hLV = GUICtrlGetHandle( $idLV )

    GUICtrlSendMsg( $idLV, $LVM_SETCOLUMNWIDTH, 0, 100)
    GUICtrlSendMsg( $idLV, $LVM_SETCOLUMNWIDTH, 1, 300)
    GUICtrlSendMsg( $idLV, $LVM_SETCOLUMNWIDTH, 2, 300)
    GUICtrlSendMsg( $idLV, $LVM_SETITEMCOUNT, $rowNum , 0 )

    GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )
    GUISetState( @SW_SHOW )

    While 1
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
    WEnd
    GUIDelete()
EndFunc

Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam )

    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate( $tagNMHDR, $lParam )
    $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) )
    $iCode = DllStructGetData( $tNMHDR, "Code" )

    Switch $hWndFrom

        Case $hLV

            Switch $iCode
                ;this never fire
                Case $HDN_TRACK, $HDN_TRACKW
                    ConsoleWrite("dragging " & @MSEC & @CRLF)
 
                Case $LVN_GETDISPINFOW
                    Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam )
                    If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then

                        Local $sItem = $tNMLVDISPINFO.SubItem = 0 ? String($tNMLVDISPINFO.Item) : FillString($tNMLVDISPINFO.Item, $tNMLVDISPINFO.SubItem)
                        Local Static $tText = DllStructCreate( "wchar[" & $charNum + 1 & "]" )
                        Local Static $pText = DllStructGetPtr( $tText )

                        DllStructSetData( $tText, 1, $sItem )
                        DllStructSetData( $tNMLVDISPINFO, "Text", $pText )
                    EndIf

            EndSwitch

    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc

Func FillString($row, $col)
    Local $n = 65 + Mod($row + (($col - 1) * $charNum),  26)
    Local $r = ""
    For $i = 1 To $charNum
        $r &= Chr($n)
        $n += 1
        If $n > 90 Then $n = 65
    Next
    Return $r
EndFunc

 

 

LarsJ posted nice code that emulates listview header, but I was wondering if there is a more "native" way get these notifications in listview itself

 

[EDIT]

Solution from Larsj below is to remove $HDS_FULLDRAG from listview header style:

  ; Remove the $HDS_FULLDRAG style from the ListView Header to get $HDN_TRACKW notifications
  ;_WinAPI_SetWindowLong( $hHeader, $GWL_STYLE, _WinAPI_GetWindowLong( $hHeader, $GWL_STYLE ) - $HDS_FULLDRAG ) ; AutoIt 3.3.14.5 issue
  DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "SetWindowLongPtrW" : "SetWindowLongW", "hwnd", $hHeader, "int", $GWL_STYLE, "long_ptr", _
  DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "GetWindowLongPtrW" : "GetWindowLongW", "hwnd", $hHeader, "int", $GWL_STYLE )[0] - $HDS_FULLDRAG )
Edited by VAN0

Share this post


Link to post
Share on other sites

WM_NOTIFY messages from a header control, which is a child window of a listview, are not sent to the GUI window and therefore you cannot capture these messages with GUIRegisterMsg(). You must subclass the listview to capture these messages. The easiest way is to use GUIRegisterMsg20().

Share this post


Link to post
Share on other sites
Posted (edited)

Hmmm still nothing:

#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <GUIRegisterMsg20.au3>

Opt( "MustDeclareVars", 1 )

Global $hGui, $hListView, $hHeader
Global $rowNum = 100000000 ;number of rows
Global $charNum = 20 ;number of characters

Example()

Func Example()
    $hGui = GUICreate( "Virtual ListViews", 850, 400 )

    Local $gListView = GUICtrlCreateListView( "Col1|Col2|Col3", 20, 40, 850-40, 400-60, $LVS_OWNERDATA, BitOR( $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT ) )
    $hListView = GUICtrlGetHandle( $gListView )
    $hHeader = HWnd(GUICtrlSendMsg($gListView, $LVM_GETHEADER, 0, 0))

    GUICtrlSendMsg( $gListView, $LVM_SETCOLUMNWIDTH, 0, 100)
    GUICtrlSendMsg( $gListView, $LVM_SETCOLUMNWIDTH, 1, 300)
    GUICtrlSendMsg( $gListView, $LVM_SETCOLUMNWIDTH, 2, 300)
    GUICtrlSendMsg( $gListView, $LVM_SETITEMCOUNT, $rowNum , 0 )

    GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )
    Local $pWM_NOTIFY_SUBCLASS = DllCallbackGetPtr( DllCallbackRegister( "WM_NOTIFY_SUBCLASS", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) )
    DllCall( "comctl32.dll", "bool", "SetWindowSubclass", "hwnd", $hListView, "ptr", $pWM_NOTIFY_SUBCLASS, "uint_ptr", 0, "dword_ptr", 0 ) ; $iSubclassId = 0, $pData = 0
    GUISetState( @SW_SHOW )

    While 1
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
    WEnd
    DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $hListView, "ptr", $pWM_NOTIFY_SUBCLASS, "uint_ptr", 0 ) ; $iSubclassId = 0
    GUIDelete()
EndFunc

Func WM_NOTIFY_SUBCLASS( $hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData )
    If $iMsg <> $WM_NOTIFY Then Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0]

    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate( $tagNMHDR, $lParam )
    $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) )
    $iCode = DllStructGetData( $tNMHDR, "Code" )
    Switch $hWndFrom
        Case $hHeader
            Switch $iCode
                ;this never fire
                Case $HDN_TRACK, $HDN_TRACKW
                    ConsoleWrite("dragging " & @MSEC & @CRLF)
            EndSwitch
    EndSwitch

    Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0]
    #forceref $iSubclassId, $pData
EndFunc

Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam )

    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate( $tagNMHDR, $lParam )
    $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) )
    $iCode = DllStructGetData( $tNMHDR, "Code" )

    Switch $hWndFrom

        Case $hListView

            Switch $iCode

                Case $LVN_GETDISPINFOW
                    Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam )
                    If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then

                        Local $sItem = $tNMLVDISPINFO.SubItem = 0 ? String($tNMLVDISPINFO.Item) : FillString($tNMLVDISPINFO.Item, $tNMLVDISPINFO.SubItem)
                        Local Static $tText = DllStructCreate( "wchar[" & $charNum + 1 & "]" )
                        Local Static $pText = DllStructGetPtr( $tText )

                        DllStructSetData( $tText, 1, $sItem )
                        DllStructSetData( $tNMLVDISPINFO, "Text", $pText )
                    EndIf

            EndSwitch

    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc

Func FillString($row, $col)
    Local $n = 65 + Mod($row + (($col - 1) * $charNum),  26)
    Local $r = ""
    For $i = 1 To $charNum
        $r &= Chr($n)
        $n += 1
        If $n > 90 Then $n = 65
    Next
    Return $r
EndFunc

 

Even example "ListView header, wmm.au3" only logs $HDR_BEGINTRACKW and $HDR_ENDTRACKW

Edited by VAN0

Share this post


Link to post
Share on other sites

You have to remove the $HDS_FULLDRAG style from the ListView Header to get $HDN_TRACKW notifications:

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7

#AutoIt3Wrapper_UseX64=y

Opt( "MustDeclareVars", 1 )

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

Example()

Func Example()
  ; Create GUI
  GUICreate( "ListView header", 420, 122 )

  ; Create ListView
  Local $idListView = GUICtrlCreateListView( "", 10, 10, 400, 104, $GUI_SS_DEFAULT_LISTVIEW-$LVS_SINGLESEL )
  _GUICtrlListView_SetExtendedListViewStyle( $idListView, $LVS_EX_DOUBLEBUFFER+$LVS_EX_FULLROWSELECT )

  ; Add columns to ListView
  _GUICtrlListView_AddColumn( $idListView, "Column 1", 94 )
  _GUICtrlListView_AddColumn( $idListView, "Column 2", 94 )
  _GUICtrlListView_AddColumn( $idListView, "Column 3", 94 )
  _GUICtrlListView_AddColumn( $idListView, "Column 4", 94 )

  ; Get ListView Header
  Local $hHeader = _GUICtrlListView_GetHeader( $idListView )

  ; Remove the $HDS_FULLDRAG style from the ListView Header to get $HDN_TRACKW notifications
  ;_WinAPI_SetWindowLong( $hHeader, $GWL_STYLE, _WinAPI_GetWindowLong( $hHeader, $GWL_STYLE ) - $HDS_FULLDRAG ) ; AutoIt 3.3.14.5 issue
  DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "SetWindowLongPtrW" : "SetWindowLongW", "hwnd", $hHeader, "int", $GWL_STYLE, "long_ptr", _
  DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "GetWindowLongPtrW" : "GetWindowLongW", "hwnd", $hHeader, "int", $GWL_STYLE )[0] - $HDS_FULLDRAG )

  ; Fill ListView
  Local $iRows = 10
  For $i = 0 To $iRows - 1
    GUICtrlCreateListViewItem( $i & "/Column 1|" & $i & "/Column 2|" & $i & "/Column 3|" & $i & "/Column 4", $idListView )
  Next

  ; Subclass ListView
  GUIRegisterMsg20( $idListView, $WM_NOTIFY, ListViewFunc )

  ; Show GUI
  GUISetState( @SW_SHOW )

  ; Message loop
  While 1
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
  WEnd

  ; Cleanup
  GUIDelete()
EndFunc

; ListView message handler function
Func ListViewFunc( $hWnd, $iMsg, $wParam, $lParam )
  Switch DllStructGetData( DllStructCreate( $tagNMHDR, $lParam ), "Code" )
    Case $HDN_BEGINTRACKW
      ConsoleWrite( "HDN_BEGINTRACKW" & @CRLF )
    Case $HDN_TRACKW
      ConsoleWrite( "HDN_TRACKW" & @CRLF )
    Case $HDN_ENDTRACKW
      ConsoleWrite( "HDN_ENDTRACKW" & @CRLF )
  EndSwitch
  #forceref $hWnd, $iMsg, $wParam
EndFunc

 

Share this post


Link to post
Share on other sites

One issue: column new width is not available at $HDN_ENDTRACKW notification:

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7

#AutoIt3Wrapper_UseX64=y

Opt( "MustDeclareVars", 1 )

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

Example()

Func Example()
  ; Create GUI
  GUICreate( "ListView header", 420, 122 )

  ; Create ListView
  Local $idListView = GUICtrlCreateListView( "", 10, 10, 400, 104, $GUI_SS_DEFAULT_LISTVIEW-$LVS_SINGLESEL )
  _GUICtrlListView_SetExtendedListViewStyle( $idListView, $LVS_EX_DOUBLEBUFFER+$LVS_EX_FULLROWSELECT )

  ; Add columns to ListView
  _GUICtrlListView_AddColumn( $idListView, "Column 1", 94 )
  _GUICtrlListView_AddColumn( $idListView, "Column 2", 94 )
  _GUICtrlListView_AddColumn( $idListView, "Column 3", 94 )
  _GUICtrlListView_AddColumn( $idListView, "Column 4", 94 )

  ; Get ListView Header
  Local $hHeader = _GUICtrlListView_GetHeader( $idListView )

  ; Remove the $HDS_FULLDRAG style from the ListView Header to get $HDN_TRACKW notifications
  ;_WinAPI_SetWindowLong( $hHeader, $GWL_STYLE, _WinAPI_GetWindowLong( $hHeader, $GWL_STYLE ) - $HDS_FULLDRAG ) ; AutoIt 3.3.14.5 issue
  DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "SetWindowLongPtrW" : "SetWindowLongW", "hwnd", $hHeader, "int", $GWL_STYLE, "long_ptr", _
  DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "GetWindowLongPtrW" : "GetWindowLongW", "hwnd", $hHeader, "int", $GWL_STYLE )[0] - $HDS_FULLDRAG )

  ; Fill ListView
  Local $iRows = 10
  For $i = 0 To $iRows - 1
    GUICtrlCreateListViewItem( $i & "/Column 1|" & $i & "/Column 2|" & $i & "/Column 3|" & $i & "/Column 4", $idListView )
  Next

  ; Subclass ListView
  GUIRegisterMsg20( $idListView, $WM_NOTIFY, ListViewFunc )

  ; Show GUI
  GUISetState( @SW_SHOW )

  ; Message loop
  While 1
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
  WEnd

  ; Cleanup
  GUIDelete()
EndFunc

; ListView message handler function
Func ListViewFunc( $hWnd, $iMsg, $wParam, $lParam )
    Local $tNMHDR = DllStructCreate( $tagNMHEADER, $lParam )
    Local Static $tItem = DllStructCreate($tagHDITEM)
    Local $hWndFrom = HWnd( $tNMHDR.hWndFrom )
    $tItem.Mask = $HDI_WIDTH
    _SendMessage($hWndFrom, $HDM_GETITEMW, $tNMHDR.Item, $tItem, 0, "wparam", "struct*")
    Switch $tNMHDR.Code
        Case $HDN_BEGINTRACKW
            ConsoleWrite( "HDN_BEGINTRACKW width: " & $tItem.XY & @CRLF )
        Case $HDN_TRACKW
            ConsoleWrite( "HDN_TRACKW" & @CRLF )
        Case $HDN_ENDTRACKW
            ConsoleWrite( "HDN_ENDTRACKW width: " & $tItem.XY & @CRLF )
    EndSwitch
  #forceref $hWnd, $iMsg, $wParam
EndFunc

 

Share this post


Link to post
Share on other sites

Slightly modified your script, now working :

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

Opt("MustDeclareVars", 1)

Global $hHeader, $idDummy, $tItem = DllStructCreate($tagHDITEM)
$tItem.Mask = $HDI_WIDTH

Example()

Func Example()
  ; Create GUI
  GUICreate("ListView header", 420, 122)

  $idDummy = GUICtrlCreateDummy()

  ; Create ListView
  Local $idListView = GUICtrlCreateListView("", 10, 10, 400, 104, $GUI_SS_DEFAULT_LISTVIEW - $LVS_SINGLESEL)
  _GUICtrlListView_SetExtendedListViewStyle($idListView, $LVS_EX_DOUBLEBUFFER + $LVS_EX_FULLROWSELECT)

  ; Add columns to ListView
  _GUICtrlListView_AddColumn($idListView, "Column 1", 94)
  _GUICtrlListView_AddColumn($idListView, "Column 2", 94)
  _GUICtrlListView_AddColumn($idListView, "Column 3", 94)
  _GUICtrlListView_AddColumn($idListView, "Column 4", 94)

  ; Get ListView Header
  $hHeader = _GUICtrlListView_GetHeader($idListView)

  ; Remove the $HDS_FULLDRAG style from the ListView Header to get $HDN_TRACKW notifications
  ;_WinAPI_SetWindowLong( $hHeader, $GWL_STYLE, _WinAPI_GetWindowLong( $hHeader, $GWL_STYLE ) - $HDS_FULLDRAG ) ; AutoIt 3.3.14.5 issue
  DllCall("user32.dll", "long_ptr", @AutoItX64 ? "SetWindowLongPtrW" : "SetWindowLongW", "hwnd", $hHeader, "int", $GWL_STYLE, "long_ptr", _
      DllCall("user32.dll", "long_ptr", @AutoItX64 ? "GetWindowLongPtrW" : "GetWindowLongW", "hwnd", $hHeader, "int", $GWL_STYLE)[0] - $HDS_FULLDRAG)

  ; Fill ListView
  Local $iRows = 10
  For $i = 0 To $iRows - 1
    GUICtrlCreateListViewItem($i & "/Column 1|" & $i & "/Column 2|" & $i & "/Column 3|" & $i & "/Column 4", $idListView)
  Next

  GUIRegisterMsg($WM_NOTIFY, ListViewFunc)
  GUISetState(@SW_SHOW)

  ; Message loop
  While 1
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop
      Case $idDummy
        _SendMessage($hHeader, $HDM_GETITEMW, GUICtrlRead($idDummy), $tItem, 0, "wparam", "struct*")
        ConsoleWrite("New with on column " & GUICtrlRead($idDummy) & " = " & $tItem.XY & @CRLF)
    EndSwitch
  WEnd
EndFunc   ;==>Example

; ListView message handler function
Func ListViewFunc($hWnd, $iMsg, $wParam, $lParam)
  #forceref $hWnd, $iMsg, $wParam
  Local $tNMHDR = DllStructCreate($tagNMHEADER, $lParam)
  If $tNMHDR.hWndFrom = $hHeader Then
    Switch $tNMHDR.Code
      Case $HDN_BEGINTRACKW
        ConsoleWrite("HDN_BEGINTRACKW" & @CRLF)
      Case $HDN_TRACKW
        ConsoleWrite("HDN_TRACKW" & @CRLF)
      Case $HDN_ENDTRACKW
        ConsoleWrite("HDN_ENDTRACKW " & $tNMHDR.Item & @CRLF)
        GUICtrlSendToDummy($idDummy, $tNMHDR.Item)
    EndSwitch
  EndIf
  Return $GUI_RUNDEFMSG
EndFunc   ;==>ListViewFunc

 

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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...