Jump to content
Sign in to follow this  
Realistphill

Sorting a Guictrlcreatelist

Recommended Posts

Realistphill

Hello all,

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <ListboxConstants.au3>

local $action
guicreate("My GUI", 200, 200)
guisetstate(@SW_SHOW)
$list = guictrlcreatelist("", 20, 20, 80, 150, $LBS_USETABSTOPS)
$ini = IniReadSectionNames("C:\temp\test.ini")
for $i = 1 to $ini[0]
guictrlsetdata($list, $ini[$i])
Next
while 1
   $action = GUIGetMsg()
  Select
  Case $action = $GUI_EVENT_CLOSE
  exit
  EndSelect
WEnd

This is my current code, if you open it (and you have the datafile) it will display a bunch of names on a List which all come from a .ini file.

My question: is there any way to re-organise the list manually? Not alphabetically, but by the user's prefrence. I know there are options to sort it alphabetically and to sort it also depending on the order they are listed in the .ini file. But is there any way to organise the list in any order i want?

Thank you in advance.

Share this post


Link to post
Share on other sites
LarsJ

Hi Realistphill,

Here is a small example with a ListView where you can sort the list manually with drag and drop. You drag an item with the mouse and drop it on another item under the mouse cursor. There are scroll areas near the top and bottom of the ListView. The header is part of the top scroll area.

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>
#include <ScrollBarConstants.au3>
#include <GuiScrollBars.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>
Opt( "MustDeclareVars", 1 )
; Drag and drop
Global $fDragging = 0        ; Flag <> 0 if dragging
Global $idDragLVitem         ; Dummy control for drag and drop
Global $idxDragItem       ; Index of the item being dragged
; Scrolling
Global $fScrollBarEnabled = False   ; True if the scroll bar is present
Global $iScrollAreaHeight = 50  ; The height of the scroll areas
Global $hGui, $hLV, $idLV
MainScript()
Func MainScript()
; Create GUI
$hGui = GUICreate( "ListView", 300, 200, 500, 200 )
; Create ListView control
$idLV = GUICtrlCreateListView( "Items|SubItems", 10, 10, 280, 180 )
GUICtrlSetState( $idLV, $GUI_DROPACCEPTED )
$hLV = ControlGetHandle( $hGui, "", $idLV )
; Add 100 items
For $i = 0 To 99
  GUICtrlCreateListViewItem( "Text " & $i & "|Subtext " & $i, $idLV )
Next

; For drag and drop
$idDragLVitem = GUICtrlCreateDummy()
; Functions for Windows Messages
GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )
; Show GUI
GUISetState( @SW_SHOW, $hGui )
; Message loop
While 1
  If $fDragging Then DragScroll()
  Local $aMsg = GUIGetMsg(1)
  If $aMsg[0] = 0 Or $aMsg[0] = $GUI_EVENT_MOUSEMOVE Then ContinueLoop
  Switch $aMsg[1]
   ; Events for the main GUI
   Case $hGui
    Switch $aMsg[0]
     Case $GUI_EVENT_PRIMARYUP
      If $fDragging Then DropLVitem()
     Case $GUI_EVENT_CLOSE
      ExitLoop
     Case $idDragLVitem
      DragLVitem( GUICtrlRead( $idDragLVitem ) )
    EndSwitch
  EndSwitch
WEnd
GUIDelete( $hGui )
Exit
EndFunc

#cs###################################
#   Functions for Windows Messages   #
#ce###################################
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
#forceref $hWnd, $iMsg, $iwParam
Local $tNMHDR, $hWndFrom, $iCode
$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
$iCode = DllStructGetData($tNMHDR, "Code")
Switch $hWndFrom
Case $hLV
  Switch $iCode
   Case $LVN_BEGINDRAG
    Local $aHit = _GUICtrlListView_HitTest( $hLV )
    If $aHit[0] > -1 Then GUICtrlSendToDummy( $idDragLVitem, $aHit[0] ) ; Start a drag and drop process
  EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc

#cs##################################
#   Drag and drop a ListView item   #
#ce##################################
; Initialisation of the drag and drop process
Func DragLVitem( $index )
$idxDragItem = $index
$fScrollBarEnabled = CheckVScrollBar()
$fDragging = 1
EndFunc
; DragScroll() handles mouse events when a ListView item is dragged and
; the mouse is inside the ListView with the primary mouse button pressed.
Func DragScroll()
Static $aMousePos[2]  ; Save last mouse position to check movement
; Initialisations
Static $x1, $y1, $x2, $y2
If $fDragging = 1 Then
  Local $tRect = _WinAPI_GetWindowRect( $hLV )
  $x1 = DllStructGetData( $tRect, "Left" )
  $y1 = DllStructGetData( $tRect, "Top" )
  $x2 = DllStructGetData( $tRect, "Right" )
  $y2 = DllStructGetData( $tRect, "Bottom" )
  $fDragging = 2
EndIf
Local $aPos = MouseGetPos()
If $aPos[0] > $x1 And $aPos[0] < $x2 And $aPos[1] > $y1 And $aPos[1] < $y2 Then
  ; Mouse cursor is inside the ListView
  Static $iScroll
  If $aPos[0] <> $aMousePos[0] Or $aPos[1] <> $aMousePos[1] Then
   ; The cursor is moving
   ; Scrolling
   If $fScrollBarEnabled Then
    Static $yPos0
    Local $yPos = $aPos[1] - $y1, $yScroll
    If $yPos < $iScrollAreaHeight Then
     ; Scrolling up
     ; Upper scroll area from 0 to $iScrollAreaHeight pixels below top of the ListView
     If $yPos < $yPos0 And _         ; Only scroll when the mouse cursor is moving upwards.
      $fDragging = 3 Then         ; For the first cursor move $fDragging = 2, that means no scroll at the first move (see below).
      $yScroll = $iScrollAreaHeight - $yPos ; The position of the mouse in the scroll area measured from the start of the scroll area.
      $iScroll = -Floor( 1.1 ^ $yScroll )  ; Number of lines to scroll, small number at the start of the scroll area, large at the end.
      GUICtrlSendMsg( $idLV, $LVM_SCROLL, 0, $iScroll )                   ; y=1.1^x: 0~1, 20~6.5, 40~45, 60~300.
      _WinAPI_RedrawWindow( $hLV, 0, 0, $RDW_ERASE + $RDW_INVALIDATE )
     EndIf                ; For the first mouse move $fDragging = 2, that means no scroll at the first move. The purpose
     $yPos0 = $yPos          ; is to prevent a scroll up when a DOWNWARD dragging is INITIATED in the UPPER scroll area.
     $fDragging = 3          ; This situation is only relevant at the initialisation of the drag and drop process.
    ElseIf $yPos > $y2 - $y1 - $iScrollAreaHeight Then
     ; Scrolling down
     ; Lower scroll area from 0 to $iScrollAreaHeight pixels above bottom of the ListView
     If $yPos > $yPos0 And _
      $fDragging = 3 Then
      $yScroll = $yPos - $y2 + $y1 + $iScrollAreaHeight
      $iScroll = Floor( 1.1 ^ $yScroll )
      GUICtrlSendMsg( $idLV, $LVM_SCROLL, 0, $iScroll )
      _WinAPI_RedrawWindow( $hLV, 0, 0, $RDW_ERASE + $RDW_INVALIDATE )
     EndIf
     $yPos0 = $yPos
     $fDragging = 3
    EndIf
   EndIf
   ; Save mouse position
   $aMousePos[0] = $aPos[0]
   $aMousePos[1] = $aPos[1]
  EndIf
EndIf
EndFunc
; Finalisation of the drag and drop process
Func DropLVitem()
$fDragging = 0
_WinAPI_RedrawWindow( $hLV, 0, 0, $RDW_ERASE + $RDW_INVALIDATE )
Local $aHit = _GUICtrlListView_HitTest( $hLV )
If $aHit[0] > -1 Then
  Local $idxDropItem = $aHit[0]
  If $idxDropItem = $idxDragItem Then Return
  Local $aDragTxts = _GUICtrlListView_GetItemTextArray( $hLV, $idxDragItem ), $aTxts
  If $idxDropItem > $idxDragItem Then
   For $i = $idxDragItem To $idxDropItem - 1
    $aTxts = _GUICtrlListView_GetItemTextArray( $hLV, $i+1 )
    _GUICtrlListView_SetItemText( $hLV, $i, $aTxts[1] )
    _GUICtrlListView_SetItemText( $hLV, $i, $aTxts[2], 1 )
   Next
  Else
   For $i = $idxDragItem - 1 To $idxDropItem Step -1
    $aTxts = _GUICtrlListView_GetItemTextArray( $hLV, $i )
    _GUICtrlListView_SetItemText( $hLV, $i+1, $aTxts[1] )
    _GUICtrlListView_SetItemText( $hLV, $i+1, $aTxts[2], 1 )
   Next
  Endif
  _GUICtrlListView_SetItemText( $hLV, $idxDropItem, $aDragTxts[1] )
  _GUICtrlListView_SetItemText( $hLV, $idxDropItem, $aDragTxts[2], 1 )
  _GUICtrlListView_SetItemSelected( $hLV, $idxDropItem, True, True )
Else
  _GUICtrlListView_EnsureVisible( $hLV, $idxDragItem )
  _GUICtrlListView_SetItemSelected( $hLV, $idxDragItem, True, True )
EndIf
EndFunc
Func CheckVScrollBar()
Local $tSCROLLINFO = DllStructCreate( $tagSCROLLINFO )
DllStructSetData( $tSCROLLINFO, 'cbSize', DllStructGetSize( $tSCROLLINFO ) )
DllStructSetData( $tSCROLLINFO, 'fMask', $SIF_ALL )
_GUIScrollBars_GetScrollInfo( $hLV, $SB_VERT, $tSCROLLINFO )
Local $iMax = DllStructGetData( $tSCROLLINFO, 'nMax' )
If $iMax Then Return True
Return False
EndFunc

Move the cursor up and down in the scroll areas to scroll the items.

LarsJ

Edited by LarsJ

Share this post


Link to post
Share on other sites
Realistphill

Hello LarsJ, Thanks for the reply.

The problem is, the list acquires data from a .ini file. So if i was to restart the script the order wont save (which is what im after). Also is there any way of doing this in guictrlcreatelist and not in ListView?

thank you.

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  

×