Jump to content
Sign in to follow this  
buymeapc

Get ListView Header Order After Drag/Drop

Recommended Posts

buymeapc

Hi all,

So, I was following the Help file trying to get the resulting column order after dragging a column header in a listview. I can't seem to get the order after the drag as the results I receive are from before. It's rather odd. Is there a way I can get this information using WM_NOTIFY like in the below example?

Thanks for the help!

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

Global $g_ListView

Example()

Func Example()
    Local $hGUI

    ; Create GUI
    $hGUI = GUICreate("Header", 400, 300)
    $g_ListView = GUICtrlCreateListView("Column 1|Column 2|Column 3|Column 4", 0, 0, 400, 300, BitOR($LVS_SHOWSELALWAYS, $LVS_REPORT), BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_INFOTIP, $LVS_REPORT, $LVS_EX_HEADERDRAGDROP))
    GUISetState(@SW_SHOW)

    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

    ; Loop until the user exits.
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $hWndFrom, $iCode
    Local $tNMHDR, $tNMHEADER, $tNMHDFILTERBTNCLICK, $tNMHDDISPINFO
    
    $hHwnd = GUICtrlGetHandle($g_ListView)

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $iCode
        Case $HDN_ENDDRAG ; Sent by a header control when a drag operation has ended on one of its items
            ConsoleWrite("!> " & _GUICtrlListView_GetColumnOrder($g_ListView) & @CRLF); <<<<<<<<<<<<<<< This will return the order BEFORE the drop
            Return False ; To allow the control to automatically place and reorder the item
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
Edited by buymeapc

Share this post


Link to post
Share on other sites
buymeapc

Looks like I found an answer. I was hoping WM_NOTIFY would do all the work with any/all listview controls, but with this solution, each loop must check the flag in order to register the changed column order.

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

Global $bColumnOrderChanged = False

Global $g_hHeader
Global $g_ListView

Example()

Func Example()
    Local $hGUI

    ; Create GUI
    $hGUI = GUICreate("Header", 400, 300)
    $g_ListView = GUICtrlCreateListView("Column 1|Column 2|Column 3|Column 4", 0, 0, 400, 300, BitOR($LVS_SHOWSELALWAYS, $LVS_REPORT), BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_INFOTIP, $LVS_REPORT, $LVS_EX_HEADERDRAGDROP))
    $g_hHeader = _GUICtrlListView_GetHeader($g_ListView)
    GUISetState(@SW_SHOW)

    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

    ; Loop until the user exits.
    Do
        Sleep(10)
        If $bColumnOrderChanged Then
            $bColumnOrderChanged = False
            ConsoleWrite(_ArrayToString(_GUICtrlHeader_GetOrderArray($g_hHeader)) & @CRLF)
        EndIf
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $hWndFrom, $iCode
    Local $tNMHDR, $tNMHEADER, $tNMHDFILTERBTNCLICK, $tNMHDDISPINFO
    
    $hHwnd = GUICtrlGetHandle($g_ListView)

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $iCode
        Case $HDN_ENDDRAG ; Sent by a header control when a drag operation has ended on one of its items
            $bColumnOrderChanged = True
            Return False ; To allow the control to automatically place and reorder the item
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

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  

  • Similar Content

    • FrancescoDiMuro
      By FrancescoDiMuro
      Good evening everyone
      I was trying to insert function header to the functions of my script, but, in the SciTE console, this appears:
      Function or struct definition not found, unable to insert header. @Jos Any suggestion?
      Thanks in advance.

      Best Regards.
    • AndyS19
      By AndyS19
      The _WinAPI_TextOut() function requires a x/y point.  In a rectangle enclosing a text character, where is the x/y point, upper left or lower left?  I'm trying to setup a function to print a header, then normal text lines, and I want the header to be at the top of the printable area on a page..  I use _WinAPI_GetDeviceCaps() to get the start of the printable area.  Then at the start of each page, I want to print a header, then text lines.
      $iLeftMargin_X = _WinAPI_GetDeviceCaps($hDC, $PHYSICALOFFSETX) ; returns 151 $iTopMargin_Y = _WinAPI_GetDeviceCaps($hDC, $PHYSICALOFFSETY) ; returns 70 ; print the header: $x = $iLeftMargin_X $y = $iTopMargin_Y WinAPI_TextOut($hDC, $x , $y, "header text") ; print the first text line $y += 22 WinAPI_TextOut($hDC, $x , $y, "The first text line") Will the header text be at the physical top of the printable area or will it be 1 text line lower.  It all depends on whether $iTopMargin_Y refers to the top of the text or the bottom of the text.
    • Skysnake
      By Skysnake
      I am tracking this topic by @LarsJ.  It is very advanced and overkill for what I am currently trying to do.
       
      Problem is this.
      Listview contains columns, one of which is right aligned and gets populated by float values, such as 123.99.  Some do not have decimals ie 124.00 and on sort gets truncated to 124.  Its obviously still the same value, but the display has reset.
      ; line below is for list VIEW ;..................................0.........1......2............ $cListView = GUICtrlCreateListView("CUSTOMER|AMOUNT|DESCRIPTION", 8, 152, 764, 279) GUICtrlSetBkColor($cListView, $GUI_BKCOLOR_LV_ALTERNATE) ; alternate between the listview background color and the listview item background color GUICtrlSetBkColor($cListView, $LVStdClr) ; Set the background color for the listview _GUICtrlListView_SetColumnWidth($cListView, 0, 120) ; -- the client name _GUICtrlListView_SetColumnWidth($cListView, 1, 90) ;-- the amount _GUICtrlListView_JustifyColumn($cListView, 1, 1) ; 1 - Text is right aligned _GUICtrlListView_SetColumnWidth($cListView, 2, 200) ; the description What I am looking for is something native and simple like a 
          _GUICtrlListView_SetColumnFormat($cListView, 1, "%.2f") ;  1 - column is stringformatted to "%.2f"
      So that after each sort it will appear as it was in the original rendering.
      Is there something like this? I have not been able to find a simple solution.

      Thanks.
      Skysnake
    • Ambient
      By Ambient
      I have tried several way sto get this to work to no avail. Any help would be appreciated. #include <ListViewConstants.au3> #include <GuiListView.au3> #include "GuiListViewEx.au3" $idItem = GUICtrlCreateListViewItem($r & " | " & $c & $adoRs.Fields("TransactionAmount").value & " | " & $Timestamp & " | " & _StringProper($adoRs.Fields("Tillid").value) & @CRLF & @CRLF & "Card Number : " & $cardnum & " " , $idListView) ConsoleWrite( "IDITEM" & $idItem) If STRINGLEFT($adoRs.Fields("TransactionAmount").value,1)= "-" Then Consolewrite(" String is Negative" & @CRLF) ;Drops in Here as expected ;GUICtrlSetColor(-1, $COLOR_RED) ; Colour line if item is negative this didn' work $TxC= _GUICtrlListView_SetTextColor($hListView, $CLR_RED) ; I also tried $TxC= _GUICtrlListView_SetTextColor(-1, 0xFF0000) CONSOLEWRITE("TEXTCOLOUR RETURNED " & $TxC & @crlf) ; This is returning True ELSE Consolewrite(" String is NOT Negative" & @CRLF) EndIf  
    • Bilgus
      By Bilgus
      Example of Subclassing listviews using setwindowSubclass in order to intercept WM_KEYUP events
      Also pops context menu on  Shift + F10
      #include <Misc.au3> #include <ListViewConstants.au3> #include <GUIConstants.au3> #include <GuiMenu.au3> #include <WinAPIShellEx.au3> Global $g_hCB, $g_pCB, $g_ahProc[2][2] ;Stores the Data for subclassing listview Global $g_LVKEYUP = 0xFE00, $g_LVKEYDN = 0xFD00 ;Our Own Custom messages (Key Up/Dn) Global $g_iDummyData Global $g_hGui = GUICreate("test") Global $g_hList1 = GUICtrlCreateListView("#|x|y", 5, 24, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList1) Global $g_hList1_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callback Global $g_hContext1 = GUICtrlCreateContextMenu($g_hList1) GUICtrlCreateMenuItem("1", $g_hContext1) GUICtrlCreateMenuItem("2", $g_hContext1) Global $g_hList2 = GUICtrlCreateListView("#|x|y", 5, 100, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList2) Global $g_hList2_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callback Global $g_hContext2 = GUICtrlCreateContextMenu($g_hList2) GUICtrlCreateMenuItem("3", $g_hContext2) GUICtrlCreateMenuItem("4", $g_hContext2) GUISetState(@SW_SHOW) SubClassListView() ;Creates our subclass Func SubClassListView() OnAutoItExitRegister("Cleanup") ;to remove our subclass $g_hCB = DllCallbackRegister('_SubclassProc', 'lresult', 'hwnd;uint;wparam;lparam;uint_ptr;dword_ptr') $g_pCB = DllCallbackGetPtr($g_hCB) $g_ahProc[0][0] = $g_hList1 ;Add the Ids of the controls we'd like to subclass $g_ahProc[1][0] = $g_hList2 ;Set up the subclass _WinAPI_SetWindowSubclass ( $hWnd, $pSubclassProc, $idSubClass [, $pData = 0] ) $g_ahProc[0][1] = _WinAPI_SetWindowSubclass(GUICtrlGetHandle($g_ahProc[0][0]), $g_pCB, $g_ahProc[0][0], $g_hList1_LVN) $g_ahProc[1][1] = _WinAPI_SetWindowSubclass(GUICtrlGetHandle($g_ahProc[1][0]), $g_pCB, $g_ahProc[1][0], $g_hList2_LVN) EndFunc ;==>SubClassListView Func _SubclassProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) #forceref $iID Local $iRtnMsg = 0 ;Events we'd like to intercept If $iMsg = $WM_KEYUP Or $iMsg = $WM_SYSKEYUP Then $iRtnMsg = $g_LVKEYUP ElseIf $iMsg = $WM_KEYDOWN Or $iMsg = $WM_SYSKEYDOWN Then $iRtnMsg = $g_LVKEYDN EndIf ;We Recieve the Id of the dummy through $pData and pass our RtnMsg to the dummy control If $iRtnMsg Then GUICtrlSendToDummy($pData, BitOR($iRtnMsg, $wParam)) ;Pass messages on to the default handler Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>_SubclassProc Func Cleanup() For $i = 0 To UBound($g_ahProc) - 1 ;Remove Our Subclass' by setting it back to the original proc _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($g_ahProc[$i][0]), DllCallbackGetPtr($g_ahProc[$i][1]), $g_ahProc[$i][0]) Next DllCallbackFree($g_hCB) EndFunc ;==>Cleanup While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $g_hList1_LVN ;This is just a dummy it only recieves events ConsoleWrite("LV1 EVENT 0x" & Hex($g_iDummyData, 4) & @CRLF) $g_iDummyData = GUICtrlRead($g_hList1_LVN) ;Retrieve the code that was sent Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN If BitAND($g_iDummyData, 0x00FF) = 0x79 And (_IsPressed("A0") Or _IsPressed("A1")) Then ;Right/ Left Shift & F10 ShowMenu($g_hGui, $g_hList1, $g_hContext1) Else ConsoleWrite("Lv1 KeyDn Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndIf Case $g_LVKEYUP ConsoleWrite("Lv1 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch Case $g_hList2_LVN $g_iDummyData = GUICtrlRead($g_hList2_LVN) ;Retrieve the code that was sent ConsoleWrite("LV2 EVENT 0x" & Hex($g_iDummyData, 4) & @CRLF) Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN ConsoleWrite("Lv2 KeyDn Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode Case $g_LVKEYUP ConsoleWrite("Lv2 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch EndSwitch WEnd Func ShowMenu($hWnd, $idCtrl, $idContext) Local $aPos, $iX, $iY Local $hMenu = GUICtrlGetHandle($idContext) $aPos = ControlGetPos($hWnd, "", $idCtrl) $iX = $aPos[0] $iY = $aPos[1] + $aPos[3] ClientToScreen($hWnd, $iX, $iY) ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) _GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd, $iX, $iY) EndFunc ;==>ShowMenu ; Convert the client (GUI) coordinates to screen (desktop) coordinates Func ClientToScreen($hWnd, ByRef $iX, ByRef $iY) Local $tPoint = DllStructCreate("int;int") DllStructSetData($tPoint, 1, $iX) DllStructSetData($tPoint, 2, $iY) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "struct*", $tPoint) $iX = DllStructGetData($tPoint, 1) $iY = DllStructGetData($tPoint, 2) ; release Struct not really needed as it is a local $tPoint = 0 EndFunc ;==>ClientToScreen  
      Old Code Using setWindowLong
       
×