Sign in to follow this  
Followers 0
StungStang

ListView Item

21 posts in this topic

#1 ·  Posted (edited)

Hi to all, my question is not about an issue...but i want to know if there are a metods to improve the Adding Item to listview.

I've about 7000 item to add in a listview...but it take about 30 second!

This is an example :

_GUICtrlListView_BeginUpdate($hListView)
    _GUICtrlListView_DeleteAllItems($hListView)
    For $i = 1 to 7000
        GUICtrlCreateListViewItem($Line[$i], $ListView)
    next
    _GUICtrlListView_EndUpdate($ListView)

It's very slow...there are improvment for that?

Hi!

Edited by StungStang

Share this post


Link to post
Share on other sites



The only thing I can think of is of is to use a virtual listview (read through the MSDN page here). It looks as though you already have the lines in an array so it should be easy

Share this post


Link to post
Share on other sites

Yes i have already the lines in an array...

I see the MSDN page...but sincerly i can't understand too much...al the example is not written in autoit (ofc), it's hard to understand...

Can you help me with it?

hi!

Share this post


Link to post
Share on other sites

Up :)

Share this post


Link to post
Share on other sites

Yes i have already the lines in an array...

Then you can use _GUICtrlListView_AddArray. This is the fastest way.

Share this post


Link to post
Share on other sites

perhabs: _GUICtrlListView_AddArray

do what you want.

best regards, Reinhard

Share this post


Link to post
Share on other sites

I'm not sure how much data is in each line, but I added a list of 7000 dummy lines (each line held approximately 26 characters) to a Listview from an array in about .06 seconds using your code above. I can't see how you are getting 30 seconds to do the same thing unless your computer is extremely slow. Also, using _GUICtrlListView_AddArray it took about 10 times LONGER than looping through the array using the exact same data to create the listview.


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

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Im using a pentium 4 with 2 Gb of ram with win xp pro sp3, not too much slow...

My listview iteam line is formed like that :

Radio Name|Streaming Link|Web Site|Genre|Country

I grab the info from a sql database...the search time is about 3 second...stamp time is about 30 second!

This is the piece of code that create listview item

GUICtrlListView_BeginUpdate($hListView)
    _GUICtrlListView_DeleteAllItems($hListView)
    Local $hQuery, $aRow, $aNames
    _SQLite_Query(-1, "SELECT * FROM Data WHERE Radio LIKE '%" & $sText & "%';", $hQuery)
    While _SQLite_FetchData($hQuery, $aRow, False, False) = $SQLITE_OK
        $Line = $aRow[0] & "|" & $aRow[1] & "|" & $aRow[2] & "|" & $aRow[3] & "|" & $aRow[4]
        GUICtrlCreateListViewItem($Line, $ListView)
    WEnd
    _GUICtrlListView_EndUpdate($hListView)

How you do that in 6 second?...What kind of pc you have?

Hi :)

Edited by StungStang

Share this post


Link to post
Share on other sites

That's hardly the same code as you posted in the first post.

Here you're pulling the information from a SQL database, manipulating that information to format it the way you wanted, and then adding it to the listview. As I don't know much if anything about SQL queries, I don't know what information you're getting. It's not the code adding the information to the LV that's taking so much time, it's the data manipulation. Because if you had a 7000 line array with all of the information already in it, it would take very little time to create the LV from it.


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

Share this post


Link to post
Share on other sites

Im getting an info like that :

Radiname|Streaminglink|Website|Genre|Country

To grab the info the application take about 3 second...to populate the listview it take 28 second!

Too much... :/

Have you some trick?...What about this "virtual listview"?

Hi! :)

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

It's look like an faster array display function...

I have to use a listview...with that i can read the listview selected item, that contain the info for reproducing my preferite radio with bass.dll :)

Thank's again for your help :)

Edited by StungStang

Share this post


Link to post
Share on other sites

It is a faster _ArrayDisplay function (which uses a listview btw), but it makes it faster by using a virtual listview. The source code is rather cryptic thanks to the person deciding he could make it faster by using values rather than constants, so it will take some work. Unfortunately for you I'm writing exams soon, so I don't have much time to write out a full example for you. However, you now have a method you can try to implement which already has an example (albeit not that nice to look at) in AutoIt, so I think you could at least make a considerable start in getting some code together.

Take a few days and I would try and tidy up the faster _ArrayDisplay, you can then take that and change it to better suite your needs. Once you have a basic example that is legible then the solution will either become clear or you will be able to get more specific help from us.

On an interesting aside (don't even think about this yet) for future reference, once you have the virtual list view sorted then look up the notification codes in place to deal with cache. It may be you can speed up loading of the data from the database (a perfect example of when caching like this is suitable) so that you only load items you need. I wouldn't worry about that until you have the listview working though.

Share this post


Link to post
Share on other sites

Hello,

try _SQLite_GetTable2d instead of _SQLite_Query:

Local $aResult, $iRows, $iColumns
_GUICtrlListView_BeginUpdate($hListView)
_GUICtrlListView_DeleteAllItems($hListView)
Local $hQuery, $aRow, $aNames
$iRval = _SQLite_GetTable2d(-1, "SELECT * FROM Data WHERE Radio LIKE '%" & $sText & "%';", $aResult, $iRows, $iColumns)
_ArrayDelete($aResult,0) ;delete columnnames
If $iRval = $SQLITE_OK Then _GUICtrlListView_AddArray($aResult)
_GUICtrlListView_EndUpdate($hListView)

mfg autoBert

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Hello,

try _SQLite_GetTable2d instead of _SQLite_Query:

Local $aResult, $iRows, $iColumns
_GUICtrlListView_BeginUpdate($hListView)
_GUICtrlListView_DeleteAllItems($hListView)
Local $hQuery, $aRow, $aNames
$iRval = _SQLite_GetTable2d(-1, "SELECT * FROM Data WHERE Radio LIKE '%" & $sText & "%';", $aResult, $iRows, $iColumns)
_ArrayDelete($aResult,0) ;delete columnnames
If $iRval = $SQLITE_OK Then _GUICtrlListView_AddArray($aResult)
_GUICtrlListView_EndUpdate($hListView)

mfg autoBert

Good improvement...passed to 30 second in 9 second...other trick or is the best that can do ?...

What about a virtual listview?...Anyone have an example ?

Hi

Edited by StungStang

Share this post


Link to post
Share on other sites

You have an example. The faster version of _ArrayDisplay uses a virtual listview.

Share this post


Link to post
Share on other sites

Good improvement...passed to 30 second in 9 second...

The better result (21 second) is ca. 80% the faster way to get the data in SQLite so i cann't believe

To grab the info the application take about 3 second...to populate the listview it take 28 second!

Too much... :/

mfg autoBert

Share this post


Link to post
Share on other sites

You have an example. The faster version of _ArrayDisplay uses a virtual listview.

It's true...but sincerly i dont know how to create a virtual listview :) No too much example here...:)

Share this post


Link to post
Share on other sites

Considering the fact that you can populate a listview with 7000 rows in WELL under .1 second by looping through an array, just exactly how much faster do you need it to be?


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

Share this post


Link to post
Share on other sites

Ok. This is the last time I'm going to point you to the same piece of code.

The main file for the faster _ArrayDisplay took me 2mins to edit to get the following, and even most of that was just to take out an include so you'd have one file you could copy, paste and run.

Bear in mind that this code is designed to suite all kinds of arrays. You could make it faster by making certain assumptions, like the dimensions of the array, and how many columns you need, that you don't want to sort... There are so many ways you can get a bit more speed out of this.

And then there is what I said about caching and the database in an earlier post. Thats the right way to do this.

; _ArrayDisplayVS.au3
;~ #AutoIt3Wrapper_AU3Check_Parameters= -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiListView.au3>
#include <GuiEdit.au3>
#include <string.au3>
;#include <_ArrayDisplaySort.au3>
;~ #include <StringSplit.au3>
;~ #include <_ArraySortClib2SetV.au3>
Global $iEndVPrev, $iToVPrev, $aArrayIndexV[1], $iStartcolV, $slider1V, $iStartVPrev, $iFromVPrev
Global $tTextBufferV, $iCaseV, $avArrayV, $s_LISTVIEWSortOrderV, $iUBoundV, $iColV, $sSeparatorV, $imaskV, $iNumRowsV;, $iTimerProgressV
Global $vDescendingV[1], $arArAscV[1], $i_LISTVIEWPrevcolumnV = -1, $ar_LISTVIEWArrayV[1], $hGUI, $hListView, $iStartV, $iEndV;, $arArDescV2V[1]
Global $maxlenV, $tTextPtrV, $iNotSortedV, $iToV, $iFromV, $avTempV[1][1], $iColumnCountV, $iColumnToDisplayV, $iRowV, $tNMLVDISPINFOV
Global $iTimeSPlitDataV, $iTimeSetDataV, $iTimeStartDataV, $iTimeStartCacheV, $iTimeRemCacheV, $iTimeStartMaskV, $iColWidth
Global Const $WM_HSCROLL = 0x0114
Global $hMsvcrtV, $sStrCmpV, $tFloatCmpV, $pCmpV, $tIndexerV, $tagSourceV, $tSourceV, $pSourceV, $procStrCmpV


;==============================================================================================================================

Local $aItems[7000]
For $i = 0 To 6999
    $aItems[$i] = "Item: " & $i
Next

_ArrayDisplaySortV($aItems)

;==============================================================================================================================


Func _ArrayDisplaySortV(Const ByRef $avArrayVF, $sTitle = "Array: ListView Display", $iItemLimit = 0, $iOptions = 0, $sSeparatorVF = "", $sReplace = "")
    #Region const
    Local Const $_ARRAYUUCONSTANT_GUI_EVENT_CLOSE = -3
    Local Const $_ARRAYUUCONSTANT_LVM_GETITEMCOUNT = (0x1000 + 4)
    Local Const $_ARRAYUUCONSTANT_LVM_GETITEMSTATE = (0x1000 + 44)
    Local Const $LVM_SETCOLUMNWIDTHU = (0x1000 + 30)
    Local Const $LVSCWU_AUTOSIZE = -1
    Local Const $LVSCWU_AUTOSIZE_USEHEADER = -2
    ;===========================================added rjc
    ;;virtual lv style
    Local Const $LVS_OWNERDATA = 0x1000

    Local Const $_ARRAYCONSTANT_GUI_DOCKBORDERS = 0x66
    Local Const $_ARRAYCONSTANT_GUI_DOCKBOTTOM = 0x40
    Local Const $_ARRAYCONSTANT_GUI_DOCKHEIGHT = 0x0200
    Local Const $_ARRAYCONSTANT_GUI_DOCKLEFT = 0x2
    Local Const $_ARRAYCONSTANT_GUI_DOCKRIGHT = 0x4
    Local Const $_ARRAYCONSTANT_GUI_EVENT_CLOSE = -3
    Local Const $_ARRAYCONSTANT_LVIF_PARAM = 0x4
    Local Const $_ARRAYCONSTANT_LVIF_TEXT = 0x1
    Local Const $_ARRAYCONSTANT_LVM_GETITEMCOUNT = (0x1000 + 4)
    Local Const $_ARRAYCONSTANT_LVM_GETITEMSTATE = (0x1000 + 44)
    Local Const $_ARRAYCONSTANT_LVM_INSERTITEMA = (0x1000 + 7)
    Local Const $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE = (0x1000 + 54)
    Local Const $_ARRAYCONSTANT_LVM_SETITEMA = (0x1000 + 6)
    Local Const $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT = 0x20
    Local Const $_ARRAYCONSTANT_LVS_EX_GRIDLINES = 0x1
    Local Const $_ARRAYCONSTANT_LVS_SHOWSELALWAYS = 0x8
    Local Const $_ARRAYCONSTANT_WS_EX_CLIENTEDGE = 0x0200
    Local Const $_ARRAYCONSTANT_WS_MAXIMIZEBOX = 0x00010000
    Local Const $_ARRAYCONSTANT_WS_MINIMIZEBOX = 0x00020000
    Local Const $_ARRAYCONSTANT_WS_SIZEBOX = 0x00040000
    Local Const $_ARRAYCONSTANT_LVN_GETDISPINFO = -177
    Local Const $_ARRAYCONSTANT_tagLVITEM = "int Mask;int Item;int SubItem;int State;int StateMask;ptr Text;int TextMax;int Image;int Param;int Indent;int GroupID;int Columns;ptr pColumns"
    #EndRegion const
    #Region first
    Local $sTextBuff = "char[261]"
    If Execute("@Unicode") Then $sTextBuff = "w" & $sTextBuff
    $tTextBufferV = DllStructCreate($sTextBuff)
    $maxlenV = DllStructGetSize($tTextBufferV)
    If Execute("@Unicode") Then $maxlenV = $maxlenV / 2
    $tTextPtrV = DllStructGetPtr($tTextBufferV)
    Local $sBlank = ""
    Local $sCol0 = "", $vTmp, $iNumItems, $iBuffer = 2048000;,64;;$sSeparatorV3, $sSeparatorV2 = $sSeparatorV,
    Local $timerstamp1 = TimerInit(), $aItem, $i_ColWidth, $i_OrderColumn;, $timerstampprep = TimerInit()
    Local $iTranspose = BitAND($iOptions, 1), $iSort = BitAND($iOptions, 2)
;~  ReDim $ar_LISTVIEWArrayV[4000]
    $iCaseV = BitAND($iOptions, 4)
    $sSeparatorV = $sSeparatorVF
    $iDelimited = BitAND($iOptions, 8)
    Local $iReplaceTrue = BitAND($iOptions, 16)
    Local $iColUnLimited = BitAND($iOptions, 32) ; so 32 sets unlimited cols in Virtual
    If Not IsArray($avArrayVF) And IsString($avArrayVF) Then
        $avArrayV = StringSplit(StringStripCR($avArrayVF), @LF)
;~      $iDelimited = 1
    Else
        $avArrayV = $avArrayVF
    EndIf
    If Not IsArray($avArrayV) Then Return SetError(1, 0, 0)
    ; Dimension checking
    Local $iDimension = UBound($avArrayV, 0), $iSubItems = UBound($avArrayV, 2), $arTitle[1], $sTempHeader = 'Row' ;,
    $iUBoundV = UBound($avArrayV, 1)
    If $iDimension > 2 Then Return SetError(2, 0, 0)
    If $iDelimited And $iDimension > 1 Then $iDelimited = 0

    ;===========================================added rjc
    $arTitle = StringSplit($sTitle, "|")
    If (UBound($arTitle) > 2 Or $iDelimited) And $iDimension = 1 Then
        $iSubItems = UBound($arTitle)
        $iDelimited = 1
        $ar_LISTVIEWArrayV = $avArrayV
    EndIf

    ; Separator handling
    If $iDelimited Then
        $iTranspose = 0
        Local $arSeps = StringSplit(",|;", "")
        $iSort = 1
        If $sSeparatorVF = "" Then
            For $i = 1 To UBound($arSeps) - 1
                If StringInStr($avArrayV[0] & $avArrayV[1] & $avArrayV[UBound($avArrayV) - 1], $arSeps[$i]) Then
                    $sSeparatorV = $arSeps[$i]
                    ExitLoop
                EndIf
            Next
        EndIf
        If $iDelimited And $sSeparatorV <> "" Then $sReplace = $sSeparatorV
    EndIf
    If $iSort Then
        If $sSeparatorV = "" Then $sSeparatorV = ","
;~      $sBlank = " "
;~      $sSeparatorV2 = $sBlank & $sSeparatorV
        $sReplace = $sSeparatorV
    EndIf
    If $sSeparatorV = "" Then
        $sSeparatorV = Chr(1)
        If $sReplace == "" Then $sReplace = Chr(1); Then $chr = 1
    EndIf
    If $sReplace == "" Then $sReplace = "&"

    ;===========================================added rjc
    If $sTitle = -1 Or $sTitle = "" Then $sTitle = "ListView array 1D and 2D Display"
    If StringInStr($sTitle, "|") Then; then check if there are header cols too;
        $arTitle = StringSplit($sTitle, "|")
        $sTitle = StringReplace($arTitle[1], $sSeparatorV, $sReplace, 0, 1);$arTitle[1]
        If $arTitle[2] = "" Then $sCol0 = "col 0"
        $sTempHeader &= $sSeparatorV & StringReplace($arTitle[2], $sSeparatorV, $sReplace, 0, 1) & $sCol0;$arTitle[2]
    Else
        $sTempHeader &= $sSeparatorV & "Col 0"
    EndIf

    ; Separator handling
    If $sSeparatorV = "" Then
        $sSeparatorV = Chr(1)
        If $sReplace == "" Then $sReplace = Chr(1); Then $chr = 1
    EndIf
    If $sReplace == "" Then $sReplace = "&"

    ;===========================================added rjc
    If $sSeparatorV <> $sReplace Or $iReplaceTrue Then
        ;ConsoleWrite("$iReplaceTrue=" & $iReplaceTrue & @LF)
;~      ConsoleWrite("$sSeparatorV=" & $sSeparatorV & @LF)
        ;ConsoleWrite("==================================$sReplace=" & $sReplace & @LF)
        If $iDimension = 2 Then
            ReDim $avArrayV[$iUBoundV][$iSubItems]
            For $i = 0 To $iUBoundV - 1
                For $j = 0 To $iSubItems - 1
                    $avArrayV[$i][$j] = StringReplace($avArrayV[$i][$j], $sSeparatorV, $sReplace, 0, 1);replace seaparator
                Next
            Next
        ElseIf $iDimension = 1 Then
            ReDim $avArrayV[$iUBoundV]
            For $i = 0 To $iUBoundV - 1
                $avArrayV[$i] = StringReplace($avArrayV[$i], $sSeparatorV, $sReplace, 0, 1) ;replace seaparator
            Next
        EndIf
    Else
;~      $avArrayV = $avArrayVF
        If $iDelimited Then
            $iSubItems = UBound($arTitle) - 2
            $iDelimited = 1
;~          Local $ar_LISTVIEWArrayV = $avArrayV
;~          For $i = 0 To $iUBoundV - 1
;~              $vTmp = StringLen($avArrayV[$i])
;~              If $vTmp > $iBuffer Then $iBuffer = $vTmp
;~          Next
        EndIf
    EndIf
    ReDim $vDescendingV[$iSubItems + 2]
    ;ConsoleWrite("$iSubItems=" & $iSubItems & @LF)
;~  ;===========================================added rjc

    If $iDelimited And $iTranspose = 1 Then
        $iTranspose = 0
        $sTitle = "** WARNING ** no transpose for delimited string array: " & $sTitle
    EndIf

    ; Hard limits
    Local $iLVIAddUDFThreshold = 4000, $iColVLimit, $iWidth = @DesktopWidth * 2 / 3, $iHeight = @DesktopHeight * 2 / 3;, $sSeparatorV = $sBlank & $sSeparatorV, $sSeparatorV3
    If $iItemLimit > 40 Then $iLVIAddUDFThreshold = $iItemLimit
    $iColVLimit = $iLVIAddUDFThreshold
;~  If Not $iColUnLimited Then $iColVLimit = 5
;~  $iColVLimit = 5
    If $iItemLimit = 1 Or $iItemLimit < 0 Or $iItemLimit = Default Then $iItemLimit = $iLVIAddUDFThreshold

    ; Declare/define variables
    Local $sHeader ;= "Row" ;, $avArrayV[1];, $ar_LISTVIEWArrayV$i, $j,  $arSelItems,

    ; Swap dimensions if transposing
    If $iTranspose Then
        Local $iTmp = $iUBoundV
        $iUBoundV = $iSubItems
        $iSubItems = $iTmp
    EndIf
    ; Set limits for dimensions
    If Not $iUBoundV Then $iUBoundV = 1
    If Not $iSubItems Then $iSubItems = 1
    ;===========================================added rjc
    If $iSubItems > $iColVLimit Then
        $iSubItems = $iColVLimit
        $sTitle = "** WARNING ** $iColVLimit maximum 4000: " & $sTitle
    EndIf

    ;===========================================added rjc
    If $iItemLimit < 1 Then $iItemLimit = $iUBoundV
    If $iUBoundV > $iItemLimit Then $iUBoundV = $iItemLimit
    ;===========================================added ult
    If $iLVIAddUDFThreshold > $iUBoundV - 1 Then $iLVIAddUDFThreshold = $iUBoundV - 1
    ;===========================================added ult

    ; Convert array into text for listview
    ReDim $ar_LISTVIEWArrayV[$iUBoundV]
    Local $iArrayType = $iDimension + 2 * $iTranspose - 1, $sTxt;, $iTemp=1;, $sExec1 = '"', $sExec2 = '"',$avArrayVText[$iUBoundV + 1]

    ; Set header up;; make LV header
    ;===========================================added rjc

    StringReplace($ar_LISTVIEWArrayV[UBound($ar_LISTVIEWArrayV) - 1], $sSeparatorV, $sSeparatorV)
    Local $FirstPipes = @extended, $uboundary = $iSubItems - 1, $iMaxPipes = $FirstPipes, $sStrRep
    ;ConsoleWrite("$iMaxPipes=" & $iMaxPipes & @LF)
    If $iDelimited Then
        $uboundary = $iMaxPipes
        $iSubItems = $uboundary + 1
        $avArrayV = $ar_LISTVIEWArrayV
        $avArrayV[0] = $ar_LISTVIEWArrayV[0]
        ReDim $arArAscV[$iSubItems + 1]
    Else
        ReDim $arArAscV[2] ;for 1D
        If $iDimension = 2 Then ReDim $arArAscV[UBound($avArrayV, 2) + 1]
    EndIf
    ;===========================================added rjc
    If Not $iDelimited And $iDimension = 1 And Not $iTranspose And Not $iSort Then
        $uboundary = 0
    EndIf
    If $uboundary > $iColVLimit - 1 Then $uboundary = $iColVLimit - 1
    If $uboundary > 4 Then $uboundary = 4
    For $i = 1 To $uboundary
        If $i < UBound($arTitle) - 2 Then
            $sTempHeader &= $sSeparatorV & StringReplace($arTitle[$i + 2], $sSeparatorV, $sBlank & $sReplace, 0, 1);arTitle[$i + 2]
        Else
            $sTempHeader &= $sSeparatorV & "Col " & $i
        EndIf
    Next
    ; Set header up
    If $iSort Then $sHeader = "Row" & $sSeparatorV & $sHeader

    $sHeader = $sTempHeader & $sBlank
    Local $iOnEventMode = Opt("GUIOnEventMode", 0), $sDataSeparatorChar = Opt("GUIDataSeparatorChar", $sSeparatorV)
    ;ConsoleWrite("$sHeader=" & $sHeader & @LF)
;~  If $iColVLimit > 5 Then $iColVLimit = 5
;~  If ($iSubItems > 5 And Not $iColUnLimited) Or $iDelimited Then ;10 Then
;~      $iSubItems = 5
;~      _ArrayDisplaySort($avArrayVF, $sTitle & $sHeader, $iItemLimit, $iOptions, $sSeparatorV, $sReplace)
;~      Return
;~  EndIf
    ;===========================================
    #EndRegion first
    #Region second
    Local $iHt = 30
    If $iSubItems <= 5 Then $iHt = 0
    ; Set interface up
    $hGUI = GUICreate($sTitle, $iWidth, $iHeight + $iHt, Default, Default, BitOR($_ARRAYCONSTANT_WS_SIZEBOX, $_ARRAYCONSTANT_WS_MINIMIZEBOX, $_ARRAYCONSTANT_WS_MAXIMIZEBOX))
    Local $aiGUISize = WinGetClientSize($hGUI), $iGUIwidth = $aiGUISize[0]
    $hListView = GUICtrlCreateListView($sHeader, 0, 0, $aiGUISize[0], $aiGUISize[1] - 26 - 2 * $iHt, $_ARRAYCONSTANT_LVS_SHOWSELALWAYS + $LVS_OWNERDATA)
    Local $hCopy = GUICtrlCreateButton("Copy Selected", 3, $aiGUISize[1] - 23, 100, 20)
    Local $hClose = GUICtrlCreateButton("Close", 200, $aiGUISize[1] - 23, 100, 20)
;~  Local $aiGUISize = WinGetClientSize($hGUI), $iGUIwidth = $aiGUISize[0]
    $iColWidth = $aiGUISize[0] / 9 ;1280,@DesktopWidth
;~  Local $hRefresh = GUICtrlCreateButton("Refresh", 400, $aiGUISize[1] - 23, 100, 20)
    ;ConsoleWrite("$iSubItems=" & $iSubItems & @LF)
    If $iSubItems > 5 Then
        $slider1V = GUICtrlCreateSlider(3, $aiGUISize[1] - 23 - 30, $aiGUISize[0] - 6, 40)
        GUICtrlSetLimit(-1, UBound($avArrayV, 2) - 5, 0) ; change min/max value
    EndIf

    GUICtrlSetResizing($hListView, $_ARRAYCONSTANT_GUI_DOCKBORDERS)
;~  GUICtrlSetResizing($slider1V, $_ARRAYCONSTANT_GUI_DOCKBORDERS)
;~  GUICtrlSetResizing($hCopy, $_ARRAYCONSTANT_GUI_DOCKBORDERS)
;~  GUICtrlSetResizing($hClose, $_ARRAYCONSTANT_GUI_DOCKBORDERS)
    GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_GRIDLINES, $_ARRAYCONSTANT_LVS_EX_GRIDLINES)
    GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT)
    GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE)
    GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_DOUBLEBUFFER)
    ; ================================================================================================================
    For $i = 0 To $iColVLimit ;;fix columns width
        GUICtrlSendMsg($hListView, 0x101E, $i, $iColWidth) ;;LVM_SETCOLUMNWIDTH = 0x101E
    Next
    ;===========================================added rjc         ; ensure column width narrow enough to avoid crash with many columns
    GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTHU, $iSubItems, $LVSCWU_AUTOSIZE_USEHEADER)
    ; ================================================================================================================
;~      ConsoleWrite("$iUBoundV=" &$iUBoundV& @LF)
    GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, $iUBoundV, 0) ;;set total item count - necessary for virtual lv
;~  GUIRegisterMsg($WM_HSCROLL, "WM_HVSCROLL")
    Local $wProcNew
    If $iDimension = 1 And Not $iDelimited Then
        $wProcNew = DllCallbackRegister("_ArrayUDF_WM_NOTIFYSort1D", "ptr", "hwnd;uint;long;ptr") ;;register new window proc
        ;ConsoleWrite("will sort with _ArrayUDF_WM_NOTIFYSort1D " & @LF)
    ElseIf $iDimension = 1 Then
        $wProcNew = DllCallbackRegister("_ArrayUDF_WM_NOTIFYSort2", "ptr", "hwnd;uint;long;ptr") ;;register new window proc
        ;ConsoleWrite("will sort with _ArrayUDF_WM_NOTIFYSort2 " & @LF)
    ElseIf $iDimension = 2 Then
        $wProcNew = DllCallbackRegister("_ArrayUDF_WM_NOTIFYVir2D", "ptr", "hwnd;uint;long;ptr") ;;register new window proc
        ;ConsoleWrite("will not sort with _ArrayUDF_WM_NOTIFYVir2D " & @LF)
    EndIf

    Local $wProcOld = _ArrayUDF_WinSubclassV($hGUI, DllCallbackGetPtr($wProcNew)) ;;sublass gui
    Assign('ArrayUDF_wProcOld', $wProcOld, 2) ;; $ArrayUDF_wProcOld = global keeper of old windowproc ptr

    ;===========================================added rjc
    ; Show dialog
    GUISetState(@SW_SHOW, $hGUI)
    ConsoleWrite($sTitle & " MineV Total Time=" & Round(TimerDiff($timerstamp1)) & "" & @TAB & " msec" & @LF)
    ;===========================================avbs code for QuickSort
    If $iSort And $iDelimited Then
        Local $timerstamp11 = TimerInit()
        If $iDelimited Then
            ConsoleWrite("$iDelimited=" & $iDelimited & @LF)
            Local $timerstamp12 = TimerInit()
            For $i = 0 To UBound($ar_LISTVIEWArrayV) - 1
                StringReplace($ar_LISTVIEWArrayV[$i], $sSeparatorV, $sSeparatorV)
                If @extended > $iMaxPipes Then $iMaxPipes = @extended
            Next
            $uboundary = $iMaxPipes
            $iSubItems = $uboundary + 1
            If $iMaxPipes > $FirstPipes Then
                For $i = 1 To $iMaxPipes - $FirstPipes
                    $sStrRep &= " " & $sSeparatorV & " "
                Next
            EndIf
            ConsoleWrite($sTitle & " $iMaxPipes Time=" & Round(TimerDiff($timerstamp12)) & "" & @TAB & " msec" & @LF)
        EndIf
    EndIf
    #EndRegion second
    If $iSort Or $iDelimited Then
        Local $timerstamp11 = TimerInit(), $iGuessNumeric
        If $iDimension = 1 And Not $iDelimited Then $iGuessNumeric = IsNumber($avArrayV[0]) And IsNumber($avArrayV[1]) And IsNumber($avArrayV[UBound($avArrayV) - 1])
        ConsoleWrite($sTitle & "$iGuessNumeric=" & $iGuessNumeric & @LF)
        _GUICtrlListView_BeginUpdate($hListView)
        ReDim $aArrayIndexV[UBound($avArrayV)]
        For $i = 0 To UBound($avArrayV) - 1
            $aArrayIndexV[$i] = $i
        Next
        $arArAscV[0] = $aArrayIndexV
        DllCallbackFree($wProcNew)
        If $iDimension = 1 And Not $iDelimited Then
            $wProcNew = DllCallbackRegister("_ArrayUDF_WM_NOTIFYSort1D", "ptr", "hwnd;uint;long;ptr") ;;register new window proc
            ConsoleWrite("will NOW sort with _ArrayUDF_WM_NOTIFYSort1D " & @LF)
        Else
            $wProcNew = DllCallbackRegister("_ArrayUDF_WM_NOTIFYSort2", "ptr", "hwnd;uint;long;ptr") ;;register new window proc
            ConsoleWrite("will NOW sort with _ArrayUDF_WM_NOTIFYSort2 " & @LF)
        EndIf
        _GUICtrlListView_EndUpdate($hListView)
        Local $timerstamp11 = TimerInit(), $iGuessNumeric
        ;_ArraySortClibSet3(ByRef $Array, $iMode = 1, $fDescend = False, $iStart = 0, $iEnd = 0, $iColumn = 0, $iWidth = 128)
        Local $aIndex = _ArraySortClibIndex3($avArrayV, 1, False, 0, UBound($avArrayV) - 1, 0)
;~      DllCall('kernel32.dll', 'hwnd', 'FreeLibrary', 'hwnd', $hMsvcrtV)
        $arArAscV[1] = $aIndex
        ConsoleWrite($sTitle & "_ArraySortClibIndex3 Time=" & Round(TimerDiff($timerstamp11)) & "" & @TAB & " msec" & @LF)
        $s_LISTVIEWSortOrderV = "DESC"
    EndIf
    Local $iCountLoops = 0
    While 1
;~      if $iSliderOn then
;~
;~      EndIf
        Switch GUIGetMsg()
            Case $_ARRAYUUCONSTANT_GUI_EVENT_CLOSE, $hClose
                ExitLoop

            Case $hCopy
                Local $sClip = ""

                ; Get selected indices [ _GUICtrlListView_GetSelectedIndices($hListView, True) ]
                Local $aiCurItems[1] = [0]
                For $i = 0 To GUICtrlSendMsg($hListView, $_ARRAYUUCONSTANT_LVM_GETITEMCOUNT, 0, 0)
                    If GUICtrlSendMsg($hListView, $_ARRAYUUCONSTANT_LVM_GETITEMSTATE, $i, 0x2) Then
                        $aiCurItems[0] += 1
                        ReDim $aiCurItems[$aiCurItems[0] + 1]
                        $aiCurItems[$aiCurItems[0]] = $i
                    EndIf
                Next

                ; Generate clipboard text
                If Not $aiCurItems[0] Then
                    For $i = 0 To $iUBoundV - 1
                        $sClip &= $ar_LISTVIEWArrayV[$i] & @CRLF
                    Next
                Else
                    For $i = 1 To UBound($aiCurItems) - 1
                        $sClip &= $ar_LISTVIEWArrayV[$aiCurItems[$i]] & @CRLF
                    Next
                EndIf
                ClipPut($sClip)
;~          Case Else
;~              $iCountLoops += 1
;~              If Int($iCountLoops / 5) >= 1 Then
;~                  $iCountLoops = 0
;~                  ConsoleWrite("ListView Check" & @LF)
;~              EndIf
        EndSwitch
    WEnd
    GUIDelete($hGUI)
    ReDim $arArAscV[1]
    $s_LISTVIEWSortOrderV = ""
    $i_LISTVIEWPrevcolumnV = -1
;~  ReDim $arArDescV2V[1]
    If IsString($ar_LISTVIEWArrayV) Then $ar_LISTVIEWArrayV = StringSplit("", "|")
;~  _ArrayDisplaySortV($ar_LISTVIEWArrayV, "$ar_LISTVIEWArrayV at exit")
    ReDim $ar_LISTVIEWArrayV[1]
    ReDim $avArrayV[1]
    DllCall('kernel32.dll', 'hwnd', 'FreeLibrary', 'hwnd', $hMsvcrtV)
    Opt("GUIOnEventMode", $iOnEventMode)
    Opt("GUIDataSeparatorChar", $sDataSeparatorChar)

    Return 1
EndFunc   ;==>_ArrayDisplaySortV
Func _ArrayUDF_WM_NOTIFYSort2($hWnd, $Msg, $wParam, $LParam)
    Local $iTimer = TimerInit()
    Local $wProcOld = Eval('ArrayUDF_wProcOld'), $i, $j, $ii, $jj, $text, $textlen, $maxlen, $a_Rowa2, $iRef ;;$WM_NOTIFY = 0x004E
    Switch $Msg
        Case 0x004E
            ;and the rest of it
            Local $tNMHDR = DllStructCreate("hwnd hwndfrom;int idfrom;int code", $LParam)
            Local $hWndFrom = DllStructGetData($tNMHDR, "hwndfrom"), $iCode = DllStructGetData($tNMHDR, "code")
            $iTimeStartDataV += TimerDiff($iTimer)
            If $iNotSortedV Then $iNotSortedV = ($s_LISTVIEWSortOrderV == "")
            ;; the following is not very good, better would be have listview handle available in global scope.
            If ControlGetHandle($hWnd, "", "[Class:SysListView32;Instance:1]") = $hWndFrom Then

                Switch $iCode
                    Case $LVN_COLUMNCLICK
                        $iNotSortedV = ($s_LISTVIEWSortOrderV == ""); Or ($s_LISTVIEWSortOrderV == "Ready")
                        If $iNotSortedV Then
                            MsgBox(64, "Warning", "Not Ready to sort, please wait", 1)
                            ContinueCase
                        EndIf
                        $tNMLISTVIEW = DllStructCreate("hwnd hwndfrom;int idfrom;int code;" & _
                                "int item;int subitem", $LParam)
                        $iColV = DllStructGetData($tNMLISTVIEW, "subitem")
                        $iStartcolV = GUICtrlRead($slider1V)
                        ConsoleWrite("$iStartcolV=" & $iStartcolV & @LF)
                        If $iColV Then $iColV += $iStartcolV
                        ConsoleWrite("$iColV=" & $iColV & @LF)
                        ;===========================================
                        $timer = TimerInit()
                        _Sort($iColV)
                        ConsoleWrite("_Sort in _ArrayUDF_WM_NOTIFYSort2=" & Round(TimerDiff($timer), 2) & " msecs" & @LF)
                    Case -150, -177 ;;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177
                        ;;give requested items one by one (kinda slow if a lot of items are visible at the same time)
                        $tNMLVDISPINFOV = DllStructCreate("hwnd hwndfrom;int idfrom;int code;" & _
                                "uint mask;int item;int subitem;uint state;uint statemask;ptr text;int textmax;int;dword lparam;int;uint[5]", $LParam)
                        If BitAND(DllStructGetData($tNMLVDISPINFOV, "mask"), $LVIF_TEXT) Then
                            $i = Dec(Hex(DllStructGetData($tNMLVDISPINFOV, "item")))
                            $j = DllStructGetData($tNMLVDISPINFOV, "subitem")
                            If $j Then $j += $iStartcolV
                            $iRowV = $i
                            $iColumnToDisplayV = $j
                            Local $iTimer = TimerInit()
                            If $i_LISTVIEWPrevcolumnV = $iColV And $s_LISTVIEWSortOrderV == "DESC" Then $i = $iUBoundV - $i - 1
                            ;================================================================
                            Select
                                Case $j = 0 And $iNotSortedV;
                                    $text = "[" & $i & "]"
                                Case $j <> 0 And $iNotSortedV;
                                    $text = $avArrayV[$i][$j - 1]
                                Case $j = 0 And Not $iNotSortedV And Not $iColV;sorted on Colzero
                                    $text = "[" & $i & "]"
                                Case $j <> 0 And Not $iNotSortedV And Not $iColV;sorted on Colzero
                                    $text = $avArrayV[$i][$j - 1]
                                    ;================================================================
                                Case $j = 0 And Not $iNotSortedV And $iColV;
;~                          $i = $i * 2 + 2
;~                          $text = "[" & DllStructGetData($tSourceV, $i, 2) & "]"
                                    $text = "[" & $aArrayIndexV[$i] & "]"
;~                          $text = $aArrayIndexV[$i];$aArrayIndexV
                                Case $j <> 0 And Not $iNotSortedV And $iColV;
;~                          $i = $i * 2 + 2
;~                          $iRef = DllStructGetData($tSourceV, $i, 2)
;~                          $text = $avArrayV[$iRef][$j - 1]
                                    $text = $avArrayV[$aArrayIndexV[$i]][$j - 1];$aArrayIndexV
                                    ;================================================================
                            EndSelect
                            $iTimeSPlitDataV += TimerDiff($iTimer)
                            ;================================================================
                            Local $iTimer = TimerInit()
                            $textlen = StringLen($text)
                            If $textlen > $maxlenV - 1 Then $text = StringLeft($text, $maxlenV - 1)
                            DllStructSetData($tTextBufferV, 1, $text)
                            DllStructSetData($tNMLVDISPINFOV, "textmax", $textlen)
                            DllStructSetData($tNMLVDISPINFOV, "text", $tTextPtrV)
                            $iTimeSetDataV += TimerDiff($iTimer)
                        EndIf
                        ;           Case - 113 ;$LVN_OCACHEHINT = -113
;~              $iNotSortedV = ($s_LISTVIEWSortOrderV == "")
                        Return ; ***************************************************************************
                        ;;cache data to make it faster. not quite sure how it works
;~          Case - 113 ;$LVN_OCACHEHINT = -113
;~              ;;cache data to make it faster. not quite sure how it works
;~              Local $iTimer = TimerInit()
;~              Local $tNMLVCACHEHINT = DllStructCreate("hwnd hwndfrom;int idfrom;int code;" & _
;~                      "int from;int to", $lParam)
;~              $iFromVPrev = $iFromV
;~              $iFromV = DllStructGetData($tNMLVCACHEHINT, "from")
;~              _GUICtrlListView_EnsureVisible($hListView, $iFromV)
;~              $iRowV = $iFromV
;~              $iToV = DllStructGetData($tNMLVCACHEHINT, "to")
;~              ConsoleWrite('- chache: from ' & $iFromV & ' to ' & $iToV & @CRLF)
                EndSwitch
            EndIf
        Case $WM_HSCROLL
            ;WM_HSCROLL function
;~  Switch $LParam
;~      Case GUICtrlGetHandle($slider1V)
            If $LParam = GUICtrlGetHandle($slider1V) Then
                $iStartcolV = GUICtrlRead($slider1V)
                ConsoleWrite("$iStartcolV=" & $iStartcolV & @LF)
                For $i = 1 To 5
                    _GUICtrlListView_SetColumn($hListView, $i, "Col" & $iStartcolV + $i - 1)
                Next
                Local $iTop = _GUICtrlListView_GetTopIndex($hListView)
                ConsoleWrite("$iTop=" & $iTop & @LF)
                ConsoleWrite("$iFromV=" & $iFromV & @LF)
                GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, $iUBoundV, 0)
;~      _GUICtrlListView_EnsureVisible($hListView, $iTop)
                _GUICtrlListView_EnsureVisible($hListView, $iFromV)
;~      sleep(5000)

            EndIf
;~  EndSwitch
    EndSwitch
;~ Return CallWindowProc(old)
;~  If $Msg <> 0x004E Then Return _ArrayUDF_CallWndProcV($wProcOld, $hWnd, $Msg, $wParam, $LParam)

    ;;pass the unhandled messages to default WindowProc
    Return _ArrayUDF_CallWndProcV($wProcOld, $hWnd, $Msg, $wParam, $LParam)
EndFunc   ;==>_ArrayUDF_WM_NOTIFYSort2
Func _ArrayUDF_WM_NOTIFYVir2D($hWnd, $Msg, $wParam, $LParam)

    Local $wProcOld = Eval('ArrayUDF_wProcOld'), $i, $j, $text, $textlen, $maxlen, $a_Rowa2;;$WM_NOTIFY = 0x004E
    If $Msg <> 0x004E Then Return _ArrayUDF_CallWndProcV($wProcOld, $hWnd, $Msg, $wParam, $LParam)
    Local $tNMHDR = DllStructCreate("hwnd hwndfrom;int idfrom;int code", $LParam)
    Local $hWndFrom = DllStructGetData($tNMHDR, "hwndfrom"), $iCode = DllStructGetData($tNMHDR, "code")

    ;; the following is not very good, better would be have listview handle available in global scope.
    If ControlGetHandle($hWnd, "", "[Class:SysListView32;Instance:1]") = $hWndFrom Then

        Switch $iCode
            Case $LVN_COLUMNCLICK
                If $iNotSortedV Then
                    MsgBox(64, "Warning", "Not Ready to sort, please wait", 1)
                    ContinueCase
                EndIf
                $tNMLISTVIEW = DllStructCreate("hwnd hwndfrom;int idfrom;int code;" & _
                        "int item;int subitem", $LParam)
                $iColV = DllStructGetData($tNMLISTVIEW, "subitem")
                ;===========================================
;~              _GUICtrlListView_BeginUpdate($hWndFrom)
                $timer = TimerInit()
                _Sort($iColV)
                ConsoleWrite("_Sort in _ArrayUDF_WM_NOTIFYVir2D=" & Round(TimerDiff($timer), 2) & " msecs" & @LF)
;~              _GUICtrlListView_EndUpdate($hWndFrom)
            Case -150, -177 ;;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177
                ;;give requested items one by one (kinda slow if a lot of items are visible at the same time)
                $tNMLVDISPINFOV = DllStructCreate("hwnd hwndfrom;int idfrom;int code;" & _
                        "uint mask;int item;int subitem;uint state;uint statemask;ptr text;int textmax;int;dword lparam;int;uint[5]", $LParam)
                If BitAND(DllStructGetData($tNMLVDISPINFOV, "mask"), $LVIF_TEXT) Then
                    $i = Dec(Hex(DllStructGetData($tNMLVDISPINFOV, "item")))
                    $j = DllStructGetData($tNMLVDISPINFOV, "subitem")
                    ;================================================================
                    If $j >= $iStartV And $j <= $iEndV Then
                        If $j = 0 Then
                            $text = "[" & $i & "]"
                        Else
                            $text = $avArrayV[$i][$j - 1]
                        EndIf
                        ;================================================================
                        $textlen = StringLen($text)
                        If $textlen > $maxlenV - 1 Then $text = StringLeft($text, $maxlenV - 1)
                        DllStructSetData($tTextBufferV, 1, $text)
                        DllStructSetData($tNMLVDISPINFOV, "textmax", $textlen)
                        DllStructSetData($tNMLVDISPINFOV, "text", $tTextPtrV)
                    EndIf
                EndIf
        EndSwitch
    EndIf

    ;;pass the unhandled messages to default WindowProc
    Return _ArrayUDF_CallWndProcV($wProcOld, $hWnd, $Msg, $wParam, $LParam)
EndFunc   ;==>_ArrayUDF_WM_NOTIFYVir2D
Func _ArrayUDF_WM_NOTIFYSort1D($hWnd, $Msg, $wParam, $LParam)

    Local $wProcOld = Eval('ArrayUDF_wProcOld'), $i, $j, $text, $textlen, $maxlen, $a_Rowa2;;$WM_NOTIFY = 0x004E
    If $Msg <> 0x004E Then Return _ArrayUDF_CallWndProcV($wProcOld, $hWnd, $Msg, $wParam, $LParam)

    Local $tNMHDR = DllStructCreate("hwnd hwndfrom;int idfrom;int code", $LParam)
    Local $hWndFrom = DllStructGetData($tNMHDR, "hwndfrom"), $iCode = DllStructGetData($tNMHDR, "code")
    If $iNotSortedV Then $iNotSortedV = ($s_LISTVIEWSortOrderV == "")
    ;; the following is not very good, better would be have listview handle available in global scope.
    If ControlGetHandle($hWnd, "", "[Class:SysListView32;Instance:1]") = $hWndFrom Then

        Switch $iCode
            Case $LVN_COLUMNCLICK
;~              Local $iNotSortedV = ($s_LISTVIEWSortOrderV == ""); Or ($s_LISTVIEWSortOrderV == "Ready")
                If $iNotSortedV Then
                    MsgBox(64, "Warning", "Not Ready to sort, please wait", 1)
                    ContinueCase
                EndIf
                $tNMLISTVIEW = DllStructCreate("hwnd hwndfrom;int idfrom;int code;" & _
                        "int item;int subitem", $LParam)
                $iColV = DllStructGetData($tNMLISTVIEW, "subitem")

                ;===========================================
                _GUICtrlListView_BeginUpdate($hWndFrom)
                $timer = TimerInit()
                If $i_LISTVIEWPrevcolumnV <> $iColV Then $s_LISTVIEWSortOrderV = "DESC"
                If $i_LISTVIEWPrevcolumnV = $iColV And $s_LISTVIEWSortOrderV == "DESC" Then ;
                    ConsoleWrite('_ArrayReverse $s_LISTVIEWSortOrderV=' & $s_LISTVIEWSortOrderV & @CRLF)
                    $s_LISTVIEWSortOrderV = "ASC"
                Else
                    If ($i_LISTVIEWPrevcolumnV <> $iColV Or Not $s_LISTVIEWSortOrderV) And _
                            Not IsArray($arArAscV[$iColV]) And $iColV Then
                        Local $iGuessNumeric = IsNumber($avArrayV[0]) And IsNumber($avArrayV[1]) And IsNumber($avArrayV[UBound($avArrayV) - 1])

                        Local $timerstamp13 = TimerInit()
                        ConsoleWrite("$avArrayV[ubound($avArrayV)-1]=" & $avArrayV[UBound($avArrayV) - 1] & @LF)
                        $arArAscV[$iColV] = $avArrayV
                    ElseIf ($i_LISTVIEWPrevcolumnV <> $iColV Or Not $s_LISTVIEWSortOrderV) Or $iColV = 0 Then
                        $avArrayV = $arArAscV[$iColV]
                    EndIf
                    $i_LISTVIEWPrevcolumnV = $iColV
                    $s_LISTVIEWSortOrderV = "DESC"
                EndIf
                ConsoleWrite("Sort " & Round(TimerDiff($timer), 2) & " msecs" & @LF)
                _GUICtrlListView_EndUpdate($hWndFrom)
            Case -150, -177 ;;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177
                ;;give requested items one by one (kinda slow if a lot of items are visible at the same time)
                $tNMLVDISPINFOV = DllStructCreate("hwnd hwndfrom;int idfrom;int code;" & _
                        "uint mask;int item;int subitem;uint state;uint statemask;ptr text;int textmax;int;dword lparam;int;uint[5]", $LParam)

                If BitAND(DllStructGetData($tNMLVDISPINFOV, "mask"), $LVIF_TEXT) Then
                    $i = Dec(Hex(DllStructGetData($tNMLVDISPINFOV, "item")))
                    $j = DllStructGetData($tNMLVDISPINFOV, "subitem")
                    ;================================================================
;~                  If $j >= $iStartV And $j <= $iEndV Then

;~                      Local $iNotSortedV = ($s_LISTVIEWSortOrderV == ""); Or ($s_LISTVIEWSortOrderV == "Ready")
                    Local $sTemp1, $aTmp, $iRef; = StringSplit($ar_LISTVIEWArrayV[UBound($avArrayV) - 1], $sSeparatorV, 1)
                    Local $a = $i
                    If $i_LISTVIEWPrevcolumnV == $iColV And $s_LISTVIEWSortOrderV == "DESC" Then $a = $iUBoundV - $i - 1
                    Select
                        Case $j = 0 And $iNotSortedV;
                            $text = "[" & $a & "]"
                        Case $j <> 0 And $iNotSortedV;
                            $text = $avArrayV[$a]
                        Case $j = 0 And Not $iNotSortedV And Not $iColV;sorted
                            $text = "[" & $a & "]"
                        Case $j <> 0 And Not $iNotSortedV And Not $iColV;;sorted
                            $text = $avArrayV[$a]
                        Case $j = 0 And Not $iNotSortedV And $iColV;;sorted
;~                              $a = $a * 2 + 2
;~                              $text = "[" & DllStructGetData($tSourceV, $a, 2) & "]"
                            $text = "[" & $aArrayIndexV[$a] & "]"
                        Case $j <> 0 And Not $iNotSortedV And $iColV;;sorted
;~                              $a = $a * 2 + 2
;~                              $iRef = DllStructGetData($tSourceV, $a, 2)
;~                              $text = $avArrayV[$iRef]
                            $text = $avArrayV[$aArrayIndexV[$a]];[$j - 1];$aArrayIndexV
                    EndSelect

                    $textlen = StringLen($text)
                    If $textlen > $maxlenV - 1 Then $text = StringLeft($text, $maxlenV - 1)
                    DllStructSetData($tTextBufferV, 1, $text)
                    DllStructSetData($tNMLVDISPINFOV, "textmax", $textlen)
                    DllStructSetData($tNMLVDISPINFOV, "text", $tTextPtrV)
;~                  EndIf
;~              ElseIf BitAND(DllStructGetData($tNMLVDISPINFOV, "mask"), $LVIF_STATE) Then
                    ;;meh. although the selected items array filling could be implemented here, so there wouldn't be no need
                    ;;to loop through entire thing again when "Copy Selected" button is clicked

                EndIf
        EndSwitch
    EndIf

    ;;pass the unhandled messages to default WindowProc
    Return _ArrayUDF_CallWndProcV($wProcOld, $hWnd, $Msg, $wParam, $LParam)
EndFunc   ;==>_ArrayUDF_WM_NOTIFYSort1D
Func _Sort($i_OrderColumn)
    ;=====================================================================================================================
    _GUICtrlListView_BeginUpdate($hListView)
    $timer = TimerInit()
    If $i_LISTVIEWPrevcolumnV <> $i_OrderColumn Then $s_LISTVIEWSortOrderV = "DESC"
    If $i_LISTVIEWPrevcolumnV = $i_OrderColumn And $s_LISTVIEWSortOrderV == "DESC" Then ;
        ConsoleWrite('_ArrayReverse $s_LISTVIEWSortOrderV=' & $s_LISTVIEWSortOrderV & @CRLF)
        $s_LISTVIEWSortOrderV = "ASC"
    Else
        If ($i_LISTVIEWPrevcolumnV <> $i_OrderColumn Or Not $s_LISTVIEWSortOrderV) And _
                Not IsArray($arArAscV[$i_OrderColumn]) And $i_OrderColumn Then
            $aArrayIndexV = _ArraySortClibIndex3($avArrayV, 1, False, 0, UBound($avArrayV) - 1, $i_OrderColumn - 1)
;~          _ArraySortClibSet3($avArrayV, 1, False, 0, UBound($avArrayV) - 1, $i_OrderColumn - 1)
            Local $timerstamp13 = TimerInit()
            $arArAscV[$i_OrderColumn] = $aArrayIndexV
            ConsoleWrite("_ArraySortClibIndex3 Sort on $i_OrderColumn=" & $i_OrderColumn & @LF)
        ElseIf ($i_LISTVIEWPrevcolumnV <> $i_OrderColumn Or Not $s_LISTVIEWSortOrderV) Or $i_OrderColumn < 2 Then
            $aArrayIndexV = $arArAscV[$i_OrderColumn]; = $aArrayIndexV
            ConsoleWrite('- Get prev Array Index $s_LISTVIEWSortOrderV=' & $s_LISTVIEWSortOrderV & @CRLF)
        EndIf
        $i_LISTVIEWPrevcolumnV = $i_OrderColumn
        $s_LISTVIEWSortOrderV = "DESC"
    EndIf
    ConsoleWrite("Sort func" & Round(TimerDiff($timer), 2) & " msecs" & @LF)
    _GUICtrlListView_EndUpdate($hListView)
    ;=====================================================================================================================
EndFunc   ;==>_Sort
Func _ArrayUDF_WinSubclassV($hWnd, $lpNewWindowProc)
    ;#define GWL_WNDPROC (-4)
    Local $aTmp, $sFunc = "SetWindowLong"
    If Execute("@Unicode") Then $sFunc &= "W"
    $aTmp = DllCall("user32.dll", "ptr", $sFunc, "hwnd", $hWnd, "int", -4, "ptr", $lpNewWindowProc)
    If @error Then Return SetError(1, 0, 0)
    If $aTmp[0] = 0 Then Return SetError(1, 0, 0)
    Return $aTmp[0]
EndFunc   ;==>_ArrayUDF_WinSubclassV
Func _ArrayUDF_CallWndProcV($lpPrevWndFunc, $hWnd, $Msg, $wParam, $LParam)
    Local $aRet = DllCall('user32.dll', 'uint', 'CallWindowProc', 'ptr', $lpPrevWndFunc, 'hwnd', $hWnd, 'uint', $Msg, 'wparam', $wParam, 'lparam', $LParam)
;~  If @error Then Return 0
    Return $aRet[0]
EndFunc   ;==>_ArrayUDF_CallWndProcV
Func _ArraySortClibIndex3(ByRef $Array, $iMode = 1, $fDescend = False, $iStart = 0, $iEnd = 0, $iColumn = 0, $iWidth = 128)
    Local $iArrayDims = UBound($Array, 0), $aIndex[1]
    If @error Or $iArrayDims > 2 Then Return SetError(1, 0, 0)
    Local $iArraySize = UBound($Array, 1), $iColumnMax = UBound($Array, 2)
    If $iArraySize < 2 Then Return 0
    If $iEnd < 1 Or $iEnd > $iArraySize - 1 Then $iEnd = $iArraySize - 1
    If ($iEnd - $iStart < 2) Then Return SetError(2, 0, 0)
    If $iArrayDims = 2 Then
        If ($iColumnMax - $iColumn < 0) Then Return SetError(2, 0, 0)
    EndIf
    If $iWidth < 1 Then Return SetError(2, 0, 0)
    $iWidth = Ceiling($iWidth / 8) * 8
    Local $sMem, $tSourceV, $pSourceV, $i, $j, $iCount, $fNumeric, $fCase, $aRet, $hMsvcrtV, $sStrCmpV, $tFloatCmpV, $pCmpV, $tIndexerV
    Switch $iMode
        Case 0
            $fNumeric = True
        Case 1
            $fCase = False
        Case 2
            $fCase = True
        Case Else
            Return SetError(2, 0, 0)
    EndSwitch
    ;; initialize sorting proc
    If $fNumeric Then
        $tFloatCmpV = DllStructCreate("byte[36]")
        DllStructSetData($tFloatCmpV, 1, Binary("0x8B4C24048B542408DD01DC1ADFE0F6C440750D80E441740433C048C333C040C333C0C3"))
        $pCmpV = DllStructGetPtr($tFloatCmpV)
    Else
        $sStrCmpV = "_strcmpi" ;case insensitive
        If $fCase Then $sStrCmpV = "strcmp" ;case sensitive
        $aRet = DllCall('kernel32.dll', 'hwnd', 'LoadLibraryA', 'str', 'msvcrt.dll')
        $hMsvcrtV = $aRet[0]
        $aRet = DllCall('kernel32.dll', 'ptr', 'GetProcAddress', 'ptr', $hMsvcrtV, 'str', $sStrCmpV)
        DllCall('kernel32.dll', 'hwnd', 'FreeLibrary', 'hwnd', $hMsvcrtV)
        If $aRet[0] = 0 Then Return -1
        $pCmpV = $aRet[0]
    EndIf
    ;; initialize memory
    $sMem = ""
    If $fNumeric Then
        For $i = 1 To $iArraySize
            $sMem &= "double;int[4];"
        Next
        $iWidth = 24
    Else
        For $i = 1 To $iArraySize
            $sMem &= "char[" & $iWidth & "];int[4];"
        Next
        $iWidth += 16
    EndIf
    $sMem = StringTrimRight($sMem, 1)
    $tSourceV = DllStructCreate($sMem)
    ;; fill memory
    If $iArrayDims = 1 Then
        For $i = 0 To $iArraySize - 1
            DllStructSetData($tSourceV, $i * 2 + 1, $Array[$i])
        Next
    Else
        For $i = 0 To $iArraySize - 1
            DllStructSetData($tSourceV, $i * 2 + 1, $Array[$i][$iColumn])
        Next
    EndIf
    ;; enumerate elements
    $tIndexerV = DllStructCreate("byte[32]")
    DllStructSetData($tIndexerV, 1, Binary("0x33C08B7424048B4C2408037424108B5C240C890603F3403BC17CF7C3"))
    DllCall('user32.dll', 'uint', 'CallWindowProc', 'ptr', DllStructGetPtr($tIndexerV), 'ptr', DllStructGetPtr($tSourceV, 2), 'int', $iArraySize, 'int', $iWidth, 'int', 4)
    $pSourceV = DllStructGetPtr($tSourceV, $iStart * 2 + 1) ;;pointer to search starting element
    $iCount = $iEnd - $iStart + 1 ;;count of elements to search
    ;;sort
    DllCall('msvcrt.dll', 'none:cdecl', 'qsort', 'ptr', $pSourceV, 'int', $iCount, 'int', $iWidth, 'ptr', $pCmpV)
    ;; read back the result
    ReDim $aIndex[UBound($Array)]
    For $i = $iStart To $iEnd
        $aIndex[$i] = DllStructGetData($tSourceV, $i * 2 + 2, 2)
    Next
    Return $aIndex
EndFunc   ;==>_ArraySortClibIndex3

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0