Jump to content

ListView sort problem


Recommended Posts

Hi guys, i have this script:

include <ListViewConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiEdit.au3>
#include <GuiMenu.au3>
#include <WinAPI.au3>

Global $hEdit, $hDC, $hBrush, $Item = -1, $SubItem = 0, $Number = 0, $hMenu
Global Enum $idMoveUp = 1000, $idMoveDown, $idDelete
Global $Style = BitOR($WS_CHILD, $WS_VISIBLE, $ES_AUTOHSCROLL, $ES_LEFT)

$hGUI = GUICreate("_GUICtrlListView_Example", 262, 351, -1, -1)
$cListview = GUICtrlCreateListView("N°|Test|Test2", 5, 5, 250, 272, $LVS_REPORT)
$hListview = GUICtrlGetHandle($cListview)
_GUICtrlListView_SetExtendedListViewStyle($hListview, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_BORDERSELECT))
_GUICtrlListView_SetColumnWidth($hListview, 0, 35)
_GUICtrlListView_SetColumnWidth($hListview, 1, 107)
_GUICtrlListView_SetColumnWidth($hListview, 2, 108)
$Label = GUICtrlCreateLabel("Name", 13, 290, 67, 17)
$c_Button_Add = GUICtrlCreateButton("Add", 90, 315, 80, 25)
$Info = GUICtrlCreateInput("Value", 88, 286, 83, 21)
$c_Button_Save = GUICtrlCreateButton("Save", 174, 284, 80, 25)

$hMenu = _GUICtrlMenu_CreatePopup()
_GUICtrlMenu_InsertMenuItem($hMenu, 0, "Move Up", $idMoveUp)
_GUICtrlMenu_InsertMenuItem($hMenu, 1, "Move Down", $idMoveDown)
_GUICtrlMenu_InsertMenuItem($hMenu, 3, "", 0)
_GUICtrlMenu_InsertMenuItem($hMenu, 3, "Delete", $idDelete)

$c_Dummy_Down = GUICtrlCreateDummy()
$c_Dummy_Up = GUICtrlCreateDummy()
$c_Dummy_Delete = GUICtrlCreateDummy()
$c_Dummy_Enter = GUICtrlCreateDummy()

Local $AccelKeys[4][2] = [["{DELETE}", $c_Dummy_Delete],["{UP}", $c_Dummy_Up],["{DOWN}", $c_Dummy_Down],["{ENTER}", $c_Dummy_Enter]]
 
GUISetAccelerators($AccelKeys, $hGUI)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
Global $B_DESCENDING[_GUICtrlListView_GetColumnCount($hListview)]
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $c_Button_Add
            Add_Item()
        Case $c_Button_Save
            Save_List()
        Case $c_Dummy_Delete
            Delete_Item()
        Case $c_Dummy_Down
            Move_Down()
        Case $c_Dummy_Up
            Move_Up()
        Case $c_Dummy_Enter
            If _WinAPI_GetFocus() = $hEdit Then _WinAPI_SetFocus($hListview) ; fires $EN_KILLFOCUS in WM_COMMAND
        Case $cListview
            _GUICtrlListView_SimpleSort($hListview, $B_DESCENDING, GUICtrlGetState($cListview))
    EndSwitch
WEnd

Func Add_Item()
    $Number += 1
    _GUICtrlListView_AddItem($hListview, $Number, -1, 9999 + $Number) ; add lparam value, is used for sorting as far as I remember
    _GUICtrlListView_AddSubItem($hListview, $Number - 1, GUICtrlRead($Label), 1)
    _GUICtrlListView_AddSubItem($hListview, $Number - 1, GUICtrlRead($Info), 2)
EndFunc   ;==>Add_Item
Func Delete_Item()
    _GUICtrlListView_DeleteItemsSelected($hListview)
    _Arrange_Numbers()
EndFunc   ;==>Delete_Item
Func _Arrange_Numbers()
    Dim $iCount = 0
    $Total_Number = _GUICtrlListView_GetItemCount($hListview) - 1
    For $i = 0 To $Total_Number
        $iCount += 1
        _GUICtrlListView_SetItemText($hListview, $i, $iCount)
    Next
EndFunc   ;==>_Arrange_Numbers

Func Save_List()
    Local $Save = FileSaveDialog("Save", @WorkingDir, "Txt Files (*.txt)", 2, "Test_File_" & @MDAY & "-" & @MON & "-" & @YEAR & "_" & @HOUR & "-" & @MIN)
    If @error Then
        ConsoleWrite("Abort")
    Else
        $List = FileOpen($Save & ".txt", 2)
        $Number_items = _GUICtrlListView_GetItemCount($hListview)
        For $i = 0 To $Number_items - 1 Step +1
            $output = StringReplace(_GUICtrlListView_GetItemTextString($hListview, $i), "|", " - ")
            FileWriteLine($List, $output)
        Next
        FileClose($List)
    EndIf
EndFunc   ;==>Save_List

Func Move_Up()
    Local $Sel, $aArrayListView
    $aArrayListView = _GUICtrlListView_CreateArray($hListview)
    $Sel = _GUICtrlListView_GetNextItem($hListview)
    If $Sel > 0 Then
        Local $SelItem, $NxtItem
        $SelItem = _GUICtrlListView_GetItemTextArray($hListview, $Sel)
        $PrvItem = _GUICtrlListView_GetItemTextArray($hListview, $Sel - 1)
        For $i = 1 To $SelItem[0]
            $aArrayListView[$Sel][$i - 1] = $PrvItem[$i]
            $aArrayListView[$Sel - 1][$i - 1] = $SelItem[$i]
            _GUICtrlListView_SetItemText($hListview, $Sel, $PrvItem[$i], $i - 1)
            _GUICtrlListView_SetItemText($hListview, $Sel - 1, $SelItem[$i], $i - 1)
            _GUICtrlListView_SetItemSelected($hListview, $Sel, 0)
            _GUICtrlListView_SetItemSelected($hListview, $Sel - 1)
        Next
    EndIf
    _Arrange_Numbers()
EndFunc   ;==>Move_Up

Func Move_Down()
    Local $Sel, $Lst, $aArrayListView
    $aArrayListView = _GUICtrlListView_CreateArray($hListview)
    $Sel = _GUICtrlListView_GetNextItem($hListview)
    $Lst = _GUICtrlListView_GetItemCount($hListview) - 1
    If $Sel < $Lst And $Sel <> -1 Then
        Local $SelItem, $NxtItem
        $SelItem = _GUICtrlListView_GetItemTextArray($hListview, $Sel)
        $NxtItem = _GUICtrlListView_GetItemTextArray($hListview, $Sel + 1)
        For $i = 1 To $SelItem[0]
            $aArrayListView[$Sel][$i - 1] = $NxtItem[$i]
            $aArrayListView[$Sel + 1][$i - 1] = $SelItem[$i]
            _GUICtrlListView_SetItemText($hListview, $Sel, $NxtItem[$i], $i - 1)
            _GUICtrlListView_SetItemText($hListview, $Sel + 1, $SelItem[$i], $i - 1)
            _GUICtrlListView_SetItemSelected($hListview, $Sel, 0)
            _GUICtrlListView_SetItemSelected($hListview, $Sel + 1)
        Next
    EndIf
    _Arrange_Numbers()
EndFunc   ;==>Move_Down

Func _GUICtrlListView_CreateArray($hListview, $sDelimeter = '|')
    Local $iColumnCount = _GUICtrlListView_GetColumnCount($hListview), $iDim = 0, $iItemCount = _GUICtrlListView_GetItemCount($hListview)
    If $iColumnCount < 3 Then
        $iDim = 3 - $iColumnCount
    EndIf
    If $sDelimeter = Default Then
        $sDelimeter = '|'
    EndIf
    Local $aColumns = 0, $aReturn[$iItemCount + 1][$iColumnCount + $iDim] = [[$iItemCount, $iColumnCount, '']]
    For $i = 0 To $iColumnCount - 1
        $aColumns = _GUICtrlListView_GetColumn($hListview, $i)
        $aReturn[0][2] &= $aColumns[5] & $sDelimeter
    Next
    $aReturn[0][2] = StringTrimRight($aReturn[0][2], StringLen($sDelimeter))
    For $i = 0 To $iItemCount - 1
        For $j = 0 To $iColumnCount - 1
            $aReturn[$i + 1][$j] = _GUICtrlListView_GetItemText($hListview, $i, $j)
        Next
    Next
    Return SetError(Number($aReturn[0][0] = 0), 0, $aReturn)
EndFunc   ;==>_GUICtrlListView_CreateArray

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListview
            Switch $iCode
                Case $NM_DBLCLK
                    Local $aHit = _GUICtrlListView_SubItemHitTest($hListview)
                    If ($aHit[0] <> -1) And ($aHit[1] = 0) Then
                        $Item = $aHit[0]
                        $SubItem = 0
                        Local $aRect = _GUICtrlListView_GetItemRect($hListview, $Item)
                    ElseIf ($aHit[0] <> -1) And ($aHit[1] > 0) Then
                        $Item = $aHit[0]
                        $SubItem = $aHit[1]
                        Local $aRect = _GUICtrlListView_GetSubItemRect($hListview, $Item, $SubItem)
                    Else
                        Return $GUI_RUNDEFMSG
                    EndIf
                    Local $iItemText = _GUICtrlListView_GetItemText($hListview, $Item, $SubItem)
                    Local $iLen = _GUICtrlListView_GetStringWidth($hListview, $iItemText)
                    $hEdit = _GUICtrlEdit_Create($hGUI, $iItemText, $aRect[0] + 8, $aRect[1] + 7, $iLen + 10, 17, $Style)
                    _GUICtrlEdit_SetSel($hEdit, 0, -1)
                    _WinAPI_SetFocus($hEdit)
                    $hDC = _WinAPI_GetWindowDC($hEdit)
                    $hBrush = _WinAPI_CreateSolidBrush(0x0000FF)
                    FrameRect($hDC, 0, 0, $iLen + 10, 17, $hBrush)
                Case $NM_RCLICK
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                    If DllStructGetData($tInfo, "Item") > -1 Then
                        _GUICtrlMenu_TrackPopupMenu($hMenu, $hGUI)
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func FrameRect($hDC, $nLeft, $nTop, $nRight, $nBottom, $hBrush)
    Local $stRect = DllStructCreate("int;int;int;int")
    DllStructSetData($stRect, 1, $nLeft)
    DllStructSetData($stRect, 2, $nTop)
    DllStructSetData($stRect, 3, $nRight)
    DllStructSetData($stRect, 4, $nBottom)
    DllCall("user32.dll", "int", "FrameRect", "hwnd", $hDC, "ptr", DllStructGetPtr($stRect), "hwnd", $hBrush)
EndFunc   ;==>FrameRect

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $iCode = BitShift($wParam, 16)
    Switch $lParam
        Case $hEdit
            Switch $iCode
                Case $EN_KILLFOCUS
                    Local $iText = _GUICtrlEdit_GetText($hEdit)
                    _GUICtrlListView_SetItemText($hListview, $Item, $iText, $SubItem)
                    _WinAPI_DeleteObject($hBrush)
                    _WinAPI_ReleaseDC($hEdit, $hDC)
                    _WinAPI_DestroyWindow($hEdit)
                    $Item = -1
                    $SubItem = 0
            EndSwitch
    EndSwitch
    Switch $wParam
        Case $idMoveUp
            Move_Up()
        Case $idMoveDown
            Move_Down()
        Case $idDelete
            Delete_Item()
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

I can sort item with ARROW_UP and ARROW_DOWN on the keyboard, move in one position

Work if i select ONE item, not work with multiple items ( CTRL + Click )

How i can manage multiple item selecting and Move_Func?

Thanks for any help

Edited by johnmcloud
Link to comment
Share on other sites

  • Moderators

johnmcloud,

Look inside my GUIListViewEx UDF and you will see how I did it. ;)

M23

Edit: Although I now notice that I only move multiple items by dragging, the principle should be transferable. Let me know if you run into problems and we can work on it together later in the week. :)

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Hi Melba, you don't want to make my life easier? :D

If you have time

Many func of your UDF to check how it work:

_GUIListViewEx_Up ( Down )

_GUIListViewEx_Array_Swap

_GUIListViewEx_Data_Change

_GUIListViewEx_Highlight

_GUIListViewEx_Return_Array

Edited by johnmcloud
Link to comment
Share on other sites

  • Moderators

johnmcloud,

I know how it works! :D

Let me look into seeing how we might get your script to do something similar - but I am off to London soon to see a concert with my son (the wonderful Steven Wilson at the Royal Festival Hall) and I will not be able to work on it until I return late tomorrow. So please be patient. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

johnmcloud,

I know how it works! :D

I was referring to me :D

Let me look into seeing how we might get your script to do something similar - but I am off to London soon to see a concert with my son (the wonderful Steven Wilson at the Royal Festival Hall) and I will not be able to work on it until I return late tomorrow. So please be patient. :)

M23

Ok, don't worry. Have fun ;)

Link to comment
Share on other sites

Where did you get _GUICtrlListView_CreateArray from? I'm not looking for my name to be there, but a link would be useful just in case I update that function in the future, you understand?

Edited by guinness

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

guinness, is yours? i don't have idea, really, i have find it somewhere on another site many time ago, 7-8 month i think. I don't remember the site anyway

Sigh! That's why people should post a back reference, not out of courtesy, but out of common sense for if the developer updates the UDF. Are you sure it's 7-8 months? As the code above was created 4 months ago. Oh well, never mind. Edited by guinness

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

  • Moderators

johnmcloud,

The concert was suitably epic and I had a splendid evening. :thumbsup:

To give you a flavour, this is taken from the last tour - but it was the opener last night:

Now to work on your problem. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

  • Moderators

johnmcloud,

I have now got my UDF to move multiple items both dragged and via a button - now to get your script to do it. :)

M23

Edit:

Here is a version of your script which uses the UDF:

#include <ListViewConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiEdit.au3>
#include <GuiMenu.au3>
#include <WinAPI.au3>

#include "GUIListViewEx_Mod.au3"

Global $hEdit, $hDC, $hBrush, $Item = -1, $SubItem = 0, $Number = 0, $hMenu
Global Enum $idMoveUp = 1000, $idMoveDown, $idDelete
Global $Style = BitOR($WS_CHILD, $WS_VISIBLE, $ES_AUTOHSCROLL, $ES_LEFT)

$hGUI = GUICreate("_GUICtrlListView_Example", 262, 351, -1, -1)
$cListview = GUICtrlCreateListView("N°|Test|Test2", 5, 5, 250, 272, $LVS_REPORT)
$hListview = GUICtrlGetHandle($cListview)
_GUICtrlListView_SetExtendedListViewStyle($hListview, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_BORDERSELECT))
_GUICtrlListView_SetColumnWidth($hListview, 0, 35)
_GUICtrlListView_SetColumnWidth($hListview, 1, 107)
_GUICtrlListView_SetColumnWidth($hListview, 2, 108)

$iLV_Index = _GUIListViewEx_Init($hListview, "", 0, 0, True)

$Label = GUICtrlCreateLabel("Name", 13, 290, 67, 17)
$c_Button_Add = GUICtrlCreateButton("Add", 90, 315, 80, 25)
$Info = GUICtrlCreateInput("Value", 88, 286, 83, 21)
$c_Button_Save = GUICtrlCreateButton("Save", 174, 284, 80, 25)

$hMenu = _GUICtrlMenu_CreatePopup()
_GUICtrlMenu_InsertMenuItem($hMenu, 0, "Move Up", $idMoveUp)
_GUICtrlMenu_InsertMenuItem($hMenu, 1, "Move Down", $idMoveDown)
_GUICtrlMenu_InsertMenuItem($hMenu, 3, "", 0)
_GUICtrlMenu_InsertMenuItem($hMenu, 3, "Delete", $idDelete)

$c_Dummy_Down = GUICtrlCreateDummy()
$c_Dummy_Up = GUICtrlCreateDummy()
$c_Dummy_Delete = GUICtrlCreateDummy()
$c_Dummy_Enter = GUICtrlCreateDummy()

Local $AccelKeys[4][2] = [["{DELETE}", $c_Dummy_Delete],["{UP}", $c_Dummy_Up],["{DOWN}", $c_Dummy_Down],["{ENTER}", $c_Dummy_Enter]]
GUISetAccelerators($AccelKeys, $hGUI)

Global $B_DESCENDING[_GUICtrlListView_GetColumnCount($hListview)]

GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $c_Button_Add
            Add_Item()
        Case $c_Button_Save
            Save_List()
        Case $c_Dummy_Delete
            Delete_Item()
        Case $c_Dummy_Down
            Move_Down()
        Case $c_Dummy_Up
            Move_Up()
        Case $c_Dummy_Enter
            If _WinAPI_GetFocus() = $hEdit Then _WinAPI_SetFocus($hListview) ; fires $EN_KILLFOCUS in WM_COMMAND
            ;Case $cListview
            ;    _GUICtrlListView_SimpleSort($hListview, $B_DESCENDING, GUICtrlGetState($cListview))
    EndSwitch
WEnd

Func Add_Item()
    $Number += 1
    $vData = $Number & "|" & GUICtrlRead($Label) & "|" & GUICtrlRead($Info)
    _GUIListViewEx_Insert($vData)
EndFunc   ;==>Add_Item

Func Delete_Item()
    _GUIListViewEx_Delete()
EndFunc   ;==>Delete_Item

Func Save_List()
    Local $Save = FileSaveDialog("Save", @WorkingDir, "Txt Files (*.txt)", 2, "Test_File_" & @MDAY & "-" & @MON & "-" & @YEAR & "_" & @HOUR & "-" & @MIN)
    If @error Then
        ConsoleWrite("Abort")
    Else
        $List = FileOpen($Save & ".txt", 2)
        $Number_items = _GUICtrlListView_GetItemCount($hListview)
        For $i = 0 To $Number_items - 1 Step +1
            $output = StringReplace(_GUICtrlListView_GetItemTextString($hListview, $i), "|", " - ")
            FileWriteLine($List, $output)
        Next
        FileClose($List)
    EndIf
EndFunc   ;==>Save_List

Func Move_Up()
    _GUIListViewEx_Up()
EndFunc   ;==>Move_Up

Func Move_Down()
    _GUIListViewEx_Down()
EndFunc   ;==>Move_Down


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)

    _GUIListViewEx_WM_NOTIFY_Handler($hWnd, $iMsg, $iwParam, $ilParam)

    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListview
            Switch $iCode
                Case $NM_DBLCLK
                    Local $aHit = _GUICtrlListView_SubItemHitTest($hListview)
                    If ($aHit[0] <> -1) And ($aHit[1] = 0) Then
                        $Item = $aHit[0]
                        $SubItem = 0
                        Local $aRect = _GUICtrlListView_GetItemRect($hListview, $Item)
                    ElseIf ($aHit[0] <> -1) And ($aHit[1] > 0) Then
                        $Item = $aHit[0]
                        $SubItem = $aHit[1]
                        Local $aRect = _GUICtrlListView_GetSubItemRect($hListview, $Item, $SubItem)
                    Else
                        Return $GUI_RUNDEFMSG
                    EndIf
                    Local $iItemText = _GUICtrlListView_GetItemText($hListview, $Item, $SubItem)
                    Local $iLen = _GUICtrlListView_GetStringWidth($hListview, $iItemText)
                    $hEdit = _GUICtrlEdit_Create($hGUI, $iItemText, $aRect[0] + 8, $aRect[1] + 7, $iLen + 10, 17, $Style)
                    _GUICtrlEdit_SetSel($hEdit, 0, -1)
                    _WinAPI_SetFocus($hEdit)
                    $hDC = _WinAPI_GetWindowDC($hEdit)
                    $hBrush = _WinAPI_CreateSolidBrush(0x0000FF)
                    FrameRect($hDC, 0, 0, $iLen + 10, 17, $hBrush)
                Case $NM_RCLICK
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                    If DllStructGetData($tInfo, "Item") > -1 Then
                        _GUICtrlMenu_TrackPopupMenu($hMenu, $hGUI)
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func FrameRect($hDC, $nLeft, $nTop, $nRight, $nBottom, $hBrush)
    Local $stRect = DllStructCreate("int;int;int;int")
    DllStructSetData($stRect, 1, $nLeft)
    DllStructSetData($stRect, 2, $nTop)
    DllStructSetData($stRect, 3, $nRight)
    DllStructSetData($stRect, 4, $nBottom)
    DllCall("user32.dll", "int", "FrameRect", "hwnd", $hDC, "ptr", DllStructGetPtr($stRect), "hwnd", $hBrush)
EndFunc   ;==>FrameRect

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $iCode = BitShift($wParam, 16)
    Switch $lParam
        Case $hEdit
            Switch $iCode
                Case $EN_KILLFOCUS
                    Local $iText = _GUICtrlEdit_GetText($hEdit)
                    _GUICtrlListView_SetItemText($hListview, $Item, $iText, $SubItem)
                    _WinAPI_DeleteObject($hBrush)
                    _WinAPI_ReleaseDC($hEdit, $hDC)
                    _WinAPI_DestroyWindow($hEdit)
                    $Item = -1
                    $SubItem = 0
            EndSwitch
    EndSwitch
    Switch $wParam
        Case $idMoveUp
            Move_Up()
        Case $idMoveDown
            Move_Down()
        Case $idDelete
            Delete_Item()
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

And here is a beta version of the UDF which does the multiple selection move you wanted - save as GUIListViewEx_Mod.au3:

#include-once

; #INDEX# ============================================================================================================
; Title .........: GUIListViewEx
; AutoIt Version : 3.3 +
; Language ......: English
; Description ...: Permits insertion, deletion, moving, dragging and sorting of items within activated ListViews
; Remarks .......: - It is important to use _GUIListViewEx_Close when a enabled ListView is deleted to free the memory used
;                    by the $aGLVEx_Data array which shadows the ListView contents.
;                  - If the script already has WM_NOTIFY, WM_MOUSEMOVE or WM_LBUTTONUP handlers then only set the
;                    unregistered messages in _GUIListViewEx_DragRegister and call the relevant _GUIListViewEx_WM_#####_Handler from
;                    within the existing handler
;                  - Uses 2 undocumented function within GUIListView UDF to set and colour insert mark (thanks rover)
; Author ........: Melba23 - credit to martin (basic drag code), Array.au3 authors (original array functions)
; Modified ......;
; ====================================================================================================================

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

; #INCLUDES# =========================================================================================================
#include <GuiListView.au3>
#include <GUIImageList.au3>

; #GLOBAL VARIABLES# =================================================================================================
; Array to hold registered ListView data
Global $aGLVEx_Data[1][7] = [[0, 0]]
; [0][0] = Count            [n][0] = ListView handle
; [0][1] = Active Index        [n][1] = Native ListView ControlID / 0
;                             [n][2] = Content array
;                             [n][3] = [0] element is count
;                           [n][4] = Sorting array
;                           [n][5] = Drag image
;                             [n][6] = Checkbox array
; Variables for all UDF functions
Global $hGLVEx_Handle, $hGLVEx_CID, $aGLVEx_Array
; Variables for UDF dragging handlers
Global $iGLVEx_Dragging = 0, $iGLVExDragged_Index, $hGLVExDragged_Image = 0, $iGLVExInsert_Index = -1, $iGLVExLast_Y
Global $fGLVEx_Bar_Under, $fGLVEx_MultipleDrag, $aGLVExDragCheck_Array

; #CURRENT# ==========================================================================================================
; _GUIListViewEx_Init:                 Enables UDF button functions for the ListView and sets insert mark colour
; _GUIListViewEx_Close:                Disables all UDF functions for the specified ListView and clears all memory used
; _GUIListViewEx_SetActive:            Set specified ListView as active for UDF functions
; _GUIListViewEx_GetActive:            Get index number of ListView active for UDF functions
; _GUIListViewEx_Return_Array:         Returns an array reflecting the current state of the ListView
; _GUIListViewEx_Insert:               Inserts data just below selected item in active ListView
; _GUIListViewEx_Delete:               Deletes selected item in active ListView
; _GUIListViewEx_Up:                   Moves selected item in active ListView up 1 place
; _GUIListViewEx_Down                  Moves selected item in active ListView down 1 place
; _GUIListViewEx_DragRegister:         Registers Windows messages to enable item dragging for listed ListViews
; _GUIListViewEx_WM_NOTIFY_Handler:    Windows message handler for WM_NOTIFY
; _GUIListViewEx_WM_MOUSEMOVE_Handler: Windows message handler for WM_MOUSEMOVE
; _GUIListViewEx_WM_LBUTTONUP_Handler: Windows message handler for WM_LBUTTONUP
; ====================================================================================================================

; #INTERNAL_USE_ONLY#=================================================================================================
; _GUIListViewEx_HighLight:    Highlights specified ListView item and ensures it is visible
; _GUIListViewEx_Data_Change:  Resets ListView items within a defined range to the current values in the stored array
; _GUIListViewEx_Array_Add:    Adds a specified value at the end of an array
; _GUIListViewEx_Array_Insert: Adds a value at the specified index of an array
; _GUIListViewEx_Array_Delete: Deletes a specified index from an array
; _GUIListViewEx_Array_Swap:   Swaps specified elements within an array
; ====================================================================================================================

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Init
; Description ...: Enables UDF button functions for the ListView and sets insert mark colour for drag function
; Syntax.........: _GUIListViewEx_Init($hLV, [$aArray = "", [$iStart = 0, [$iColour, [$fSort, $fImage]]]]])
; Parameters ....: $hLV     - Handle or ControlID of ListView
;                  $a Array - Name of array used to fill ListView.  "" = empty ListView
;                  $iStart  - 0 (default) = ListView data starts in [0] element of array, 1 = Count in [0] element
;                  $iColour - RGB colour for insert mark (default = black)
;                  $fSort   - True = ListView can be sorted by click on column header - (Default = False)
;                  $fImage  - True = Shadow image of dragged item when dragging
; Requirement(s).: v3.3 +
; Return values .: Index number of ListView for use in other GUIListViewEx functions
; Author ........: Melba23
; Modified ......:
; Remarks .......: - If the ListView is the only one enabled, it is automatically set as active
;                  - If no array is passed a shadow array is created automatically - if the ListView has more than
;                  1 column this array is 2D with the second dimension set to the number of columns
;                  - The shadow array has a count in element [0] added if it does not exist. However, if the $iStart
;                  parameter is set to 0 this count element will not be returned by other GUIListViewEx functions
;                  - Only first item of a multiple selection is shadow imaged when dragging (API limitation)
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Init($hLV, $aArray = "", $iStart = 0, $iColour = 0, $fSort = False, $fImage = False)

    Local $iIndex = 0

    ; See if there is a blank line available in the array
    For $i = 1 To $aGLVEx_Data[0][0]
        If $aGLVEx_Data[$i][0] = 0 Then
            $iIndex = $i
            ExitLoop
        EndIf
    Next
    ; If no blank line found then increase array size
    If $iIndex = 0 Then
        $aGLVEx_Data[0][0] += 1
        ReDim $aGLVEx_Data[$aGLVEx_Data[0][0] + 1][7]
        $iIndex = $aGLVEx_Data[0][0]
    EndIf

    ; Store ListView handle and ControlID
    If IsHWnd($hLV) Then
        $aGLVEx_Data[$iIndex][0] = $hLV
        $aGLVEx_Data[$iIndex][1] = 0
    Else
        $aGLVEx_Data[$iIndex][0] = GUICtrlGetHandle($hLV)
        $aGLVEx_Data[$iIndex][1] = $hLV
    EndIf

    ; Create a shadow array if needed
    If $aArray = "" Then
        Local $iCols = _GUICtrlListView_GetColumnCount($aGLVEx_Data[$iIndex][0])
        Switch $iCols
            Case 1
                Local $aReplacement[1] = [0]
            Case Else
                Local $aReplacement[1][$iCols] = [[0]]
        EndSwitch
        $aArray = $aReplacement
    Else
        ; Add count element to shadow array if required
        If $iStart = 0 Then _GUIListViewEx_Array_Insert($aArray, 0, UBound($aArray))
    EndIf
    ; Store array
    $aGLVEx_Data[$iIndex][2] = $aArray

    ; Store [0] = count data
    $aGLVEx_Data[$iIndex][3] = $iStart
    ; If sortable, store sort array
    If $fSort Then
        Local $aLVSortState[_GUICtrlListView_GetColumnCount($hLV)]
        $aGLVEx_Data[$iIndex][4] = $aLVSortState
    Else
        $aGLVEx_Data[$iIndex][4] = 0
    EndIf
    ; If image required
    If $fImage Then
        $aGLVEx_Data[$iIndex][5] = 1
    EndIf
    ;  If checkbox extended style
    If BitAnd(_GUICtrlListView_GetExtendedListViewStyle($hLV), 4) Then ; $LVS_EX_CHECKBOXES
        $aGLVEx_Data[$iIndex][6] = 1
    EndIf

    ; Set insert mark colour after conversion to BGR
    _GUICtrlListView_SetInsertMarkColor($hLV, BitOR(BitShift(BitAND($iColour, 0x000000FF), -16), BitAND($iColour, 0x0000FF00), BitShift(BitAND($iColour, 0x00FF0000), 16)))

    ; If only 1 current ListView then activate
    Local $iListView_Count = 0
    For $i = 1 To $iIndex
        If $aGLVEx_Data[$i][0] Then $iListView_Count += 1
    Next
    If $iListView_Count = 1 Then _GUIListViewEx_SetActive($iIndex)

    ; Return ListView index
    Return $iIndex

EndFunc   ;==>_GUIListViewEx_Init

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Close
; Description ...: Disables all UDF functions for the specified ListView and clears all memory used
; Syntax.........: _GUIListViewEx_Close($iIndex)
; Parameters ....: $iIndex - Index number of ListView to close as returned by _GUIListViewEx_Init
;                            0 (default) = Closes all ListViews
; Requirement(s).: v3.3 +
; Return values .: Success: 1
;                  Failure: 0 and @error set to 1 - Invalid index number
; Author ........: Melba23
; Modified ......:
; Remarks .......:
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Close($iIndex = 0)

    ; Check valid index
    If $iIndex < 0 Or $iIndex > $aGLVEx_Data[0][0] Then Return SetError(1, 0, 0)

    If $iIndex = 0 Then
        ; Remove all ListView data
        Global $aGLVEx_Data[1][7] = [[0, 0]]
    Else
        ; Reset all data for ListView
        For $i = 0 To 6
            $aGLVEx_Data[$iIndex][$i] = 0
        Next

        ; Cancel active index if set to this ListView
        If $aGLVEx_Data[0][1] = $iIndex Then $aGLVEx_Data[0][1] = 0
    EndIf

    Return 1

EndFunc   ;==>_GUIListViewEx_Close

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_SetActive
; Description ...: Set specified ListView as active for UDF functions
; Syntax.........: _GUIListViewEx_SetActive($iIndex)
; Parameters ....: $iIndex - Index number of ListView as returned by _GUIListViewEx_Init
;                  An index of 0 clears any current setting
; Requirement(s).: v3.3 +
; Return values .: Success: Returns previous active index number, 0 = no previously active ListView
;                  Failure: -1 and @error set to 1 - Invalid index number
; Author ........: Melba23
; Modified ......:
; Remarks .......: ListViews can also be activated by clicking on them
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_SetActive($iIndex)

    ; Check valid index
    If $iIndex < 0 Or $iIndex > $aGLVEx_Data[0][0] Then Return SetError(1, 0, -1)

    Local $iCurr_Index = $aGLVEx_Data[0][1]

    If $iIndex Then
        ; Store index of specified ListView
        $aGLVEx_Data[0][1] = $iIndex
        ; Set values for specified ListView
        $hGLVEx_Handle = $aGLVEx_Data[$iIndex][0]
        $hGLVEx_CID = $aGLVEx_Data[$iIndex][1]
    Else
        ; Clear active index
        $aGLVEx_Data[0][1] = 0
    EndIf

    Return $iCurr_Index

EndFunc

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_GetActive
; Description ...: Get index number of ListView active for UDF functions
; Syntax.........: _GUIListViewEx_GetActive()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: Success: Index number as returned by _GUIListViewEx_Init, 0 = no active ListView
; Author ........: Melba23
; Modified ......:
; Remarks .......:
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_GetActive()

    Return $aGLVEx_Data[0][1]

EndFunc

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Return_Array
; Description ...: Returns an array reflecting the current state of the ListView
; Syntax.........: _GUIListViewEx_Return_Array($iIndex)
; Parameters ....: $iIndex - Index number of ListView as returned by _GUIListViewEx_Init
;                  $iCheck - If non-zero then the state of the checkboxes is returned (Default = 0)
; Requirement(s).: v3.3 +
; Return values .: Success: Array of current ListView - presence of count in [0] element determined by _GUIListViewEx_Init
;                  Failure: Empty array returns null string and sets @error as follows:
;                           1 = Invalid index number
;                           2 = Empty array (no items in ListView)
;                           3 = $iCheck set to True but ListView does not have checkbox style
; Author ........: Melba23
; Modified ......:
; Remarks .......: The $iStart parameter from GUIListViewEx_Init determines whether the [0] element is a count
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Return_Array($iIndex, $iCheck = 0)

    ; Check valid index
    If $iIndex < 1 Or $iIndex > $aGLVEx_Data[0][0] Then Return SetError(1, 0, "")

    ; Copy current array
    Local $aRetArray = $aGLVEx_Data[$iIndex][2]

    ; Check if checkbox array
    If $iCheck Then
        If $aGLVEx_Data[$iIndex][6] Then
            Local $aCheck_Array[UBound($aRetArray)]
            For $i = 1 To UBound($aRetArray) - 1
                $aCheck_Array[$i] = _GUICtrlListView_GetItemChecked($aGLVEx_Data[$iIndex][0], $i - 1)
            Next
            ; Remove count element if required
            If $aGLVEx_Data[$iIndex][3] = 0 Then
                ; Check at least one entry in 1D/2D array
                Switch UBound($aRetArray, 0)
                    Case 1
                        If $aRetArray[0] = 0 Then Return SetError(2, 0, "")
                    Case 2
                        If $aRetArray[0][0] = 0 Then Return SetError(2, 0, "")
                EndSwitch
                ; Delete count element
                _GUIListViewEx_Array_Delete($aCheck_Array, 0)
            EndIf
            Return $aCheck_Array
        Else
            Return SetError(3, 0, "")
        EndIf
    EndIf

    ; Remove count element of array if required
    If $aGLVEx_Data[$iIndex][3] = 0 Then
        ; Check at least one entry in 1D/2D array
        Switch UBound($aRetArray, 0)
            Case 1
                If $aRetArray[0] = 0 Then Return SetError(2, 0, "")
            Case 2
                If $aRetArray[0][0] = 0 Then Return SetError(2, 0, "")
        EndSwitch
        ; Delete count element
        _GUIListViewEx_Array_Delete($aRetArray, 0)
    EndIf

    ; Return array
    Return $aRetArray

EndFunc   ;==>_GUIListViewEx_Return_Array

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Insert
; Description ...: Inserts data just below selected item in active ListView
;                  If no selection, data added at end
; Syntax.........: _GUIListViewEx_Insert($vData)
; Parameters ....: $vData - Data to insert, can be in array or delimited string format
; Requirement(s).: v3.3 +
; Return values .: Success: Array of current ListView with count in [0] element
;                  Failure: If no ListView active then returns "" and sets @error to 1
; Author ........: Melba23
; Modified ......:
; Remarks .......: - New data is inserted after the selected item.  If no item is selected then the datat is added at
;                  the end of the ListView.  If multiple items are selected, the data is inserted after the first
;                  - $vData can be passed in string or array format - it is automatically transformed if required
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Insert($vData)

    Local $vInsert

    ; Set data for active ListView
    Local $iArray_Index = $aGLVEx_Data[0][1]
    ; If no ListView active then return
    If $iArray_Index = 0 Then Return SetError(1, 0, "")

    ; Load active ListView details
    $hGLVEx_Handle = $aGLVEx_Data[$iArray_Index][0]
    $hGLVEx_CID = $aGLVEx_Data[$iArray_Index][1]

    ; Get selected item in ListView
    Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
    Local $iInsert_Index = $iIndex
    ; If no selection
    If $iIndex = "" Then $iInsert_Index = -1
    ; Check for multiple selections
    If StringInStr($iIndex, "|") Then
        Local $aIndex = StringSplit($iIndex, "|")
        ; Use first selection
        $iIndex = $aIndex[1]
        ; Cancel all other selections
        For $i = 2 To $aIndex[0]
            _GUICtrlListView_SetItemSelected($hGLVEx_Handle, $aIndex[$i], False)
        Next
    EndIf

    ; Copy array for manipulation
    $aGLVEx_Array = $aGLVEx_Data[$iArray_Index][2]

    ; Create Local array for checkboxes if required
    If $aGLVEx_Data[$iArray_Index][6] Then
        Local $aCheck_Array[UBound($aGLVEx_Array)]
        For $i = 1 To UBound($aCheck_Array) - 1
            $aCheck_Array[$i] = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $i - 1)
        Next
    EndIf

    ; Check if 1D/2D array
    Switch UBound($aGLVEx_Array, 0)
        Case 1
            ; If empty array insert at 0
            If $aGLVEx_Array[0] = 0 Then $iInsert_Index = 0
            ; Get data into string format for insert
            If IsArray($vData) Then
                $vInsert = ""
                For $i = 0 To UBound($vData) - 1
                    $vInsert &= $vData[$i] & "|"
                Next
                $vInsert = StringTrimRight($vInsert, 1)
            Else
                $vInsert = $vData
            EndIf
            ; Increase count
            $aGLVEx_Array[0] += 1
        Case 2
            ; If empty array insert at 0
            If $aGLVEx_Array[0][0] = 0 Then $iInsert_Index = 0
            ; Get data into array format for insert
            If IsArray($vData) Then
                $vInsert = $vData
            Else
                Local $aData = StringSplit($vData, "|")
                Switch $aData[0]
                    Case 1
                        $vInsert = $aData[1]
                    Case Else
                        Local $vInsert[$aData[0]]
                        For $i = 0 To $aData[0] - 1
                            $vInsert[$i] = $aData[$i + 1]
                        Next
                EndSwitch
            EndIf
            ; Increase count
            $aGLVEx_Array[0][0] += 1
    EndSwitch

    ; Insert data into array
    If $iIndex = "" Then
        _GUIListViewEx_Array_Add($aGLVEx_Array, $vInsert)
    Else
        _GUIListViewEx_Array_Insert($aGLVEx_Array, $iInsert_Index + 2, $vInsert)
        If $aGLVEx_Data[$iArray_Index][6] Then
            _GUIListViewEx_Array_Insert($aCheck_Array, $iInsert_Index + 2, False)
            ; Reset all checkboxes
            For $i = 1 To UBound($aCheck_Array) - 1
                _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $i - 1, $aCheck_Array[$i])
            Next
        EndIf
    EndIf

    ; Check if Native or UDF
    If $hGLVEx_CID Then
        ; Add new item at ListView end
        If IsArray($vInsert) Then
            If IsArray($vData) Then
                $vInsert = ""
                For $i = 0 To UBound($vData) - 1
                    $vInsert &= $vData[$i] & "|"
                Next
                $vInsert = StringTrimRight($vInsert, 1)
                GUICtrlCreateListViewItem($vInsert, $hGLVEx_CID)
            Else
                GUICtrlCreateListViewItem($vData, $hGLVEx_CID)
            EndIf
        Else
            GUICtrlCreateListViewItem($vInsert, $hGLVEx_CID)
        EndIf
    Else
        ; Add new item at ListView end
        Local $iNewItem
        If IsArray($vInsert) Then
            $iNewItem = _GUICtrlListView_AddItem($hGLVEx_Handle, $vInsert[0])
            ; Add new subitems
            For $i = 1 To UBound($vInsert) - 1
                _GUICtrlListView_AddSubItem($hGLVEx_Handle, $iNewItem, $vInsert[$i], $i)
            Next
        Else
            $iNewItem = _GUICtrlListView_AddItem($hGLVEx_Handle, $vInsert)
        EndIf
    EndIf
    ; Check where item was to be inserted
    If $iIndex = "" Then
        _GUIListViewEx_Data_Change($iInsert_Index, $iInsert_Index)
        ; No moves required so set highlight
        _GUIListViewEx_Highlight(_GUICtrlListView_GetItemCount($hGLVEx_Handle) - 1)
    Else
        ; Reset item contents below insert position
        _GUIListViewEx_Data_Change($iInsert_Index, _GUICtrlListView_GetItemCount($hGLVEx_Handle) - 1)
        ; Set highlight
        _GUIListViewEx_Highlight($iInsert_Index + 1, $iInsert_Index)
    EndIf

    ; Store amended array
    $aGLVEx_Data[$iArray_Index][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0
    ; Return amended array
    Return _GUIListViewEx_Return_Array($iArray_Index)

EndFunc   ;==>_GUIListViewEx_Insert

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Delete
; Description ...: Deletes selected item in active ListView
; Syntax.........: _GUIListViewEx_Delete()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: Success: Array of active ListView with count in [0] element
;                  Failure: Returns "" and sets @error as follows:
;                      1 = No ListView active
;                      2 = No item selected
;                      3 = No items to delete
; Author ........: Melba23
; Modified ......:
; Remarks .......: If multiple items are selected, all are deleted
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Delete()

    ; Set data for active ListView
    Local $iArray_Index = $aGLVEx_Data[0][1]
    ; If no ListView active then return
    If $iArray_Index = 0 Then Return SetError(1, 0, "")

    ; Load active ListView details
    $hGLVEx_Handle = $aGLVEx_Data[$iArray_Index][0]
    $hGLVEx_CID = $aGLVEx_Data[$iArray_Index][1]

    ; Check for selected items
    Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
    If $iIndex = "" Then Return SetError(2, 0, "")

    ; Copy array for manipulation
    $aGLVEx_Array = $aGLVEx_Data[$iArray_Index][2]

    ; Determine final item
    Local $iLast = UBound($aGLVEx_Array) - 2

    ; Check if item is part of a multiple selection
    If StringInStr($iIndex, "|") Then
        ; Extract all selected items
        Local $aIndex = StringSplit($iIndex, "|")
        For $i = 1 To $aIndex[0]
            ; Remove highlighting from items
            _GUICtrlListView_SetItemSelected($hGLVEx_Handle, $i, False)
        Next

        ; Check if 1D/2D array
        Switch UBound($aGLVEx_Array, 0)
            Case 1
                ; Decrease count
                $aGLVEx_Array[0] -= $aIndex[0]
            Case 2
                ; Decrease count
                $aGLVEx_Array[0][0] -= $aIndex[0]
        EndSwitch

        ; Delete elements from array - start from bottom
        For $i = $aIndex[0] To 1 Step -1
            _GUIListViewEx_Array_Delete($aGLVEx_Array, $aIndex[$i] + 1)
        Next

        ; Delete items from ListView - again start from bottom
        For $i = $aIndex[0] To 1 Step -1
            _GUICtrlListView_DeleteItem($hGLVEx_Handle, $aIndex[$i])
        Next

    Else
        ; Check if 1D/2D array
        Switch UBound($aGLVEx_Array, 0)
            Case 1
                ; Decrease count
                $aGLVEx_Array[0] -= 1
            Case 2
                ; Decrease count
                $aGLVEx_Array[0][0] -= 1
        EndSwitch
        ; Delete element from array
        _GUIListViewEx_Array_Delete($aGLVEx_Array, $iIndex + 1)

        ; Delete item from ListView
        _GUICtrlListView_DeleteItem($hGLVEx_Handle, $iIndex)
        ; Set highlight - up one if bottom deleted
        If $iIndex = $iLast Then
            _GUIListViewEx_Highlight($iIndex - 1)
        Else
            _GUIListViewEx_Highlight($iIndex)
        EndIf
    EndIf

    ; Store amended array
    $aGLVEx_Data[$iArray_Index][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0
    ; Return amended array
    Return _GUIListViewEx_Return_Array($iArray_Index)

EndFunc   ;==>_GUIListViewEx_Delete

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Up
; Description ...: Moves selected item in active ListView up 1 place
; Syntax.........: _GUIListViewEx_Up()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: Success: Array of active ListView with count in [0] element
;                  Failure: Returns "" and sets @error as follows:
;                      1 = No ListView active
;                      2 = No item selected
;                      3 = Item already at top
; Author ........: Melba23
; Modified ......:
; Remarks .......: If multiple items are selected, only the top consecutive block is moved
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Up()

    Local $iGLVExMove_Index, $iGLVEx_Moving = 0

    ; Set data for active ListView
    Local $iArray_Index = $aGLVEx_Data[0][1]
    ; If no ListView active then return
    If $iArray_Index = 0 Then Return SetError(1, 0, 0)

    ; Load active ListView details
    $hGLVEx_Handle = $aGLVEx_Data[$iArray_Index][0]
    $hGLVEx_CID = $aGLVEx_Data[$iArray_Index][1]

    ; Check for selected items
    Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
    Local $aIndex = StringSplit($iIndex, "|")
    $iGLVExMove_Index = $aIndex[1]
    ; Check if item is part of a multiple selection
    If $aIndex[0] > 1 Then
        ; Check for consecutive items
        For $i = 1 To $aIndex[0] - 1
            If $aIndex[$i + 1] = $aIndex[1] + $i Then
                $iGLVEx_Moving += 1
            Else
                ExitLoop
            EndIf
        Next
    Else
        $iGLVExMove_Index = $aIndex[1]
    EndIf

    ; Remove all highlighting
    _GUICtrlListView_SetItemSelected($hGLVEx_Handle, -1, False)

    ; Check not top item
    If $iGLVExMove_Index = "0" Then Return SetError(3, 0, "")

    ; Copy array for manipulation
    $aGLVEx_Array = $aGLVEx_Data[$iArray_Index][2]

    ; Move consecutive items
    For $iIndex = $iGLVExMove_Index To $iGLVExMove_Index + $iGLVEx_Moving

        ; Swap array elements
        _GUIListViewEx_Array_Swap($aGLVEx_Array, $iIndex, $iIndex + 1)

        ; Swap checkboxes if required
        If $aGLVEx_Data[$iArray_Index][6] Then
            Local $fTemp = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iIndex)
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $iIndex, _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iIndex - 1))
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $iIndex - 1, $fTemp)
        EndIf

        ; Change data in affected items
        _GUIListViewEx_Data_Change($iIndex - 1, $iIndex);, $aGLVEx_Array)
        ; Set highlight and cancel existing one (needed for multiple selection ListViews)
        _GUIListViewEx_Highlight($iIndex - 1, $iIndex)
    Next

    ; Store amended array
    $aGLVEx_Data[$iArray_Index][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0
    ; Return amended array
    Return _GUIListViewEx_Return_Array($iArray_Index)

EndFunc   ;==>_GUIListViewEx_Up

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Down
; Description ...: Moves selected item in active ListView down 1 place
; Syntax.........: _GUIListViewEx_Down()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: Success: Array of active ListView with count in [0] element
;                  Failure: Returns "" and sets @error as follows:
;                      1 = No ListView active
;                      2 = No item selected
;                      3 = Item already at bottom
; Author ........: Melba23
; Modified ......:
; Remarks .......: If multiple items are selected, only the bottom consecutive block is moved
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Down()

    Local $iGLVExMove_Index, $iGLVEx_Moving = 0

    ; Set data for active ListView
    Local $iArray_Index = $aGLVEx_Data[0][1]
    ; If no ListView active then return
    If $iArray_Index = 0 Then Return SetError(1, 0, 0)

    ; Load active ListView details
    $hGLVEx_Handle = $aGLVEx_Data[$iArray_Index][0]
    $hGLVEx_CID = $aGLVEx_Data[$iArray_Index][1]

    ; Check for selected items
    Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
    Local $aIndex = StringSplit($iIndex, "|")
    ; Check if item is part of a multiple selection
    If $aIndex[0] > 1 Then
        $iGLVExMove_Index = $aIndex[$aIndex[0]]
        ; Check for consecutive items
        For $i = 1 To $aIndex[0] - 1
            If $aIndex[$aIndex[0] - $i] = $aIndex[$aIndex[0]] - $i Then
                $iGLVEx_Moving += 1
            Else
                ExitLoop
            EndIf
        Next
    Else
        $iGLVExMove_Index = $aIndex[1]
    EndIf

    ; Remove all highlighting
    _GUICtrlListView_SetItemSelected($hGLVEx_Handle, -1, False)

    ; Check not last item
    If $iGLVExMove_Index = _GUICtrlListView_GetItemCount($hGLVEx_Handle) - 1 Then
        _GUIListViewEx_Highlight($iIndex)
        Return
    EndIf

    ; Copy array for manipulation
    $aGLVEx_Array = $aGLVEx_Data[$iArray_Index][2]

    ; Move consecutive items
    For $iIndex = $iGLVExMove_Index To $iGLVExMove_Index - $iGLVEx_Moving Step -1

        ; Swap array elements
        _GUIListViewEx_Array_Swap($aGLVEx_Array, $iIndex + 1, $iIndex + 2)

        ; Swap checkboxes if required
        If $aGLVEx_Data[$iArray_Index][6] Then
            Local $fTemp = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iIndex)
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $iIndex, _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iIndex + 1))
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $iIndex + 1, $fTemp)
        EndIf

        ; Change data in affected items
        _GUIListViewEx_Data_Change($iIndex, $iIndex + 1)
        ; Set highlight and cancel existing one (needed for multiple selection ListViews)
        _GUIListViewEx_Highlight($iIndex + 1, $iIndex)

    Next

    ; Store amended array
    $aGLVEx_Data[$iArray_Index][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0
    ; Return amended array
    Return _GUIListViewEx_Return_Array($iArray_Index)

EndFunc   ;==>_GUIListViewEx_Down

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_DragRegister
; Description ...: Registers Windows messages needed for the UDF
; Syntax.........: _GUIListViewEx_DragRegister([$fNOTIFY = True, [$fMOUSEMOVE = True, [$fLBUTTONUP = True]]])
; Parameters ....: $fNOTIFY    - True = Register WM_NOTIFY message
;                  $fMOUSEMOVE - True = Register WM_MOUSEMOVE message
;                  $fLBUTTONUP - True = Register WM_LBUTTONUP message
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Modified ......:
; Remarks .......: If other handlers already registered, then call the relevant handler function from within that handler
;                  If no dragging is required, only the WM_NOTIFY handler needs to be registered
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_DragRegister($fNOTIFY = True, $fMOUSEMOVE = True, $fLBUTTONUP = True)

    ; Register required messages
    If $fNOTIFY    Then GUIRegisterMsg(0x004E, "_GUIListViewEx_WM_NOTIFY_Handler")    ; $WM_NOTIFY
    If $fMOUSEMOVE Then GUIRegisterMsg(0x0200, "_GUIListViewEx_WM_MOUSEMOVE_Handler") ; $WM_MOUSEMOVE
    If $fLBUTTONUP Then GUIRegisterMsg(0x0202, "_GUIListViewEx_WM_LBUTTONUP_Handler") ; $WM_LBUTTONUP

EndFunc   ;==>_GUIListViewEx_DragRegister

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_WM_NOTIFY_Handler
; Description ...: Windows message handler for WM_NOTIFY
; Syntax.........: _GUIListViewEx_WM_NOTIFY_Handler
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Modified ......:
; Remarks .......: If a WM_NOTIFY handler already registered, then call this function from within that handler
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_WM_NOTIFY_Handler($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam

    ; Struct = $tagNMHDR and "int Item;int SubItem" from $tagNMLISTVIEW
    Local $tStruct = DllStructCreate("hwnd;uint_ptr;int_ptr;int;int", $lParam)
    If @error Then Return

    Local $iCode = BitAND(DllStructGetData($tStruct, 3), 0xFFFFFFFF)

    Switch $iCode
        Case $LVN_COLUMNCLICK, -2 ; $NM_CLICK
            ; Check if enabled ListView
            For $i = 1 To $aGLVEx_Data[0][0]
                If DllStructGetData($tStruct, 1) = $aGLVEx_Data[$i][0] Then
                    ExitLoop
                EndIf
            Next
            If $i > $aGLVEx_Data[0][0] Then Return ; Not enabled

            ; Set values for active ListView
            $aGLVEx_Data[0][1] = $i
            $hGLVEx_Handle = $aGLVEx_Data[$i][0]
            $hGLVEx_CID = $aGLVEx_Data[$i][1]
            $aGLVEx_Array = $aGLVEx_Data[$i][2]

            ; Sort if a column header was clicked and ListView is sortable
            If $iCode = $LVN_COLUMNCLICK And IsArray($aGLVEx_Data[$i][4]) Then
                ; Load current ListView sort state array
                Local $aLVSortState = $aGLVEx_Data[$aGLVEx_Data[0][0]][4]
                ; Sort column - get column from from struct
                _GUICtrlListView_SimpleSort($hGLVEx_Handle, $aLVSortState, DllStructGetData($tStruct, 5))
                ; Store new ListView sort state array
                $aGLVEx_Data[$aGLVEx_Data[0][0]][4] = $aLVSortState
                ; Reread listview items into array
                Switch UBound($aGLVEx_Array, 0) ; Check array format
                    Case 1
                        For $j = 1 To $aGLVEx_Array[0]
                            $aGLVEx_Array[$j] = _GUICtrlListView_GetItemTextString($hGLVEx_Handle, $j - 1)
                        Next
                    Case 2
                        Local $iDim2 = UBound($aGLVEx_Array, 2) - 1
                        For $j = 1 To $aGLVEx_Array[0][0]
                            For $k = 0 To $iDim2
                                $aGLVEx_Array[$j][$k] = _GUICtrlListView_GetItemText($hGLVEx_Handle, $j - 1, $k)
                            Next
                        Next
                EndSwitch
                ; Store amended array
                $aGLVEx_Data[$i][2] = $aGLVEx_Array
            EndIf

        Case $LVN_BEGINDRAG
            ; Check if enabled ListView
            For $i = 1 To $aGLVEx_Data[0][0]
                If DllStructGetData($tStruct, 1) = $aGLVEx_Data[$i][0] Then
                    ExitLoop
                EndIf
            Next
            If $i > $aGLVEx_Data[0][0] Then Return ; Not registered

            ; Set values for this ListView
            $aGLVEx_Data[0][1] = $i
            $hGLVEx_Handle = $aGLVEx_Data[$i][0]
            $hGLVEx_CID = $aGLVEx_Data[$i][1]
            Local $fImage = $aGLVEx_Data[$i][5]
            Local $fCheck = $aGLVEx_Data[$i][6]
            ; Copy array for manipulation
            $aGLVEx_Array = $aGLVEx_Data[$i][2]

            ; Check if Native or UDF and set focus
            If $hGLVEx_CID Then
                GUICtrlSetState($hGLVEx_CID, 256) ; $GUI_FOCUS
            Else
                _WinAPI_SetFocus($hGLVEx_Handle)
            EndIf

            ; Get dragged item index
            $iGLVExDragged_Index = DllStructGetData($tStruct, 4) ; Item
            ; Set dragged item count
            $iGLVEx_Dragging = 1

            ; Check for selected items
            Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
            ; Check if item is part of a multiple selection
            If StringInStr($iIndex, $iGLVExDragged_Index) And StringInStr($iIndex, "|") Then
                ; Extract all selected items
                Local $aIndex = StringSplit($iIndex, "|")
                For $i = 1 To $aIndex[0]
                    If $aIndex[$i] = $iGLVExDragged_Index Then ExitLoop
                Next
                ; Now check for consecutive items
                If $i <> 1 Then ; Up
                    For $j = $i - 1 To 1 Step -1
                        ; Consecutive?
                        If $aIndex[$j] <> $aIndex[$j + 1] - 1 Then ExitLoop
                        ; Adjust dragged index to this item
                        $iGLVExDragged_Index -= 1
                        ; Increase number to drag
                        $iGLVEx_Dragging += 1
                    Next
                EndIf
                If $i <> $aIndex[0] Then ; Down
                    For $j = $i + 1 To $aIndex[0]
                        ; Consecutive
                        If $aIndex[$j] <> $aIndex[$j - 1] + 1 Then ExitLoop
                        ; Increase number to drag
                        $iGLVEx_Dragging += 1
                    Next
                EndIf
            Else ; Either no selection or only a single
                ; Set flag
                $iGLVEx_Dragging = 1
            EndIf

            ; Remove all highlighting
            _GUICtrlListView_SetItemSelected($hGLVEx_Handle, -1, False)

            ; Create drag image
            If $fImage Then
                Local $aImageData = _GUICtrlListView_CreateDragImage($hGLVEx_Handle, $iGLVExDragged_Index)
                $hGLVExDragged_Image = $aImageData[0]
                _GUIImageList_BeginDrag($hGLVExDragged_Image, 0, 0, 0)
            EndIf

            ; Create Global array for checkboxes if required
            If $fCheck Then
                Global $aGLVExDragCheck_Array[UBound($aGLVEx_Array)]
                For $i = 1 To UBound($aGLVExDragCheck_Array) - 1
                    $aGLVExDragCheck_Array[$i] = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $i - 1)
                Next
            EndIf

    EndSwitch

EndFunc   ;==>_GUIListViewEx_WM_NOTIFY_Handler

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_WM_MOUSEMOVE_Handler
; Description ...: Windows message handler for WM_NOTIFY
; Syntax.........: _GUIListViewEx_WM_MOUSEMOVE_Handler
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Modified ......:
; Remarks .......: If a WM_MOUSEMOVE handler already registered, then call this function from within that handler
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_WM_MOUSEMOVE_Handler($hWnd, $iMsg, $wParam, $lParam)

    #forceref $iMsg, $wParam

    If Not $iGLVEx_Dragging Then Return "GUI_RUNDEFMSG"

    Local $aLV_Pos, $tLVHITTESTINFO, $iCurr_Index

    ; Get current mouse Y coord
    Local $iCurr_Y = BitShift($lParam, 16)

    ; Set insert mark to correct side of items depending on sense of movement when cursor within range
    If $iGLVExInsert_Index <> -1 Then
        If $iGLVExLast_Y = $iCurr_Y Then
            Return "GUI_RUNDEFMSG"
        ElseIf $iGLVExLast_Y > $iCurr_Y Then
            $fGLVEx_Bar_Under = False
            _GUICtrlListView_SetInsertMark($hGLVEx_Handle, $iGLVExInsert_Index, False)
        Else
            $fGLVEx_Bar_Under = True
            _GUICtrlListView_SetInsertMark($hGLVEx_Handle, $iGLVExInsert_Index, True)
        EndIf
    EndIf
    ; Store current Y coord
    $iGLVExLast_Y = $iCurr_Y

    ; Get ListView item under mouse - depends on ListView type
    If $hGLVEx_CID Then
        $aLV_Pos = ControlGetPos($hWnd, "", $hGLVEx_CID)
        $tLVHITTESTINFO = DllStructCreate("int;int;uint;int;int;int")
        ; Force response even if off side of GUI - normal X coord = BitAND($lParam, 0xFFFF) - $aLV_Pos[0]
        DllStructSetData($tLVHITTESTINFO, 1, 1)
        DllStructSetData($tLVHITTESTINFO, 2, $iCurr_Y - $aLV_Pos[1])
        ; Get item under mouse
        $iCurr_Index = GUICtrlSendMsg($hGLVEx_CID, $LVM_HITTEST, 0, DllStructGetPtr($tLVHITTESTINFO))
    Else
        ; Get coords of client area
        Local $tPoint = DllStructCreate("int X;int Y")
        DllStructSetData($tPoint, "X", 0)
        DllStructSetData($tPoint, "Y", 0)
        Local $pPoint = DllStructGetPtr($tPoint)
        DllCall("user32.dll", "bool", "ClientToScreen", "hwnd", $hWnd, "ptr", $pPoint)
        ; Get coords of ListView
        $aLV_Pos = WinGetPos($hGLVEx_Handle)
        Local $iY = $iCurr_Y - $aLV_Pos[1] + DllStructGetData($tPoint, "Y")
        $tLVHITTESTINFO = DllStructCreate("int;int;uint;int;int;int")
        ; Force response even if off side of GUI - normal X coord = BitAND($lParam, 0xFFFF) - $aLV_Pos[0] + DllStructGetData($tPoint, "X")
        DllStructSetData($tLVHITTESTINFO, 1, 1)
        DllStructSetData($tLVHITTESTINFO, 2, $iY)
        Local $pLVHITTESTINFO = DllStructGetPtr($tLVHITTESTINFO)
        ; Get item under mouse
        Local $aRet = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hGLVEx_Handle, "uint", $LVM_HITTEST, "wparam", 0, "lparam", $pLVHITTESTINFO)
        $iCurr_Index = $aRet[0]
    EndIf

    ; If mouse is above or below ListView then scroll ListView
    If $iCurr_Index = -1 Then
        If $fGLVEx_Bar_Under Then
            _GUICtrlListView_Scroll($hGLVEx_Handle, 0, 10)
        Else
            _GUICtrlListView_Scroll($hGLVEx_Handle, 0, -10)
        EndIf
        Sleep(100)
    EndIf

    ; Check if over same item
    If $iGLVExInsert_Index = $iCurr_Index Then Return "GUI_RUNDEFMSG"

    ; Show insert mark on current item
    _GUICtrlListView_SetInsertMark($hGLVEx_Handle, $iCurr_Index, $fGLVEx_Bar_Under)
    ; Store current item
    $iGLVExInsert_Index = $iCurr_Index

EndFunc   ;==>_GUIListViewEx_WM_MOUSEMOVE_Handler

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_WM_LBUTTONUP_Handler
; Description ...: Windows message handler for WM_NOTIFY
; Syntax.........: _GUIListViewEx_WM_LBUTTONUP_Handler
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Modified ......:
; Remarks .......: If a WM_LBUTTONUP handler already registered, then call this function from within that handler
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_WM_LBUTTONUP_Handler($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam, $lParam

    If Not $iGLVEx_Dragging Then Return "GUI_RUNDEFMSG"

    ; Get item count
    Local $iMultipleItems = $iGLVEx_Dragging - 1

    ; Reset flag
    $iGLVEx_Dragging = 0

    ; Check mouse within ListView
    If $iGLVExInsert_Index = -1 Then
        ; Clear insert mark
        _GUICtrlListView_SetInsertMark($hGLVEx_Handle, -1, True)
        ; Reset highlight to original items
        For $i = 0 To $iMultipleItems
            _GUIListViewEx_HighLight($iGLVExDragged_Index + $i)
        Next
        Return
    EndIf

    ; Determine position to insert
    If $fGLVEx_Bar_Under Then
        If $iGLVExDragged_Index > $iGLVExInsert_Index Then $iGLVExInsert_Index += 1
    Else
        If $iGLVExDragged_Index < $iGLVExInsert_Index Then $iGLVExInsert_Index -= 1
    EndIf

    ; Clear insert mark
    _GUICtrlListView_SetInsertMark($hGLVEx_Handle, -1, True)

    ; Clear drag image
    If $hGLVExDragged_Image Then
        _GUIImageList_DragLeave($hGLVEx_Handle)
        _GUIImageList_EndDrag()
        _GUIImageList_Destroy($hGLVExDragged_Image)
        $hGLVExDragged_Image = 0
    EndIf

    ; Check not dropping on dragged item(s)
    Switch $iGLVExInsert_Index
        Case $iGLVExDragged_Index To $iGLVExDragged_Index + $iMultipleItems
            ; Reset highlight to original items
            For $i = 0 To $iMultipleItems
                _GUIListViewEx_HighLight($iGLVExDragged_Index + $i)
            Next
            Return
    EndSwitch

    ; Amend array
    ; Get data from dragged element(s)
    If $iMultipleItems Then
        ; Multiple dragged elements
        Switch UBound($aGLVEx_Array, 0) ; Check array format
            Case 1
                Local $aInsertData[$iMultipleItems + 1]
                For $i = 0 To $iMultipleItems
                    $aInsertData[$i] = $aGLVEx_Array[$iGLVExDragged_Index + 1 + $i]
                Next
            Case 2
                Local $aInsertData[$iMultipleItems + 1]
                For $i = 0 To $iMultipleItems
                    Local $aItemData[UBound($aGLVEx_Array, 2)]
                    For $j = 0 To UBound($aGLVEx_Array, 2) - 1
                        $aItemData[$j] = $aGLVEx_Array[$iGLVExDragged_Index + 1][$j]
                    Next
                    $aInsertData[$i] = $aItemData
                Next
        EndSwitch
    Else
        ; Single dragged element
        Switch UBound($aGLVEx_Array, 0) ; Check array format
            Case 1
                Local $aInsertData[1]
                $aInsertData[0] = $aGLVEx_Array[$iGLVExDragged_Index + 1]
            Case 2
                Local $aInsertData[1]
                Local $aItemData[UBound($aGLVEx_Array, 2)]
                For $i = 0 To UBound($aGLVEx_Array, 2) - 1
                    $aItemData[$i] = $aGLVEx_Array[$iGLVExDragged_Index + 1][$i]
                Next
                $aInsertData[0] = $aItemData
        EndSwitch
    EndIf

    ; Copy checkbox data from dragged elements
    If IsArray($aGLVExDragCheck_Array) Then
        If $iMultipleItems Then
            Local $aDragged_Data[$iMultipleItems + 1]
            For $i = 0 To $iMultipleItems
                $aDragged_Data[$i] = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iGLVExDragged_Index + $i)
            Next
        Else
            Local $aDragged_Data[1]
            $aDragged_Data[0] = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iGLVExDragged_Index)
        EndIf
    EndIf

    ; Delete dragged element(s) from arrays
    For $i = 0 To $iMultipleItems
        _GUIListViewEx_Array_Delete($aGLVEx_Array, $iGLVExDragged_Index + 1)
        If IsArray($aGLVExDragCheck_Array) Then
            _GUIListViewEx_Array_Delete($aGLVExDragCheck_Array, $iGLVExDragged_Index + 1)
        EndIf
    Next

    ; Amend insert positon for multiple items deleted above
    If $iGLVExDragged_Index < $iGLVExInsert_Index Then
        $iGLVExInsert_Index -= $iMultipleItems
    EndIf
    ; Re-insert dragged element(s) into array
    For $i = $iMultipleItems To 0 Step -1
        _GUIListViewEx_Array_Insert($aGLVEx_Array, $iGLVExInsert_Index + 1, $aInsertData[$i])
        If IsArray($aGLVExDragCheck_Array) Then
            _GUIListViewEx_Array_Insert($aGLVExDragCheck_Array, $iGLVExInsert_Index + 1, $aDragged_Data[$i])
        EndIf
    Next

    ; Amend ListView to match array
    If $iGLVExDragged_Index > $iGLVExInsert_Index Then
        _GUIListViewEx_Data_Change($iGLVExInsert_Index, $iGLVExDragged_Index + $iMultipleItems)
    Else
        _GUIListViewEx_Data_Change($iGLVExDragged_Index, $iGLVExInsert_Index + $iMultipleItems)
    EndIf

    ; Reset checkbox data
    If IsArray($aGLVExDragCheck_Array) Then
        For $i = 1 To UBound($aGLVExDragCheck_Array) - 1
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $i - 1, $aGLVExDragCheck_Array[$i])
        Next
        ; Clear array
        $aGLVExDragCheck_Array = 0
    EndIf

    ; Set highlight to inserted item(s)
    For $i = 0 To $iMultipleItems
        _GUIListViewEx_HighLight($iGLVExInsert_Index + $i)
    Next

    ; Store amended array
    $aGLVEx_Data[$aGLVEx_Data[0][1]][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0

EndFunc   ;==>_GUIListViewEx_WM_LBUTTONUP_Handler

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_HighLight($iIndexA, $iIndexB)
; Description ...: Highlights first item and ensures visible while removing hightlight from second in multiple selection ListViews
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================
Func _GUIListViewEx_Highlight($iIndexA, $iIndexB = -1)

    ; Check if Native or UDF and set focus
    If $hGLVEx_CID Then
        GUICtrlSetState($hGLVEx_CID, 256) ; $GUI_FOCUS
    Else
        _WinAPI_SetFocus($hGLVEx_Handle)
    EndIf
    ; Cancel highlight on other item - needed for multisel listviews
    If $iIndexB <> -1 Then _GUICtrlListView_SetItemSelected($hGLVEx_Handle, $iIndexB, False)
    ; Set highlight to inserted item and ensure in view
    _GUICtrlListView_SetItemState($hGLVEx_Handle, $iIndexA, $LVIS_SELECTED, $LVIS_SELECTED)
    _GUICtrlListView_EnsureVisible($hGLVEx_Handle, $iIndexA)

EndFunc   ;==>_GUIListViewEx_HighLight

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Data_Change($iStart, $iEnd)
; Description ...: Resets ListView items within a defined range to the current values in the stored array
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================
Func _GUIListViewEx_Data_Change($iStart, $iEnd)

    Local $sBlanker, $aInsert, $iDim2

    ; Check if Native or UDF
    If $hGLVEx_CID Then
        ; Native ListView
        For $i = $iStart To $iEnd
            ; Get CID of the item
            Local $iCID = _GUICtrlListView_GetItemParam($hGLVEx_Handle, $i)
            ; Check array type
            Switch UBound($aGLVEx_Array, 0)
                Case 1
                    $aInsert = StringSplit($aGLVEx_Array[$i + 1], "|", 2)
                Case 2
                    $iDim2 = UBound($aGLVEx_Array, 2)
                    Local $aInsert[$iDim2]
                    For $j = 0 To $iDim2 - 1
                        $aInsert[$j] = $aGLVEx_Array[$i + 1][$j]
                    Next
            EndSwitch
            ; Insert new data into each column in turn
            $sBlanker = ""
            For $j = 0 To UBound($aInsert) - 1
                GUICtrlSetData($iCID, $sBlanker & $aInsert[$j])
                $sBlanker &= "|"
            Next
        Next
    Else
        ; UDF ListView
        For $i = $iStart To $iEnd
            ; Check if multicolumn
            $iDim2 = UBound($aGLVEx_Array, 2)
            If @error Then
                _GUICtrlListView_SetItemText($hGLVEx_Handle, $i, $aGLVEx_Array[$i + 1])
            Else
                ; For each column - or just once if not multicolumn
                For $j = 0 To $iDim2 - 1
                    ; Set data
                    _GUICtrlListView_SetItemText($hGLVEx_Handle, $i, $aGLVEx_Array[$i + 1][$j], $j)
                Next
            EndIf
        Next
    EndIf

EndFunc   ;==>_GUIListViewEx_Data_Change

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Array_Add
; Description ...: Adds a specified value at the end of an existing 1D or 2D array.
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================
Func _GUIListViewEx_Array_Add(ByRef $avArray, $vAdd = "", $iStart = 0)

    ; Get size of the Array to modify
    Local $iIndex_Max = UBound($avArray)

    ; Get type of array
    Switch UBound($avArray, 0)
        Case 1

            ReDim $avArray[$iIndex_Max + 1]
            $avArray[$iIndex_Max] = $vAdd

        Case 2

        ; Get size of second dimension
        Local $iDim2 = UBound($avArray, 2)

        ; Redim the Array
        ReDim $avArray[$iIndex_Max + 1][$iDim2]

        ; Add new elements
        If IsArray($vAdd) Then
            ; Get size of Insert array
            Local $vAdd_Max = UBound($vAdd)
            For $j = 0 To $iDim2 - 1
                ; If Insert array is too small to fill Array then continue with blanks
                If $j > $vAdd_Max - 1 - $iStart Then
                    $avArray[$iIndex_Max][$j] = ""
                Else
                    $avArray[$iIndex_Max][$j] = $vAdd[$j + $iStart]
                EndIf
            Next
        Else
            ; Fill Array with variable
            For $j = 0 To $iDim2 - 1
                $avArray[$iIndex_Max][$j] = $vAdd
            Next
        EndIf

    EndSwitch

    Return $iIndex_Max

EndFunc   ;==>_GUIListViewEx_Array_Add

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Array_Insert
; Description ...: Adds a value at the specified index of a 1D or 2D array.
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================

Func _GUIListViewEx_Array_Insert(ByRef $avArray, $iIndex, $vInsert)

    ; Get size of the Array to modify
    Local $iIndex_Max = UBound($avArray)

    ; Get type of array
    Switch UBound($avArray, 0)
        Case 1

            ; Resize array
            ReDim $avArray[$iIndex_Max + 1]

            ; Move down all elements below the new index
            For $i = $iIndex_Max To $iIndex + 1 Step -1
                $avArray[$i] = $avArray[$i - 1]
            Next

            ; Add the value in the specified element
            $avArray[$iIndex] = $vInsert
            Return $iIndex_Max

        Case 2

            ; If at end of array
            If $iIndex > $iIndex_Max - 1 Then Return $iIndex_Max = _GUIListViewEx_Array_Add($avArray, $vInsert)

            ; Get size of second dimension
            Local $iDim2 = UBound($avArray, 2)

            ; Redim the Array
            ReDim $avArray[$iIndex_Max + 1][$iDim2]

            ; Move down all elements below the new index
            For $i = $iIndex_Max To $iIndex + 1 Step -1
                For $j = 0 To $iDim2 - 1
                    $avArray[$i][$j] = $avArray[$i - 1][$j]
                Next
            Next

            ; Insert new elements
            If IsArray($vInsert) Then
                ; Get size of Insert array
                Local $vInsert_Max = UBound($vInsert)
                For $j = 0 To $iDim2 - 1
                    ; If Insert array is too small to fill Array then continue with blanks
                    If $j > $vInsert_Max - 1 Then
                        $avArray[$iIndex][$j] = ""
                    Else
                        $avArray[$iIndex][$j] = $vInsert[$j]
                    EndIf
                Next
            Else
                ; Fill Array with variable
                For $j = 0 To $iDim2 - 1
                    $avArray[$iIndex][$j] = $vInsert
                Next
            EndIf

    EndSwitch

    Return $iIndex_Max + 1

EndFunc   ;==>_GUIListViewEx_Array_Insert

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Array_Delete
; Description ...: Deletes a specified index from an existing 1D or 2D array.
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================

Func _GUIListViewEx_Array_Delete(ByRef $avArray, $iIndex)

    ; Get size of the Array to modify
    Local $iIndex_Max = UBound($avArray)

    ; Get type of array
    Switch UBound($avArray, 0)
        Case 1

            ; Move up all elements below the new index
            For $i = $iIndex To $iIndex_Max - 2
                $avArray[$i] = $avArray[$i + 1]
            Next

            ; Redim the Array
            ReDim $avArray[$iIndex_Max - 1]

        Case 2

            ; Get size of second dimension
            Local $iDim2 = UBound($avArray, 2)

            ; Move up all elements below the new index
            For $i = $iIndex To $iIndex_Max - 2
                For $j = 0 To $iDim2 - 1
                    $avArray[$i][$j] = $avArray[$i + 1][$j]
                Next
            Next

            ; Redim the Array
            ReDim $avArray[$iIndex_Max - 1][$iDim2]

    EndSwitch

    Return $iIndex_Max - 1

EndFunc   ;==>_GUIListViewEx_Array_Delete

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Array_Swap
; Description ...: Swaps specified elements within a 1D or 2D array
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================

Func _GUIListViewEx_Array_Swap(ByRef $avArray, $iIndex1, $iIndex2)

    Local $vTemp

    ; Get type of array
    Switch UBound($avArray, 0)
        Case 1
            ; Swap the elements via a temp variable
            $vTemp = $avArray[$iIndex1]
            $avArray[$iIndex1] = $avArray[$iIndex2]
            $avArray[$iIndex2] = $vTemp

        Case 2

            ; Get size of second dimension
            Local $iDim2 = UBound($avArray, 2)
            ; Swap the elements via a temp variable
            For $i = 0 To $iDim2 - 1
                $vTemp = $avArray[$iIndex1][$i]
                $avArray[$iIndex1][$i] = $avArray[$iIndex2][$i]
                $avArray[$iIndex2][$i] = $vTemp
            Next
    EndSwitch

    Return 0

EndFunc   ;==>_GUIListViewEx_Array_Swap

Now to work on the UDF to get the "editing" part of your script to function correctly. You seem to like making me work! :D

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

  • Moderators

johnmcloud,

Testing time again! :D

Here is your much slimmer script: ;)

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <GuiListView.au3>
#include <GuiMenu.au3>
#include <WinAPI.au3>

#include "GUIListViewEx_Mod.au3"

Global $Number = 0, $hMenu
Global Enum $idMoveUp = 1000, $idMoveDown, $idDelete
Global $Style = BitOR($WS_CHILD, $WS_VISIBLE, $ES_AUTOHSCROLL, $ES_LEFT)

$hGUI = GUICreate("_GUICtrlListView_Example", 262, 351, -1, -1)
$cListview = GUICtrlCreateListView("N°|Test|Test2", 5, 5, 250, 272, $LVS_REPORT)
$hListview = GUICtrlGetHandle($cListview)
_GUICtrlListView_SetExtendedListViewStyle($hListview, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_BORDERSELECT))
_GUICtrlListView_SetColumnWidth($hListview, 0, 35)
_GUICtrlListView_SetColumnWidth($hListview, 1, 107)
_GUICtrlListView_SetColumnWidth($hListview, 2, 108)

$iLV_Index = _GUIListViewEx_Init($hListview, "", 0, 0, 3) ; The final parameter = "Sort & Edit" <<<<<<<<<<<<<<<<<<<<<<

$Label = GUICtrlCreateLabel("Name", 13, 290, 67, 17)
$c_Button_Add = GUICtrlCreateButton("Add", 90, 315, 80, 25)
$Info = GUICtrlCreateInput("Value", 88, 286, 83, 21)
$c_Button_Save = GUICtrlCreateButton("Save", 174, 284, 80, 25)

$hMenu = _GUICtrlMenu_CreatePopup()
_GUICtrlMenu_InsertMenuItem($hMenu, 0, "Move Up", $idMoveUp)
_GUICtrlMenu_InsertMenuItem($hMenu, 1, "Move Down", $idMoveDown)
_GUICtrlMenu_InsertMenuItem($hMenu, 3, "", 0)
_GUICtrlMenu_InsertMenuItem($hMenu, 3, "Delete", $idDelete)

$c_Dummy_Down = GUICtrlCreateDummy()
$c_Dummy_Up = GUICtrlCreateDummy()
$c_Dummy_Delete = GUICtrlCreateDummy()

Local $AccelKeys[3][2] = [["{DELETE}", $c_Dummy_Delete],["{UP}", $c_Dummy_Up],["{DOWN}", $c_Dummy_Down]]
GUISetAccelerators($AccelKeys, $hGUI)

Global $B_DESCENDING[_GUICtrlListView_GetColumnCount($hListview)]

GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $c_Button_Add
            Add_Item()
        Case $c_Button_Save
            Save_List()
        Case $c_Dummy_Delete
            Delete_Item()
        Case $c_Dummy_Down
            Move_Down()
        Case $c_Dummy_Up
            Move_Up()
    EndSwitch

    _GUIListViewEx_EditAction("1;2") ; This is the new function allowing you to edit columns 1 and 2 <<<<<<<<<<<<<<<<<<<<<<<<<<<

WEnd

Func Add_Item()
    $Number += 1
    $vData = $Number & "|" & GUICtrlRead($Label) & "|" & GUICtrlRead($Info)
    _GUIListViewEx_Insert($vData)
EndFunc   ;==>Add_Item

Func Delete_Item()
    _GUIListViewEx_Delete()
EndFunc   ;==>Delete_Item

Func Save_List()
    Local $Save = FileSaveDialog("Save", @WorkingDir, "Txt Files (*.txt)", 2, "Test_File_" & @MDAY & "-" & @MON & "-" & @YEAR & "_" & @HOUR & "-" & @MIN)
    If @error Then
        ConsoleWrite("Abort")
    Else
        $List = FileOpen($Save & ".txt", 2)
        $Number_items = _GUICtrlListView_GetItemCount($hListview)
        For $i = 0 To $Number_items - 1 Step +1
            $output = StringReplace(_GUICtrlListView_GetItemTextString($hListview, $i), "|", " - ")
            FileWriteLine($List, $output)
        Next
        FileClose($List)
    EndIf
EndFunc   ;==>Save_List

Func Move_Up()
    _GUIListViewEx_Up()
EndFunc   ;==>Move_Up

Func Move_Down()
    _GUIListViewEx_Down()
EndFunc   ;==>Move_Down

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)

    _GUIListViewEx_WM_NOTIFY_Handler($hWnd, $iMsg, $iwParam, $ilParam) ; The UDF does everything else in here <<<<<<<<<<<<<<<<<<<

    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListview
            Switch $iCode
                Case $NM_RCLICK
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                    If DllStructGetData($tInfo, "Item") > -1 Then
                        _GUICtrlMenu_TrackPopupMenu($hMenu, $hGUI)
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Switch $wParam
        Case $idMoveUp
            Move_Up()
        Case $idMoveDown
            Move_Down()
        Case $idDelete
            Delete_Item()
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

And here is a beta UDF to test it with - again save it as GUIListViewEx_Mod.au3:

#include-once

; #INDEX# ============================================================================================================
; Title .........: GUIListViewEx
; AutoIt Version : 3.3 +
; Language ......: English
; Description ...: Permits insertion, deletion, moving, dragging and sorting of items within activated ListViews
; Remarks .......: - It is important to use _GUIListViewEx_Close when a enabled ListView is deleted to free the memory used
;                    by the $aGLVEx_Data array which shadows the ListView contents.
;                  - If the script already has WM_NOTIFY, WM_MOUSEMOVE or WM_LBUTTONUP handlers then only set the
;                    unregistered messages in _GUIListViewEx_DragRegister and call the relevant _GUIListViewEx_WM_#####_Handler
;                    from within the existing handler
;                  - Uses 2 undocumented function within GUIListView UDF to set and colour insert mark (thanks rover)
;                  - If ListView is editable, Opt("GUICloseOnESC") set to 0 as ESC = edit cancel.  Do not reset Opt in script
; Author ........: Melba23 - credit to martin (basic drag code), Array.au3 authors (original array functions)
; Modified ......;
; ====================================================================================================================

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

; #INCLUDES# =========================================================================================================
#include <GuiListView.au3>
#include <GUIImageList.au3>

; #GLOBAL VARIABLES# =================================================================================================
; Array to hold registered ListView data
Global $aGLVEx_Data[1][8] = [[0, 0]]
; [0][0] = Count            [n][0] = ListView handle
; [0][1] = Active Index        [n][1] = Native ListView ControlID / 0
;                             [n][2] = Content array
;                             [n][3] = [0] element is count
;                           [n][4] = Sorting array
;                           [n][5] = Drag image
;                             [n][6] = Checkbox array
;                           [n][7] = Editable
; Variables for all UDF functions
Global $hGLVEx_Handle, $hGLVEx_CID, $aGLVEx_Array
; Variables for UDF dragging handlers
Global $iGLVEx_Dragging = 0, $iGLVExDragged_Index, $hGLVExDragged_Image = 0, $iGLVExInsert_Index = -1, $iGLVExLast_Y
Global $fGLVEx_Bar_Under, $fGLVEx_MultipleDrag, $aGLVExDragCheck_Array
; Variables for UDF edit
Global $cGLVEx_EditCID = 0, $fGLVEx_EditFlag = False

; #CURRENT# ==========================================================================================================
; _GUIListViewEx_Init:                 Enables UDF button functions for the ListView and sets insert mark colour
; _GUIListViewEx_Close:                Disables all UDF functions for the specified ListView and clears all memory used
; _GUIListViewEx_SetActive:            Set specified ListView as active for UDF functions
; _GUIListViewEx_GetActive:            Get index number of ListView active for UDF functions
; _GUIListViewEx_Return_Array:         Returns an array reflecting the current state of the ListView
; _GUIListViewEx_Insert:               Inserts data just below selected item in active ListView
; _GUIListViewEx_Delete:               Deletes selected item in active ListView
; _GUIListViewEx_Up:                   Moves selected item in active ListView up 1 place
; _GUIListViewEx_Down:                 Moves selected item in active ListView down 1 place
; _GUIListViewEx_EditAction:           Allows editing of ListView items
; _GUIListViewEx_DragRegister:         Registers Windows messages to enable item dragging for listed ListViews
; _GUIListViewEx_WM_NOTIFY_Handler:    Windows message handler for WM_NOTIFY
; _GUIListViewEx_WM_MOUSEMOVE_Handler: Windows message handler for WM_MOUSEMOVE
; _GUIListViewEx_WM_LBUTTONUP_Handler: Windows message handler for WM_LBUTTONUP
; ====================================================================================================================

; #INTERNAL_USE_ONLY#=================================================================================================
; _GUIListViewEx_HighLight:    Highlights specified ListView item and ensures it is visible
; _GUIListViewEx_Data_Change:  Resets ListView items within a defined range to the current values in the stored array
; _GUIListViewEx_Array_Add:    Adds a specified value at the end of an array
; _GUIListViewEx_Array_Insert: Adds a value at the specified index of an array
; _GUIListViewEx_Array_Delete: Deletes a specified index from an array
; _GUIListViewEx_Array_Swap:   Swaps specified elements within an array
; ====================================================================================================================

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Init
; Description ...: Enables UDF button functions for the ListView and sets insert mark colour for drag function
; Syntax.........: _GUIListViewEx_Init($hLV, [$aArray = "", [$iStart = 0, [$iColour, [$iAdded, $fImage]]]]])
; Parameters ....: $hLV     - Handle or ControlID of ListView
;                  $a Array - Name of array used to fill ListView.  "" = empty ListView
;                  $iStart  - 0 (default) = ListView data starts in [0] element of array, 1 = Count in [0] element
;                  $iColour - RGB colour for insert mark (default = black)
;                  $iAdded  - 0   - No added features (default).  To get added fatures add the following
;                             + 1 - Sortable by clickign on column headers
;                             + 2 - Editable by double clicking on a subitem
;                  $fImage  - True = Shadow image of dragged item when dragging
; Requirement(s).: v3.3 +
; Return values .: Index number of ListView for use in other GUIListViewEx functions
; Author ........: Melba23
; Modified ......:
; Remarks .......: - If the ListView is the only one enabled, it is automatically set as active
;                  - If no array is passed a shadow array is created automatically - if the ListView has more than
;                  1 column this array is 2D with the second dimension set to the number of columns
;                  - The shadow array has a count in element [0] added if it does not exist. However, if the $iStart
;                  parameter is set to 0 this count element will not be returned by other GUIListViewEx functions
;                  - Only first item of a multiple selection is shadow imaged when dragging (API limitation)
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Init($hLV, $aArray = "", $iStart = 0, $iColour = 0, $iAdded = 0, $fImage = False)

    Local $iIndex = 0

    ; See if there is a blank line available in the array
    For $i = 1 To $aGLVEx_Data[0][0]
        If $aGLVEx_Data[$i][0] = 0 Then
            $iIndex = $i
            ExitLoop
        EndIf
    Next
    ; If no blank line found then increase array size
    If $iIndex = 0 Then
        $aGLVEx_Data[0][0] += 1
        ReDim $aGLVEx_Data[$aGLVEx_Data[0][0] + 1][8]
        $iIndex = $aGLVEx_Data[0][0]
    EndIf

    ; Store ListView handle and ControlID
    If IsHWnd($hLV) Then
        $aGLVEx_Data[$iIndex][0] = $hLV
        $aGLVEx_Data[$iIndex][1] = 0
    Else
        $aGLVEx_Data[$iIndex][0] = GUICtrlGetHandle($hLV)
        $aGLVEx_Data[$iIndex][1] = $hLV
    EndIf

    ; Create a shadow array if needed
    If $aArray = "" Then
        Local $iCols = _GUICtrlListView_GetColumnCount($aGLVEx_Data[$iIndex][0])
        Switch $iCols
            Case 1
                Local $aReplacement[1] = [0]
            Case Else
                Local $aReplacement[1][$iCols] = [[0]]
        EndSwitch
        $aArray = $aReplacement
    Else
        ; Add count element to shadow array if required
        If $iStart = 0 Then _GUIListViewEx_Array_Insert($aArray, 0, UBound($aArray))
    EndIf
    ; Store array
    $aGLVEx_Data[$iIndex][2] = $aArray

    ; Store [0] = count data
    $aGLVEx_Data[$iIndex][3] = $iStart
    ; If sortable, store sort array
    If BitAnd($iAdded, 1) Then
        Local $aLVSortState[_GUICtrlListView_GetColumnCount($hLV)]
        $aGLVEx_Data[$iIndex][4] = $aLVSortState
    Else
        $aGLVEx_Data[$iIndex][4] = 0
    EndIf
    ; If editable
    If BitAnd($iAdded, 2) Then
        $aGLVEx_Data[$iIndex][7] = 1
        ; Limit ESC to edit cancel
        Opt("GUICloseOnESC", 0)
    Else
        $aGLVEx_Data[$iIndex][7] = 0
    EndIf
    ; If image required
    If $fImage Then
        $aGLVEx_Data[$iIndex][5] = 1
    EndIf
    ;  If checkbox extended style
    If BitAnd(_GUICtrlListView_GetExtendedListViewStyle($hLV), 4) Then ; $LVS_EX_CHECKBOXES
        $aGLVEx_Data[$iIndex][6] = 1
    EndIf

    ; Set insert mark colour after conversion to BGR
    _GUICtrlListView_SetInsertMarkColor($hLV, BitOR(BitShift(BitAND($iColour, 0x000000FF), -16), BitAND($iColour, 0x0000FF00), BitShift(BitAND($iColour, 0x00FF0000), 16)))

    ; If only 1 current ListView then activate
    Local $iListView_Count = 0
    For $i = 1 To $iIndex
        If $aGLVEx_Data[$i][0] Then $iListView_Count += 1
    Next
    If $iListView_Count = 1 Then _GUIListViewEx_SetActive($iIndex)

    ; Return ListView index
    Return $iIndex

EndFunc   ;==>_GUIListViewEx_Init

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Close
; Description ...: Disables all UDF functions for the specified ListView and clears all memory used
; Syntax.........: _GUIListViewEx_Close($iIndex)
; Parameters ....: $iIndex - Index number of ListView to close as returned by _GUIListViewEx_Init
;                            0 (default) = Closes all ListViews
; Requirement(s).: v3.3 +
; Return values .: Success: 1
;                  Failure: 0 and @error set to 1 - Invalid index number
; Author ........: Melba23
; Modified ......:
; Remarks .......:
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Close($iIndex = 0)

    ; Check valid index
    If $iIndex < 0 Or $iIndex > $aGLVEx_Data[0][0] Then Return SetError(1, 0, 0)

    If $iIndex = 0 Then
        ; Remove all ListView data
        Global $aGLVEx_Data[1][8] = [[0, 0]]
    Else
        ; Reset all data for ListView
        For $i = 0 To 6
            $aGLVEx_Data[$iIndex][$i] = 0
        Next

        ; Cancel active index if set to this ListView
        If $aGLVEx_Data[0][1] = $iIndex Then $aGLVEx_Data[0][1] = 0
    EndIf

    Return 1

EndFunc   ;==>_GUIListViewEx_Close

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_SetActive
; Description ...: Set specified ListView as active for UDF functions
; Syntax.........: _GUIListViewEx_SetActive($iIndex)
; Parameters ....: $iIndex - Index number of ListView as returned by _GUIListViewEx_Init
;                  An index of 0 clears any current setting
; Requirement(s).: v3.3 +
; Return values .: Success: Returns previous active index number, 0 = no previously active ListView
;                  Failure: -1 and @error set to 1 - Invalid index number
; Author ........: Melba23
; Modified ......:
; Remarks .......: ListViews can also be activated by clicking on them
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_SetActive($iIndex)

    ; Check valid index
    If $iIndex < 0 Or $iIndex > $aGLVEx_Data[0][0] Then Return SetError(1, 0, -1)

    Local $iCurr_Index = $aGLVEx_Data[0][1]

    If $iIndex Then
        ; Store index of specified ListView
        $aGLVEx_Data[0][1] = $iIndex
        ; Set values for specified ListView
        $hGLVEx_Handle = $aGLVEx_Data[$iIndex][0]
        $hGLVEx_CID = $aGLVEx_Data[$iIndex][1]
    Else
        ; Clear active index
        $aGLVEx_Data[0][1] = 0
    EndIf

    Return $iCurr_Index

EndFunc

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_GetActive
; Description ...: Get index number of ListView active for UDF functions
; Syntax.........: _GUIListViewEx_GetActive()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: Success: Index number as returned by _GUIListViewEx_Init, 0 = no active ListView
; Author ........: Melba23
; Modified ......:
; Remarks .......:
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_GetActive()

    Return $aGLVEx_Data[0][1]

EndFunc

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Return_Array
; Description ...: Returns an array reflecting the current state of the ListView
; Syntax.........: _GUIListViewEx_Return_Array($iIndex)
; Parameters ....: $iIndex - Index number of ListView as returned by _GUIListViewEx_Init
;                  $iCheck - If non-zero then the state of the checkboxes is returned (Default = 0)
; Requirement(s).: v3.3 +
; Return values .: Success: Array of current ListView - presence of count in [0] element determined by _GUIListViewEx_Init
;                  Failure: Empty array returns null string and sets @error as follows:
;                           1 = Invalid index number
;                           2 = Empty array (no items in ListView)
;                           3 = $iCheck set to True but ListView does not have checkbox style
; Author ........: Melba23
; Modified ......:
; Remarks .......: The $iStart parameter from GUIListViewEx_Init determines whether the [0] element is a count
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Return_Array($iIndex, $iCheck = 0)

    ; Check valid index
    If $iIndex < 1 Or $iIndex > $aGLVEx_Data[0][0] Then Return SetError(1, 0, "")

    ; Copy current array
    Local $aRetArray = $aGLVEx_Data[$iIndex][2]

    ; Check if checkbox array
    If $iCheck Then
        If $aGLVEx_Data[$iIndex][6] Then
            Local $aCheck_Array[UBound($aRetArray)]
            For $i = 1 To UBound($aRetArray) - 1
                $aCheck_Array[$i] = _GUICtrlListView_GetItemChecked($aGLVEx_Data[$iIndex][0], $i - 1)
            Next
            ; Remove count element if required
            If $aGLVEx_Data[$iIndex][3] = 0 Then
                ; Check at least one entry in 1D/2D array
                Switch UBound($aRetArray, 0)
                    Case 1
                        If $aRetArray[0] = 0 Then Return SetError(2, 0, "")
                    Case 2
                        If $aRetArray[0][0] = 0 Then Return SetError(2, 0, "")
                EndSwitch
                ; Delete count element
                _GUIListViewEx_Array_Delete($aCheck_Array, 0)
            EndIf
            Return $aCheck_Array
        Else
            Return SetError(3, 0, "")
        EndIf
    EndIf

    ; Remove count element of array if required
    If $aGLVEx_Data[$iIndex][3] = 0 Then
        ; Check at least one entry in 1D/2D array
        Switch UBound($aRetArray, 0)
            Case 1
                If $aRetArray[0] = 0 Then Return SetError(2, 0, "")
            Case 2
                If $aRetArray[0][0] = 0 Then Return SetError(2, 0, "")
        EndSwitch
        ; Delete count element
        _GUIListViewEx_Array_Delete($aRetArray, 0)
    EndIf

    ; Return array
    Return $aRetArray

EndFunc   ;==>_GUIListViewEx_Return_Array

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Insert
; Description ...: Inserts data just below selected item in active ListView
;                  If no selection, data added at end
; Syntax.........: _GUIListViewEx_Insert($vData)
; Parameters ....: $vData - Data to insert, can be in array or delimited string format
; Requirement(s).: v3.3 +
; Return values .: Success: Array of current ListView with count in [0] element
;                  Failure: If no ListView active then returns "" and sets @error to 1
; Author ........: Melba23
; Modified ......:
; Remarks .......: - New data is inserted after the selected item.  If no item is selected then the datat is added at
;                  the end of the ListView.  If multiple items are selected, the data is inserted after the first
;                  - $vData can be passed in string or array format - it is automatically transformed if required
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Insert($vData)

    Local $vInsert

    ; Set data for active ListView
    Local $iArray_Index = $aGLVEx_Data[0][1]
    ; If no ListView active then return
    If $iArray_Index = 0 Then Return SetError(1, 0, "")

    ; Load active ListView details
    $hGLVEx_Handle = $aGLVEx_Data[$iArray_Index][0]
    $hGLVEx_CID = $aGLVEx_Data[$iArray_Index][1]

    ; Get selected item in ListView
    Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
    Local $iInsert_Index = $iIndex
    ; If no selection
    If $iIndex = "" Then $iInsert_Index = -1
    ; Check for multiple selections
    If StringInStr($iIndex, "|") Then
        Local $aIndex = StringSplit($iIndex, "|")
        ; Use first selection
        $iIndex = $aIndex[1]
        ; Cancel all other selections
        For $i = 2 To $aIndex[0]
            _GUICtrlListView_SetItemSelected($hGLVEx_Handle, $aIndex[$i], False)
        Next
    EndIf

    ; Copy array for manipulation
    $aGLVEx_Array = $aGLVEx_Data[$iArray_Index][2]

    ; Create Local array for checkboxes if required
    If $aGLVEx_Data[$iArray_Index][6] Then
        Local $aCheck_Array[UBound($aGLVEx_Array)]
        For $i = 1 To UBound($aCheck_Array) - 1
            $aCheck_Array[$i] = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $i - 1)
        Next
    EndIf

    ; Check if 1D/2D array
    Switch UBound($aGLVEx_Array, 0)
        Case 1
            ; If empty array insert at 0
            If $aGLVEx_Array[0] = 0 Then $iInsert_Index = 0
            ; Get data into string format for insert
            If IsArray($vData) Then
                $vInsert = ""
                For $i = 0 To UBound($vData) - 1
                    $vInsert &= $vData[$i] & "|"
                Next
                $vInsert = StringTrimRight($vInsert, 1)
            Else
                $vInsert = $vData
            EndIf
            ; Increase count
            $aGLVEx_Array[0] += 1
        Case 2
            ; If empty array insert at 0
            If $aGLVEx_Array[0][0] = 0 Then $iInsert_Index = 0
            ; Get data into array format for insert
            If IsArray($vData) Then
                $vInsert = $vData
            Else
                Local $aData = StringSplit($vData, "|")
                Switch $aData[0]
                    Case 1
                        $vInsert = $aData[1]
                    Case Else
                        Local $vInsert[$aData[0]]
                        For $i = 0 To $aData[0] - 1
                            $vInsert[$i] = $aData[$i + 1]
                        Next
                EndSwitch
            EndIf
            ; Increase count
            $aGLVEx_Array[0][0] += 1
    EndSwitch

    ; Insert data into array
    If $iIndex = "" Then
        _GUIListViewEx_Array_Add($aGLVEx_Array, $vInsert)
    Else
        _GUIListViewEx_Array_Insert($aGLVEx_Array, $iInsert_Index + 2, $vInsert)
        If $aGLVEx_Data[$iArray_Index][6] Then
            _GUIListViewEx_Array_Insert($aCheck_Array, $iInsert_Index + 2, False)
            ; Reset all checkboxes
            For $i = 1 To UBound($aCheck_Array) - 1
                _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $i - 1, $aCheck_Array[$i])
            Next
        EndIf
    EndIf

    ; Check if Native or UDF
    If $hGLVEx_CID Then
        ; Add new item at ListView end
        If IsArray($vInsert) Then
            If IsArray($vData) Then
                $vInsert = ""
                For $i = 0 To UBound($vData) - 1
                    $vInsert &= $vData[$i] & "|"
                Next
                $vInsert = StringTrimRight($vInsert, 1)
                GUICtrlCreateListViewItem($vInsert, $hGLVEx_CID)
            Else
                GUICtrlCreateListViewItem($vData, $hGLVEx_CID)
            EndIf
        Else
            GUICtrlCreateListViewItem($vInsert, $hGLVEx_CID)
        EndIf
    Else
        ; Add new item at ListView end
        Local $iNewItem
        If IsArray($vInsert) Then
            $iNewItem = _GUICtrlListView_AddItem($hGLVEx_Handle, $vInsert[0])
            ; Add new subitems
            For $i = 1 To UBound($vInsert) - 1
                _GUICtrlListView_AddSubItem($hGLVEx_Handle, $iNewItem, $vInsert[$i], $i)
            Next
        Else
            $iNewItem = _GUICtrlListView_AddItem($hGLVEx_Handle, $vInsert)
        EndIf
    EndIf
    ; Check where item was to be inserted
    If $iIndex = "" Then
        _GUIListViewEx_Data_Change($iInsert_Index, $iInsert_Index)
        ; No moves required so set highlight
        _GUIListViewEx_Highlight(_GUICtrlListView_GetItemCount($hGLVEx_Handle) - 1)
    Else
        ; Reset item contents below insert position
        _GUIListViewEx_Data_Change($iInsert_Index, _GUICtrlListView_GetItemCount($hGLVEx_Handle) - 1)
        ; Set highlight
        _GUIListViewEx_Highlight($iInsert_Index + 1, $iInsert_Index)
    EndIf

    ; Store amended array
    $aGLVEx_Data[$iArray_Index][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0
    ; Return amended array
    Return _GUIListViewEx_Return_Array($iArray_Index)

EndFunc   ;==>_GUIListViewEx_Insert

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Delete
; Description ...: Deletes selected item in active ListView
; Syntax.........: _GUIListViewEx_Delete()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: Success: Array of active ListView with count in [0] element
;                  Failure: Returns "" and sets @error as follows:
;                      1 = No ListView active
;                      2 = No item selected
;                      3 = No items to delete
; Author ........: Melba23
; Modified ......:
; Remarks .......: If multiple items are selected, all are deleted
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Delete()

    ; Set data for active ListView
    Local $iArray_Index = $aGLVEx_Data[0][1]
    ; If no ListView active then return
    If $iArray_Index = 0 Then Return SetError(1, 0, "")

    ; Load active ListView details
    $hGLVEx_Handle = $aGLVEx_Data[$iArray_Index][0]
    $hGLVEx_CID = $aGLVEx_Data[$iArray_Index][1]

    ; Check for selected items
    Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
    If $iIndex = "" Then Return SetError(2, 0, "")

    ; Copy array for manipulation
    $aGLVEx_Array = $aGLVEx_Data[$iArray_Index][2]

    ; Determine final item
    Local $iLast = UBound($aGLVEx_Array) - 2

    ; Check if item is part of a multiple selection
    If StringInStr($iIndex, "|") Then
        ; Extract all selected items
        Local $aIndex = StringSplit($iIndex, "|")
        For $i = 1 To $aIndex[0]
            ; Remove highlighting from items
            _GUICtrlListView_SetItemSelected($hGLVEx_Handle, $i, False)
        Next

        ; Check if 1D/2D array
        Switch UBound($aGLVEx_Array, 0)
            Case 1
                ; Decrease count
                $aGLVEx_Array[0] -= $aIndex[0]
            Case 2
                ; Decrease count
                $aGLVEx_Array[0][0] -= $aIndex[0]
        EndSwitch

        ; Delete elements from array - start from bottom
        For $i = $aIndex[0] To 1 Step -1
            _GUIListViewEx_Array_Delete($aGLVEx_Array, $aIndex[$i] + 1)
        Next

        ; Delete items from ListView - again start from bottom
        For $i = $aIndex[0] To 1 Step -1
            _GUICtrlListView_DeleteItem($hGLVEx_Handle, $aIndex[$i])
        Next

    Else
        ; Check if 1D/2D array
        Switch UBound($aGLVEx_Array, 0)
            Case 1
                ; Decrease count
                $aGLVEx_Array[0] -= 1
            Case 2
                ; Decrease count
                $aGLVEx_Array[0][0] -= 1
        EndSwitch
        ; Delete element from array
        _GUIListViewEx_Array_Delete($aGLVEx_Array, $iIndex + 1)

        ; Delete item from ListView
        _GUICtrlListView_DeleteItem($hGLVEx_Handle, $iIndex)
        ; Set highlight - up one if bottom deleted
        If $iIndex = $iLast Then
            _GUIListViewEx_Highlight($iIndex - 1)
        Else
            _GUIListViewEx_Highlight($iIndex)
        EndIf
    EndIf

    ; Store amended array
    $aGLVEx_Data[$iArray_Index][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0
    ; Return amended array
    Return _GUIListViewEx_Return_Array($iArray_Index)

EndFunc   ;==>_GUIListViewEx_Delete

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Up
; Description ...: Moves selected item in active ListView up 1 place
; Syntax.........: _GUIListViewEx_Up()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: Success: Array of active ListView with count in [0] element
;                  Failure: Returns "" and sets @error as follows:
;                      1 = No ListView active
;                      2 = No item selected
;                      3 = Item already at top
; Author ........: Melba23
; Modified ......:
; Remarks .......: If multiple items are selected, only the top consecutive block is moved
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Up()

    Local $iGLVExMove_Index, $iGLVEx_Moving = 0

    ; Set data for active ListView
    Local $iArray_Index = $aGLVEx_Data[0][1]
    ; If no ListView active then return
    If $iArray_Index = 0 Then Return SetError(1, 0, 0)

    ; Load active ListView details
    $hGLVEx_Handle = $aGLVEx_Data[$iArray_Index][0]
    $hGLVEx_CID = $aGLVEx_Data[$iArray_Index][1]

    ; Check for selected items
    Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
    Local $aIndex = StringSplit($iIndex, "|")
    $iGLVExMove_Index = $aIndex[1]
    ; Check if item is part of a multiple selection
    If $aIndex[0] > 1 Then
        ; Check for consecutive items
        For $i = 1 To $aIndex[0] - 1
            If $aIndex[$i + 1] = $aIndex[1] + $i Then
                $iGLVEx_Moving += 1
            Else
                ExitLoop
            EndIf
        Next
    Else
        $iGLVExMove_Index = $aIndex[1]
    EndIf

    ; Remove all highlighting
    _GUICtrlListView_SetItemSelected($hGLVEx_Handle, -1, False)

    ; Check not top item
    If $iGLVExMove_Index = "0" Then Return SetError(3, 0, "")

    ; Copy array for manipulation
    $aGLVEx_Array = $aGLVEx_Data[$iArray_Index][2]

    ; Move consecutive items
    For $iIndex = $iGLVExMove_Index To $iGLVExMove_Index + $iGLVEx_Moving

        ; Swap array elements
        _GUIListViewEx_Array_Swap($aGLVEx_Array, $iIndex, $iIndex + 1)

        ; Swap checkboxes if required
        If $aGLVEx_Data[$iArray_Index][6] Then
            Local $fTemp = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iIndex)
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $iIndex, _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iIndex - 1))
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $iIndex - 1, $fTemp)
        EndIf

        ; Change data in affected items
        _GUIListViewEx_Data_Change($iIndex - 1, $iIndex);, $aGLVEx_Array)
        ; Set highlight and cancel existing one (needed for multiple selection ListViews)
        _GUIListViewEx_Highlight($iIndex - 1, $iIndex)
    Next

    ; Store amended array
    $aGLVEx_Data[$iArray_Index][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0
    ; Return amended array
    Return _GUIListViewEx_Return_Array($iArray_Index)

EndFunc   ;==>_GUIListViewEx_Up

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_Down
; Description ...: Moves selected item in active ListView down 1 place
; Syntax.........: _GUIListViewEx_Down()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: Success: Array of active ListView with count in [0] element
;                  Failure: Returns "" and sets @error as follows:
;                      1 = No ListView active
;                      2 = No item selected
;                      3 = Item already at bottom
; Author ........: Melba23
; Modified ......:
; Remarks .......: If multiple items are selected, only the bottom consecutive block is moved
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_Down()

    Local $iGLVExMove_Index, $iGLVEx_Moving = 0

    ; Set data for active ListView
    Local $iArray_Index = $aGLVEx_Data[0][1]
    ; If no ListView active then return
    If $iArray_Index = 0 Then Return SetError(1, 0, 0)

    ; Load active ListView details
    $hGLVEx_Handle = $aGLVEx_Data[$iArray_Index][0]
    $hGLVEx_CID = $aGLVEx_Data[$iArray_Index][1]

    ; Check for selected items
    Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
    Local $aIndex = StringSplit($iIndex, "|")
    ; Check if item is part of a multiple selection
    If $aIndex[0] > 1 Then
        $iGLVExMove_Index = $aIndex[$aIndex[0]]
        ; Check for consecutive items
        For $i = 1 To $aIndex[0] - 1
            If $aIndex[$aIndex[0] - $i] = $aIndex[$aIndex[0]] - $i Then
                $iGLVEx_Moving += 1
            Else
                ExitLoop
            EndIf
        Next
    Else
        $iGLVExMove_Index = $aIndex[1]
    EndIf

    ; Remove all highlighting
    _GUICtrlListView_SetItemSelected($hGLVEx_Handle, -1, False)

    ; Check not last item
    If $iGLVExMove_Index = _GUICtrlListView_GetItemCount($hGLVEx_Handle) - 1 Then
        _GUIListViewEx_Highlight($iIndex)
        Return
    EndIf

    ; Copy array for manipulation
    $aGLVEx_Array = $aGLVEx_Data[$iArray_Index][2]

    ; Move consecutive items
    For $iIndex = $iGLVExMove_Index To $iGLVExMove_Index - $iGLVEx_Moving Step -1

        ; Swap array elements
        _GUIListViewEx_Array_Swap($aGLVEx_Array, $iIndex + 1, $iIndex + 2)

        ; Swap checkboxes if required
        If $aGLVEx_Data[$iArray_Index][6] Then
            Local $fTemp = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iIndex)
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $iIndex, _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iIndex + 1))
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $iIndex + 1, $fTemp)
        EndIf

        ; Change data in affected items
        _GUIListViewEx_Data_Change($iIndex, $iIndex + 1)
        ; Set highlight and cancel existing one (needed for multiple selection ListViews)
        _GUIListViewEx_Highlight($iIndex + 1, $iIndex)

    Next

    ; Store amended array
    $aGLVEx_Data[$iArray_Index][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0
    ; Return amended array
    Return _GUIListViewEx_Return_Array($iArray_Index)

EndFunc   ;==>_GUIListViewEx_Down

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_EditAction
; Description ...: Allows editing of ListView items
; Syntax.........: _GUIListViewEx_EditAction([$sCols = "*"[, $iDelta_X = 0[, $iDelta_Y = 0]]])
; Parameters ....: $sCols    = Editable columns - "" = all (default).  Separate multiple columns with ;
;                  $iDelta_X = Fine adjustment of edit control in X axis
;                  $iDelta_Y = Fine adjustment of edit control in Y axis
; Requirement(s).: v3.3 +
; Return values .: Success: Edited array of active ListView
;                  Failure: Returns "" and sets @error as follows:
;                           1 - Edit cancelled
;                           2 - Column not editable
; Author ........: Melba23
; Modified ......:
; Remarks .......: This function must be called within the script idle loop. Once called, all other script activity
;                  suspended until edit is confimed {ENTER} or cancelled {ESCAPE}
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_EditAction($sCols = "", $iDelta_X = 0, $iDelta_Y = 0)

    ; If an item was double clicked
    If $fGLVEx_EditFlag Then
        ; Get handle of ListView parent
        Local $aResult = DllCall("user32.dll", "hwnd", "GetParent", "hwnd", $hGLVEx_Handle)
        Local $hWnd = $aResult[0]
        ; Set data for active ListView
        Local $iArray_Index = $aGLVEx_Data[0][1]
        ; If no ListView active then return
        If $iArray_Index = 0 Then
            Return SetError(1, 0, "")
        EndIf
        ; Get clicked item info
        Local $aHit = _GUICtrlListView_SubItemHitTest($hGLVEx_Handle)
        ; Check if column is editable
        If $sCols Then
            If Not StringInStr(";" & $sCols, ";" & $aHit[1]) Then
                ; Clear flag
                $fGLVEx_EditFlag = False
                Return SetError(2, 0, "")
            EndIf
        EndIf
        ; Read current text of clicked item
        Local $sItemOrgText = _GUICtrlListView_GetItemText($hGLVEx_Handle, $aHit[0], $aHit[1])
        ; Get size of edit box
        Local $aRect = _GUICtrlListView_GetSubItemRect($hGLVEx_Handle, $aHit[0], $aHit[1])
        Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($hGLVEx_Handle, $aHit[1]) - 7
        Local $iEdit_Height = $aRect[3] - $aRect[1]
        ; Get position of ListView within GUI client area
        Local $aPos = WinGetPos($hGLVEx_Handle)
        Local $tPoint = DllStructCreate("int X;int Y")
        DllStructSetData($tPoint, "X", $aPos[0])
        DllStructSetData($tPoint, "Y", $aPos[1])
        _WinAPI_ScreenToClient($hWnd, $tPoint)
        Local $iEdit_X = DllStructGetData($tPoint, "X") + $aRect[0] + 5 + $iDelta_X
        Local $iEdit_Y = DllStructGetData($tPoint, "Y") + $aRect[1] + 2 + $iDelta_Y
        ; Prevent ListView header resize
        ControlDisable($hWnd, "", HWnd(_GUICtrlListView_GetHeader($hGLVEx_Handle)))
        ; Create temporary edit - set keyboard focus and select all text
        $cGLVEx_EditCID = GUICtrlCreateEdit($sItemOrgText, $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height, 0)
        GUICtrlSetState($cGLVEx_EditCID, 256) ; $GUI_FOCUS
        GUICtrlSendMsg($cGLVEx_EditCID, 0xB1, 0, -1) ; $EM_SETSEL
        ; Copy array for manipulation
        $aGLVEx_Array = $aGLVEx_Data[$iArray_Index][2]
        ; Return index flag
        Local $iReturnIndex = -1
        ; Wait for edit to end
        While $fGLVEx_EditFlag
            ; If ENTER pressed
            If _WinAPI_GetAsyncKeyState(0x0D) Then
                ; Set label to edit content
                Local $sItemNewText = GUICtrlRead($cGLVEx_EditCID)
                ; Check edit took place
                If $sItemNewText <> $sItemOrgText Then
                    ; Amend item text
                    _GUICtrlListView_SetItemText($hGLVEx_Handle, $aHit[0], $sItemNewText, $aHit[1])
                    ; Amend array element
                    $aGLVEx_Array[$aHit[0] + 1][$aHit[1]] = $sItemNewText
                    ; Store amended array
                    $aGLVEx_Data[$iArray_Index][2] = $aGLVEx_Array
                    ; Set array to return
                    $iReturnIndex = $iArray_Index
                EndIf
                ExitLoop
            EndIf
            ; If ESC pressed
            If _WinAPI_GetAsyncKeyState(0x1B) Then
                ExitLoop
            EndIf
            ; Save CPU
            Sleep(10)
        WEnd
        ; Delete copied array
        $aGLVEx_Array = 0
        ; Delete temporary edit
        GUICtrlDelete($cGLVEx_EditCID)
        $cGLVEx_EditCID = 0
        ; Reenable ListView header resize
        ControlEnable($hWnd, "", HWnd(_GUICtrlListView_GetHeader($hGLVEx_Handle)))
        ; Clear flag
        $fGLVEx_EditFlag = False

        Return _GUIListViewEx_Return_Array($iReturnIndex)

    EndIf

EndFunc

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_DragRegister
; Description ...: Registers Windows messages needed for the UDF
; Syntax.........: _GUIListViewEx_DragRegister([$fNOTIFY = True, [$fMOUSEMOVE = True, [$fLBUTTONUP = True]]])
; Parameters ....: $fNOTIFY    - True = Register WM_NOTIFY message
;                  $fMOUSEMOVE - True = Register WM_MOUSEMOVE message
;                  $fLBUTTONUP - True = Register WM_LBUTTONUP message
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Modified ......:
; Remarks .......: If other handlers already registered, then call the relevant handler function from within that handler
;                  If no dragging is required, only the WM_NOTIFY handler needs to be registered
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_DragRegister($fNOTIFY = True, $fMOUSEMOVE = True, $fLBUTTONUP = True)

    ; Register required messages
    If $fNOTIFY    Then GUIRegisterMsg(0x004E, "_GUIListViewEx_WM_NOTIFY_Handler")    ; $WM_NOTIFY
    If $fMOUSEMOVE Then GUIRegisterMsg(0x0200, "_GUIListViewEx_WM_MOUSEMOVE_Handler") ; $WM_MOUSEMOVE
    If $fLBUTTONUP Then GUIRegisterMsg(0x0202, "_GUIListViewEx_WM_LBUTTONUP_Handler") ; $WM_LBUTTONUP

EndFunc   ;==>_GUIListViewEx_DragRegister

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_WM_NOTIFY_Handler
; Description ...: Windows message handler for WM_NOTIFY
; Syntax.........: _GUIListViewEx_WM_NOTIFY_Handler
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Modified ......:
; Remarks .......: If a WM_NOTIFY handler already registered, then call this function from within that handler
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_WM_NOTIFY_Handler($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam

    ; Struct = $tagNMHDR and "int Item;int SubItem" from $tagNMLISTVIEW
    Local $tStruct = DllStructCreate("hwnd;uint_ptr;int_ptr;int;int", $lParam)
    If @error Then Return

    ; Check if enabled ListView
    For $iLVIndex = 1 To $aGLVEx_Data[0][0]
        If DllStructGetData($tStruct, 1) = $aGLVEx_Data[$iLVIndex][0] Then
            ExitLoop
        EndIf
    Next
    If $iLVIndex > $aGLVEx_Data[0][0] Then Return ; Not enabled

    Local $iCode = BitAND(DllStructGetData($tStruct, 3), 0xFFFFFFFF)

    Switch $iCode
        Case $LVN_COLUMNCLICK, -2 ; $NM_CLICK

            ; Set values for active ListView
            $aGLVEx_Data[0][1] = $iLVIndex
            $hGLVEx_Handle = $aGLVEx_Data[$iLVIndex][0]
            $hGLVEx_CID = $aGLVEx_Data[$iLVIndex][1]
            ; Copy array for manipulation
            $aGLVEx_Array = $aGLVEx_Data[$iLVIndex][2]

            ; Sort if a column header was clicked and ListView is sortable
            If $iCode = $LVN_COLUMNCLICK And IsArray($aGLVEx_Data[$iLVIndex][4]) Then
                ; Load current ListView sort state array
                Local $aLVSortState = $aGLVEx_Data[$aGLVEx_Data[0][0]][4]
                ; Sort column - get column from from struct
                _GUICtrlListView_SimpleSort($hGLVEx_Handle, $aLVSortState, DllStructGetData($tStruct, 5))
                ; Store new ListView sort state array
                $aGLVEx_Data[$aGLVEx_Data[0][0]][4] = $aLVSortState
                ; Reread listview items into array
                Switch UBound($aGLVEx_Array, 0) ; Check array format
                    Case 1
                        For $j = 1 To $aGLVEx_Array[0]
                            $aGLVEx_Array[$j] = _GUICtrlListView_GetItemTextString($hGLVEx_Handle, $j - 1)
                        Next
                    Case 2
                        Local $iDim2 = UBound($aGLVEx_Array, 2) - 1
                        For $j = 1 To $aGLVEx_Array[0][0]
                            For $k = 0 To $iDim2
                                $aGLVEx_Array[$j][$k] = _GUICtrlListView_GetItemText($hGLVEx_Handle, $j - 1, $k)
                            Next
                        Next
                EndSwitch
                ; Store amended array
                $aGLVEx_Data[$iLVIndex][2] = $aGLVEx_Array
            EndIf

        Case $LVN_BEGINDRAG
            ; Set values for this ListView
            $aGLVEx_Data[0][1] = $iLVIndex
            $hGLVEx_Handle = $aGLVEx_Data[$iLVIndex][0]
            $hGLVEx_CID = $aGLVEx_Data[$iLVIndex][1]
            Local $fImage = $aGLVEx_Data[$iLVIndex][5]
            Local $fCheck = $aGLVEx_Data[$iLVIndex][6]
            ; Copy array for manipulation
            $aGLVEx_Array = $aGLVEx_Data[$iLVIndex][2]

            ; Check if Native or UDF and set focus
            If $hGLVEx_CID Then
                GUICtrlSetState($hGLVEx_CID, 256) ; $GUI_FOCUS
            Else
                _WinAPI_SetFocus($hGLVEx_Handle)
            EndIf

            ; Get dragged item index
            $iGLVExDragged_Index = DllStructGetData($tStruct, 4) ; Item
            ; Set dragged item count
            $iGLVEx_Dragging = 1

            ; Check for selected items
            Local $iIndex = _GUICtrlListView_GetSelectedIndices($hGLVEx_Handle)
            ; Check if item is part of a multiple selection
            If StringInStr($iIndex, $iGLVExDragged_Index) And StringInStr($iIndex, "|") Then
                ; Extract all selected items
                Local $aIndex = StringSplit($iIndex, "|")
                For $i = 1 To $aIndex[0]
                    If $aIndex[$i] = $iGLVExDragged_Index Then ExitLoop
                Next
                ; Now check for consecutive items
                If $i <> 1 Then ; Up
                    For $j = $i - 1 To 1 Step -1
                        ; Consecutive?
                        If $aIndex[$j] <> $aIndex[$j + 1] - 1 Then ExitLoop
                        ; Adjust dragged index to this item
                        $iGLVExDragged_Index -= 1
                        ; Increase number to drag
                        $iGLVEx_Dragging += 1
                    Next
                EndIf
                If $i <> $aIndex[0] Then ; Down
                    For $j = $i + 1 To $aIndex[0]
                        ; Consecutive
                        If $aIndex[$j] <> $aIndex[$j - 1] + 1 Then ExitLoop
                        ; Increase number to drag
                        $iGLVEx_Dragging += 1
                    Next
                EndIf
            Else ; Either no selection or only a single
                ; Set flag
                $iGLVEx_Dragging = 1
            EndIf

            ; Remove all highlighting
            _GUICtrlListView_SetItemSelected($hGLVEx_Handle, -1, False)

            ; Create drag image
            If $fImage Then
                Local $aImageData = _GUICtrlListView_CreateDragImage($hGLVEx_Handle, $iGLVExDragged_Index)
                $hGLVExDragged_Image = $aImageData[0]
                _GUIImageList_BeginDrag($hGLVExDragged_Image, 0, 0, 0)
            EndIf

            ; Create Global array for checkboxes if required
            If $fCheck Then
                Global $aGLVExDragCheck_Array[UBound($aGLVEx_Array)]
                For $i = 1 To UBound($aGLVExDragCheck_Array) - 1
                    $aGLVExDragCheck_Array[$i] = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $i - 1)
                Next
            EndIf

        Case -3 ; $NM_DBLCLK
            ; Only used on UDF ListViews - so confirm no ControlID - and if editable
            If $aGLVEx_Data[$iLVIndex][1] = 0 And $aGLVEx_Data[$iLVIndex][7] = 1 Then
                ; Set values for active ListView
                $aGLVEx_Data[0][1] = $iLVIndex
                $hGLVEx_Handle = $aGLVEx_Data[$iLVIndex][0]
                ; Copy array for manipulation
                $aGLVEx_Array = $aGLVEx_Data[$iLVIndex][2]
                ; Set editing flag
                $fGLVEx_EditFlag = True
            EndIf

    EndSwitch

EndFunc   ;==>_GUIListViewEx_WM_NOTIFY_Handler

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_WM_MOUSEMOVE_Handler
; Description ...: Windows message handler for WM_NOTIFY
; Syntax.........: _GUIListViewEx_WM_MOUSEMOVE_Handler
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Modified ......:
; Remarks .......: If a WM_MOUSEMOVE handler already registered, then call this function from within that handler
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_WM_MOUSEMOVE_Handler($hWnd, $iMsg, $wParam, $lParam)

    #forceref $iMsg, $wParam

    If Not $iGLVEx_Dragging Then Return "GUI_RUNDEFMSG"

    Local $aLV_Pos, $tLVHITTESTINFO, $iCurr_Index

    ; Get current mouse Y coord
    Local $iCurr_Y = BitShift($lParam, 16)

    ; Set insert mark to correct side of items depending on sense of movement when cursor within range
    If $iGLVExInsert_Index <> -1 Then
        If $iGLVExLast_Y = $iCurr_Y Then
            Return "GUI_RUNDEFMSG"
        ElseIf $iGLVExLast_Y > $iCurr_Y Then
            $fGLVEx_Bar_Under = False
            _GUICtrlListView_SetInsertMark($hGLVEx_Handle, $iGLVExInsert_Index, False)
        Else
            $fGLVEx_Bar_Under = True
            _GUICtrlListView_SetInsertMark($hGLVEx_Handle, $iGLVExInsert_Index, True)
        EndIf
    EndIf
    ; Store current Y coord
    $iGLVExLast_Y = $iCurr_Y

    ; Get ListView item under mouse - depends on ListView type
    If $hGLVEx_CID Then
        $aLV_Pos = ControlGetPos($hWnd, "", $hGLVEx_CID)
        $tLVHITTESTINFO = DllStructCreate("int;int;uint;int;int;int")
        ; Force response even if off side of GUI - normal X coord = BitAND($lParam, 0xFFFF) - $aLV_Pos[0]
        DllStructSetData($tLVHITTESTINFO, 1, 1)
        DllStructSetData($tLVHITTESTINFO, 2, $iCurr_Y - $aLV_Pos[1])
        ; Get item under mouse
        $iCurr_Index = GUICtrlSendMsg($hGLVEx_CID, $LVM_HITTEST, 0, DllStructGetPtr($tLVHITTESTINFO))
    Else
        ; Get coords of client area
        Local $tPoint = DllStructCreate("int X;int Y")
        DllStructSetData($tPoint, "X", 0)
        DllStructSetData($tPoint, "Y", 0)
        Local $pPoint = DllStructGetPtr($tPoint)
        DllCall("user32.dll", "bool", "ClientToScreen", "hwnd", $hWnd, "ptr", $pPoint)
        ; Get coords of ListView
        $aLV_Pos = WinGetPos($hGLVEx_Handle)
        Local $iY = $iCurr_Y - $aLV_Pos[1] + DllStructGetData($tPoint, "Y")
        $tLVHITTESTINFO = DllStructCreate("int;int;uint;int;int;int")
        ; Force response even if off side of GUI - normal X coord = BitAND($lParam, 0xFFFF) - $aLV_Pos[0] + DllStructGetData($tPoint, "X")
        DllStructSetData($tLVHITTESTINFO, 1, 1)
        DllStructSetData($tLVHITTESTINFO, 2, $iY)
        Local $pLVHITTESTINFO = DllStructGetPtr($tLVHITTESTINFO)
        ; Get item under mouse
        Local $aRet = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hGLVEx_Handle, "uint", $LVM_HITTEST, "wparam", 0, "lparam", $pLVHITTESTINFO)
        $iCurr_Index = $aRet[0]
    EndIf

    ; If mouse is above or below ListView then scroll ListView
    If $iCurr_Index = -1 Then
        If $fGLVEx_Bar_Under Then
            _GUICtrlListView_Scroll($hGLVEx_Handle, 0, 10)
        Else
            _GUICtrlListView_Scroll($hGLVEx_Handle, 0, -10)
        EndIf
        Sleep(100)
    EndIf

    ; Check if over same item
    If $iGLVExInsert_Index = $iCurr_Index Then Return "GUI_RUNDEFMSG"

    ; Show insert mark on current item
    _GUICtrlListView_SetInsertMark($hGLVEx_Handle, $iCurr_Index, $fGLVEx_Bar_Under)
    ; Store current item
    $iGLVExInsert_Index = $iCurr_Index

EndFunc   ;==>_GUIListViewEx_WM_MOUSEMOVE_Handler

; #FUNCTION# =========================================================================================================
; Name...........: _GUIListViewEx_WM_LBUTTONUP_Handler
; Description ...: Windows message handler for WM_NOTIFY
; Syntax.........: _GUIListViewEx_WM_LBUTTONUP_Handler
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Modified ......:
; Remarks .......: If a WM_LBUTTONUP handler already registered, then call this function from within that handler
; Example........: Yes
;=====================================================================================================================
Func _GUIListViewEx_WM_LBUTTONUP_Handler($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam, $lParam

    If Not $iGLVEx_Dragging Then Return "GUI_RUNDEFMSG"

    ; Get item count
    Local $iMultipleItems = $iGLVEx_Dragging - 1

    ; Reset flag
    $iGLVEx_Dragging = 0

    ; Check mouse within ListView
    If $iGLVExInsert_Index = -1 Then
        ; Clear insert mark
        _GUICtrlListView_SetInsertMark($hGLVEx_Handle, -1, True)
        ; Reset highlight to original items
        For $i = 0 To $iMultipleItems
            _GUIListViewEx_HighLight($iGLVExDragged_Index + $i)
        Next
        Return
    EndIf

    ; Determine position to insert
    If $fGLVEx_Bar_Under Then
        If $iGLVExDragged_Index > $iGLVExInsert_Index Then $iGLVExInsert_Index += 1
    Else
        If $iGLVExDragged_Index < $iGLVExInsert_Index Then $iGLVExInsert_Index -= 1
    EndIf

    ; Clear insert mark
    _GUICtrlListView_SetInsertMark($hGLVEx_Handle, -1, True)

    ; Clear drag image
    If $hGLVExDragged_Image Then
        _GUIImageList_DragLeave($hGLVEx_Handle)
        _GUIImageList_EndDrag()
        _GUIImageList_Destroy($hGLVExDragged_Image)
        $hGLVExDragged_Image = 0
    EndIf

    ; Check not dropping on dragged item(s)
    Switch $iGLVExInsert_Index
        Case $iGLVExDragged_Index To $iGLVExDragged_Index + $iMultipleItems
            ; Reset highlight to original items
            For $i = 0 To $iMultipleItems
                _GUIListViewEx_HighLight($iGLVExDragged_Index + $i)
            Next
            Return
    EndSwitch

    ; Amend array
    ; Get data from dragged element(s)
    If $iMultipleItems Then
        ; Multiple dragged elements
        Switch UBound($aGLVEx_Array, 0) ; Check array format
            Case 1
                Local $aInsertData[$iMultipleItems + 1]
                For $i = 0 To $iMultipleItems
                    $aInsertData[$i] = $aGLVEx_Array[$iGLVExDragged_Index + 1 + $i]
                Next
            Case 2
                Local $aInsertData[$iMultipleItems + 1]
                For $i = 0 To $iMultipleItems
                    Local $aItemData[UBound($aGLVEx_Array, 2)]
                    For $j = 0 To UBound($aGLVEx_Array, 2) - 1
                        $aItemData[$j] = $aGLVEx_Array[$iGLVExDragged_Index + 1][$j]
                    Next
                    $aInsertData[$i] = $aItemData
                Next
        EndSwitch
    Else
        ; Single dragged element
        Switch UBound($aGLVEx_Array, 0) ; Check array format
            Case 1
                Local $aInsertData[1]
                $aInsertData[0] = $aGLVEx_Array[$iGLVExDragged_Index + 1]
            Case 2
                Local $aInsertData[1]
                Local $aItemData[UBound($aGLVEx_Array, 2)]
                For $i = 0 To UBound($aGLVEx_Array, 2) - 1
                    $aItemData[$i] = $aGLVEx_Array[$iGLVExDragged_Index + 1][$i]
                Next
                $aInsertData[0] = $aItemData
        EndSwitch
    EndIf

    ; Copy checkbox data from dragged elements
    If IsArray($aGLVExDragCheck_Array) Then
        If $iMultipleItems Then
            Local $aDragged_Data[$iMultipleItems + 1]
            For $i = 0 To $iMultipleItems
                $aDragged_Data[$i] = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iGLVExDragged_Index + $i)
            Next
        Else
            Local $aDragged_Data[1]
            $aDragged_Data[0] = _GUICtrlListView_GetItemChecked($hGLVEx_Handle, $iGLVExDragged_Index)
        EndIf
    EndIf

    ; Delete dragged element(s) from arrays
    For $i = 0 To $iMultipleItems
        _GUIListViewEx_Array_Delete($aGLVEx_Array, $iGLVExDragged_Index + 1)
        If IsArray($aGLVExDragCheck_Array) Then
            _GUIListViewEx_Array_Delete($aGLVExDragCheck_Array, $iGLVExDragged_Index + 1)
        EndIf
    Next

    ; Amend insert positon for multiple items deleted above
    If $iGLVExDragged_Index < $iGLVExInsert_Index Then
        $iGLVExInsert_Index -= $iMultipleItems
    EndIf
    ; Re-insert dragged element(s) into array
    For $i = $iMultipleItems To 0 Step -1
        _GUIListViewEx_Array_Insert($aGLVEx_Array, $iGLVExInsert_Index + 1, $aInsertData[$i])
        If IsArray($aGLVExDragCheck_Array) Then
            _GUIListViewEx_Array_Insert($aGLVExDragCheck_Array, $iGLVExInsert_Index + 1, $aDragged_Data[$i])
        EndIf
    Next

    ; Amend ListView to match array
    If $iGLVExDragged_Index > $iGLVExInsert_Index Then
        _GUIListViewEx_Data_Change($iGLVExInsert_Index, $iGLVExDragged_Index + $iMultipleItems)
    Else
        _GUIListViewEx_Data_Change($iGLVExDragged_Index, $iGLVExInsert_Index + $iMultipleItems)
    EndIf

    ; Reset checkbox data
    If IsArray($aGLVExDragCheck_Array) Then
        For $i = 1 To UBound($aGLVExDragCheck_Array) - 1
            _GUICtrlListView_SetItemChecked($hGLVEx_Handle, $i - 1, $aGLVExDragCheck_Array[$i])
        Next
        ; Clear array
        $aGLVExDragCheck_Array = 0
    EndIf

    ; Set highlight to inserted item(s)
    For $i = 0 To $iMultipleItems
        _GUIListViewEx_HighLight($iGLVExInsert_Index + $i)
    Next

    ; Store amended array
    $aGLVEx_Data[$aGLVEx_Data[0][1]][2] = $aGLVEx_Array
    ; Delete copied array
    $aGLVEx_Array = 0

EndFunc   ;==>_GUIListViewEx_WM_LBUTTONUP_Handler

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_HighLight($iIndexA, $iIndexB)
; Description ...: Highlights first item and ensures visible while removing hightlight from second in multiple selection ListViews
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================
Func _GUIListViewEx_Highlight($iIndexA, $iIndexB = -1)

    ; Check if Native or UDF and set focus
    If $hGLVEx_CID Then
        GUICtrlSetState($hGLVEx_CID, 256) ; $GUI_FOCUS
    Else
        _WinAPI_SetFocus($hGLVEx_Handle)
    EndIf
    ; Cancel highlight on other item - needed for multisel listviews
    If $iIndexB <> -1 Then _GUICtrlListView_SetItemSelected($hGLVEx_Handle, $iIndexB, False)
    ; Set highlight to inserted item and ensure in view
    _GUICtrlListView_SetItemState($hGLVEx_Handle, $iIndexA, $LVIS_SELECTED, $LVIS_SELECTED)
    _GUICtrlListView_EnsureVisible($hGLVEx_Handle, $iIndexA)

EndFunc   ;==>_GUIListViewEx_HighLight

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Data_Change($iStart, $iEnd)
; Description ...: Resets ListView items within a defined range to the current values in the stored array
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================
Func _GUIListViewEx_Data_Change($iStart, $iEnd)

    Local $sBlanker, $aInsert, $iDim2

    ; Check if Native or UDF
    If $hGLVEx_CID Then
        ; Native ListView
        For $i = $iStart To $iEnd
            ; Get CID of the item
            Local $iCID = _GUICtrlListView_GetItemParam($hGLVEx_Handle, $i)
            ; Check array type
            Switch UBound($aGLVEx_Array, 0)
                Case 1
                    $aInsert = StringSplit($aGLVEx_Array[$i + 1], "|", 2)
                Case 2
                    $iDim2 = UBound($aGLVEx_Array, 2)
                    Local $aInsert[$iDim2]
                    For $j = 0 To $iDim2 - 1
                        $aInsert[$j] = $aGLVEx_Array[$i + 1][$j]
                    Next
            EndSwitch
            ; Insert new data into each column in turn
            $sBlanker = ""
            For $j = 0 To UBound($aInsert) - 1
                GUICtrlSetData($iCID, $sBlanker & $aInsert[$j])
                $sBlanker &= "|"
            Next
        Next
    Else
        ; UDF ListView
        For $i = $iStart To $iEnd
            ; Check if multicolumn
            $iDim2 = UBound($aGLVEx_Array, 2)
            If @error Then
                _GUICtrlListView_SetItemText($hGLVEx_Handle, $i, $aGLVEx_Array[$i + 1])
            Else
                ; For each column - or just once if not multicolumn
                For $j = 0 To $iDim2 - 1
                    ; Set data
                    _GUICtrlListView_SetItemText($hGLVEx_Handle, $i, $aGLVEx_Array[$i + 1][$j], $j)
                Next
            EndIf
        Next
    EndIf

EndFunc   ;==>_GUIListViewEx_Data_Change

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Array_Add
; Description ...: Adds a specified value at the end of an existing 1D or 2D array.
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================
Func _GUIListViewEx_Array_Add(ByRef $avArray, $vAdd = "", $iStart = 0)

    ; Get size of the Array to modify
    Local $iIndex_Max = UBound($avArray)

    ; Get type of array
    Switch UBound($avArray, 0)
        Case 1

            ReDim $avArray[$iIndex_Max + 1]
            $avArray[$iIndex_Max] = $vAdd

        Case 2

        ; Get size of second dimension
        Local $iDim2 = UBound($avArray, 2)

        ; Redim the Array
        ReDim $avArray[$iIndex_Max + 1][$iDim2]

        ; Add new elements
        If IsArray($vAdd) Then
            ; Get size of Insert array
            Local $vAdd_Max = UBound($vAdd)
            For $j = 0 To $iDim2 - 1
                ; If Insert array is too small to fill Array then continue with blanks
                If $j > $vAdd_Max - 1 - $iStart Then
                    $avArray[$iIndex_Max][$j] = ""
                Else
                    $avArray[$iIndex_Max][$j] = $vAdd[$j + $iStart]
                EndIf
            Next
        Else
            ; Fill Array with variable
            For $j = 0 To $iDim2 - 1
                $avArray[$iIndex_Max][$j] = $vAdd
            Next
        EndIf

    EndSwitch

    Return $iIndex_Max

EndFunc   ;==>_GUIListViewEx_Array_Add

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Array_Insert
; Description ...: Adds a value at the specified index of a 1D or 2D array.
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================

Func _GUIListViewEx_Array_Insert(ByRef $avArray, $iIndex, $vInsert)

    ; Get size of the Array to modify
    Local $iIndex_Max = UBound($avArray)

    ; Get type of array
    Switch UBound($avArray, 0)
        Case 1

            ; Resize array
            ReDim $avArray[$iIndex_Max + 1]

            ; Move down all elements below the new index
            For $i = $iIndex_Max To $iIndex + 1 Step -1
                $avArray[$i] = $avArray[$i - 1]
            Next

            ; Add the value in the specified element
            $avArray[$iIndex] = $vInsert
            Return $iIndex_Max

        Case 2

            ; If at end of array
            If $iIndex > $iIndex_Max - 1 Then Return $iIndex_Max = _GUIListViewEx_Array_Add($avArray, $vInsert)

            ; Get size of second dimension
            Local $iDim2 = UBound($avArray, 2)

            ; Redim the Array
            ReDim $avArray[$iIndex_Max + 1][$iDim2]

            ; Move down all elements below the new index
            For $i = $iIndex_Max To $iIndex + 1 Step -1
                For $j = 0 To $iDim2 - 1
                    $avArray[$i][$j] = $avArray[$i - 1][$j]
                Next
            Next

            ; Insert new elements
            If IsArray($vInsert) Then
                ; Get size of Insert array
                Local $vInsert_Max = UBound($vInsert)
                For $j = 0 To $iDim2 - 1
                    ; If Insert array is too small to fill Array then continue with blanks
                    If $j > $vInsert_Max - 1 Then
                        $avArray[$iIndex][$j] = ""
                    Else
                        $avArray[$iIndex][$j] = $vInsert[$j]
                    EndIf
                Next
            Else
                ; Fill Array with variable
                For $j = 0 To $iDim2 - 1
                    $avArray[$iIndex][$j] = $vInsert
                Next
            EndIf

    EndSwitch

    Return $iIndex_Max + 1

EndFunc   ;==>_GUIListViewEx_Array_Insert

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Array_Delete
; Description ...: Deletes a specified index from an existing 1D or 2D array.
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================

Func _GUIListViewEx_Array_Delete(ByRef $avArray, $iIndex)

    ; Get size of the Array to modify
    Local $iIndex_Max = UBound($avArray)

    ; Get type of array
    Switch UBound($avArray, 0)
        Case 1

            ; Move up all elements below the new index
            For $i = $iIndex To $iIndex_Max - 2
                $avArray[$i] = $avArray[$i + 1]
            Next

            ; Redim the Array
            ReDim $avArray[$iIndex_Max - 1]

        Case 2

            ; Get size of second dimension
            Local $iDim2 = UBound($avArray, 2)

            ; Move up all elements below the new index
            For $i = $iIndex To $iIndex_Max - 2
                For $j = 0 To $iDim2 - 1
                    $avArray[$i][$j] = $avArray[$i + 1][$j]
                Next
            Next

            ; Redim the Array
            ReDim $avArray[$iIndex_Max - 1][$iDim2]

    EndSwitch

    Return $iIndex_Max - 1

EndFunc   ;==>_GUIListViewEx_Array_Delete

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _GUIListViewEx_Array_Swap
; Description ...: Swaps specified elements within a 1D or 2D array
; Author ........: Melba23
; Remarks .......:
; ===============================================================================================================================

Func _GUIListViewEx_Array_Swap(ByRef $avArray, $iIndex1, $iIndex2)

    Local $vTemp

    ; Get type of array
    Switch UBound($avArray, 0)
        Case 1
            ; Swap the elements via a temp variable
            $vTemp = $avArray[$iIndex1]
            $avArray[$iIndex1] = $avArray[$iIndex2]
            $avArray[$iIndex2] = $vTemp

        Case 2

            ; Get size of second dimension
            Local $iDim2 = UBound($avArray, 2)
            ; Swap the elements via a temp variable
            For $i = 0 To $iDim2 - 1
                $vTemp = $avArray[$iIndex1][$i]
                $avArray[$iIndex1][$i] = $avArray[$iIndex2][$i]
                $avArray[$iIndex2][$i] = $vTemp
            Next
    EndSwitch

    Return 0

EndFunc   ;==>_GUIListViewEx_Array_Swap

Any comment welcomed (and from anyone else who would like to try it). :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

If you want the items in the listview to be sortable, you would need to modify the _GUICtrlListview_AddItem line in your _GUIListViewEx_Insert function to allow for the 5th parameter to be passed to the _GUICtrlListview_AddItem function.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

  • Moderators

BrewManNH,

I am afraid I do not understand your comment. When I run the script the columns are sortable as they are - so why do I need the $iParam parameter? Can you provide me with a scenario in which a sort on the ListView in that script fails? :huh:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Here are 4 examples using _GUICtrlListview_RegisterSort with and without the 5th parameter set. I created 4 of them because I wanted to show that it affects sorting using both the native AU3 ListView and the UDF created ListView.

#include <StructureConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <GUIListview.au3>
Global $lv
Example1()
Example2()
Example3()
Example4()
; ********************************************************
; Example 1 - Listview items created without 5th parameter
; ********************************************************
Func Example1()
    Local $lv, $msg

    GUICreate("Without 5th parameter set", 300, 200)

    $lv = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180)
    _GUICtrlListView_RegisterSortCallBack(-1) ; Register the function "SortLV" for the sorting callback

    _GUICtrlListView_AddItem($lv, "ABC")
    _GUICtrlListView_AddSubItem($lv, 0, "666", 1)
    _GUICtrlListView_AddSubItem($lv, 0, "10.05.2004", 2)
    _GUICtrlListView_AddItem($lv, "DEF")
    _GUICtrlListView_AddSubItem($lv, 1, "444", 1)
    _GUICtrlListView_AddSubItem($lv, 1, "11.05.2005", 2)
    _GUICtrlListView_AddItem($lv, "CDE")
    _GUICtrlListView_AddSubItem($lv, 2, "444", 1)
    _GUICtrlListView_AddSubItem($lv, 2, "12.05.2004", 2)

    GUISetState()

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $lv
                $bSet = 0
                $nCurCol = GUICtrlGetState($lv)
                _GUICtrlListView_SortItems($lv, $nCurCol)
        EndSwitch
    WEnd
    _GUICtrlListView_UnRegisterSortCallBack($lv)
    GUIDelete()
EndFunc   ;==>Example1


; *******************************************************
; Example 2 - Listview items created with 5th parameter
; *******************************************************
Func Example2()
    Local $lv, $msg

    GUICreate("With 5th parameter set", 300, 200)

    $lv = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180)
    _GUICtrlListView_RegisterSortCallBack(-1) ; Register the function "SortLV" for the sorting callback

    _GUICtrlListView_AddItem($lv, "ABC", -1, 1000)
    _GUICtrlListView_AddSubItem($lv, 0, "666", 1)
    _GUICtrlListView_AddSubItem($lv, 0, "10.05.2004", 2)
    _GUICtrlListView_AddItem($lv, "DEF")
    _GUICtrlListView_AddSubItem($lv, 1, "444", 1)
    _GUICtrlListView_AddSubItem($lv, 1, "11.05.2005", 2)
    _GUICtrlListView_AddItem($lv, "CDE")
    _GUICtrlListView_AddSubItem($lv, 2, "444", 1)
    _GUICtrlListView_AddSubItem($lv, 2, "12.05.2004", 2)

    GUISetState()

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $lv
                $bSet = 0
                $nCurCol = GUICtrlGetState($lv)
                _GUICtrlListView_SortItems($lv, $nCurCol)
        EndSwitch
    WEnd
    _GUICtrlListView_UnRegisterSortCallBack($lv)
    GUIDelete()
EndFunc   ;==>Example2

; ********************************************************
; Example 3 - Listview items created without 5th parameter, using UDF created ListView
; ********************************************************
Func Example3()
    Local $msg

    Local $hGUI = GUICreate("Without 5th parameter set", 300, 200)

    $lv = _GUICtrlListView_Create($hGUI, "Column1|Col2|Col3", 10, 10, 280, 180)
    _GUICtrlListView_RegisterSortCallBack($lv) ; Register the function "SortLV" for the sorting callback
    GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")
    _GUICtrlListView_AddItem($lv, "ABC")
    _GUICtrlListView_AddSubItem($lv, 0, "666", 1)
    _GUICtrlListView_AddSubItem($lv, 0, "10.05.2004", 2)
    _GUICtrlListView_AddItem($lv, "DEF")
    _GUICtrlListView_AddSubItem($lv, 1, "444", 1)
    _GUICtrlListView_AddSubItem($lv, 1, "11.05.2005", 2)
    _GUICtrlListView_AddItem($lv, "CDE")
    _GUICtrlListView_AddSubItem($lv, 2, "444", 1)
    _GUICtrlListView_AddSubItem($lv, 2, "12.05.2004", 2)

    GUISetState()

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $lv
                $bSet = 0
                $nCurCol = GUICtrlGetState($lv)
                ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $nCurCol = ' & $nCurCol & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
                _GUICtrlListView_SortItems($lv, $nCurCol)
        EndSwitch
    WEnd
    _GUICtrlListView_UnRegisterSortCallBack($lv)
    GUIDelete()
EndFunc   ;==>Example3
; *******************************************************
; Example 2 - Listview items created with 5th parameter, using UDF created ListView
; *******************************************************
Func Example4()
        Local $msg

    Local $hGUI = GUICreate("With 5th parameter set", 300, 200)

    $lv = _GUICtrlListView_Create($hGUI, "Column1|Col2|Col3", 10, 10, 280, 180)
    _GUICtrlListView_RegisterSortCallBack($lv) ; Register the function "SortLV" for the sorting callback
    GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")
    _GUICtrlListView_AddItem($lv, "ABC", -1, 1000)
    _GUICtrlListView_AddSubItem($lv, 0, "666", 1)
    _GUICtrlListView_AddSubItem($lv, 0, "10.05.2004", 2)
    _GUICtrlListView_AddItem($lv, "DEF")
    _GUICtrlListView_AddSubItem($lv, 1, "444", 1)
    _GUICtrlListView_AddSubItem($lv, 1, "11.05.2005", 2)
    _GUICtrlListView_AddItem($lv, "CDE")
    _GUICtrlListView_AddSubItem($lv, 2, "444", 1)
    _GUICtrlListView_AddSubItem($lv, 2, "12.05.2004", 2)

    GUISetState()

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $lv
                $bSet = 0
                $nCurCol = GUICtrlGetState($lv)
                ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $nCurCol = ' & $nCurCol & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
                _GUICtrlListView_SortItems($lv, $nCurCol)
        EndSwitch
    WEnd
    _GUICtrlListView_UnRegisterSortCallBack($lv)
    GUIDelete()
EndFunc
Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iCode, $tNMHDR, $hWndListView, $hWndListView2

    $hWndListView = $lv
    If Not IsHWnd($lv) Then $hWndListView = GUICtrlGetHandle($lv)

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

    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_COLUMNCLICK ; A column was clicked
                    Local $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)

                    ; Kick off the sort callback
                    _GUICtrlListView_SortItems($hWndFrom, DllStructGetData($tInfo, "SubItem"))
                    ; No return value
            EndSwitch
    EndSwitch
    Return $__LISTVIEWCONSTANT_GUI_RUNDEFMSG
EndFunc   ;==>_WM_NOTIFY

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

  • Moderators

BrewmanNH,

I wondered if that was the reason behind your comment - but as I only use SimpleSort on a single column at a time in the UDF, and not the more complex SortCallBack, it is not necessary to use the additional parameter to enable sorting to take place. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Does that mean that using your UDF, even with that change, you can't use another sorting routine?

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

  • Moderators

BrewManNH,

I have no idea as I have never tried. The whole idea behind the UDF (like many of the others I have written) was to simplify a relatively complex control (ListViews in this case) for the less-experienced user, so I decided to go for the simpler solution internally. :)

I imagine that if you use the UDF and do not ask it to do the sort internally you could then use the SortCallBack code. But give me a moment and I will try it out. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

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...