Jump to content
Norm73

Is it possible to find the index from ID-Control in ListView?

Recommended Posts

Hello,

I can't find an alternative for the _GUICtrlListView_MapIndexToID function that doesn't work for me.

Is it even possible to find the index from ID-Control in ListView?

I thank you in advance

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

Example()

Func Example()
    GUICreate("listview items", 320, 450, -1, -1, -1, $WS_EX_ACCEPTFILES)
    GUISetBkColor(0x00E0FFFF) ; will change background color
    Local $sLb = GUICtrlCreateLabel("Number Item-Index", 20, 335)
    Local $nImp = GUICtrlCreateInput("", 20, 350, 150, 24, 0x2000) ;$ES_NUMBER
    Local $idButton = GUICtrlCreateButton("Index -> Control-ID"& @CRLF &"Control-ID -> Index ?", 20, 380, 150, 48, BitOR(0x2000, 0x0100)) ;$BS_MULTILINE
    GUICtrlSetFont(-1, 11)
    Local $idListview = GUICtrlCreateListView("col 1  |col 2  |col 3  |col 4  |", 10, 10, 300, 300) ;,$LVS_SORTDESCENDING)
    Local $nP = 0
    For $nN = 0 To 10
        GUICtrlCreateListViewItem("item "& $nN &"|col "& $nP+1 &"|col "& $nP+2 &"|col "& $nP+3, $idListview)
        $nP += 1
    Next

    GUISetState(@SW_SHOW)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $idButton
                Local $nNr = Number(GUICtrlRead($nImp))
                If $nNr >= 0 And $nNr < 11 Then
                    Local $nID = _GUICtrlListView_GetItemParam($idListview, $nNr)
                    Local $nIndex = _GUICtrlListView_MapIndexToID($idListview, $nID)
                    MsgBox($MB_SYSTEMMODAL, "listview", "Input Index = "& $nNr & @CRLF &"Index To ID-Control -> "& $nID & @CRLF &"ID-Control To Index -> "& $nIndex)
                EndIf
        EndSwitch
    WEnd
EndFunc   ;==>Example

 

Edited by Norm73

Share this post


Link to post
Share on other sites

You have to approach this in a different way.

In your code, you are assuming that the number 1 is the ListViewItem number 1, which is not.

I have changed the creation of items to display the ID's which are created, by outputting it to the console.

 

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

Example()

Func Example()
    GUICreate("listview items", 320, 450, -1, -1, -1, $WS_EX_ACCEPTFILES)
    GUISetBkColor(0x00E0FFFF) ; will change background color
    Local $sLb = GUICtrlCreateLabel("Number Item-Index", 20, 335)
    Local $idButton = GUICtrlCreateButton("Index -> Control-ID"& @CRLF &"Control-ID -> Index ?", 20, 380, 150, 48, BitOR(0x2000, 0x0100)) ;$BS_MULTILINE
    GUICtrlSetFont(-1, 11)
    Local $idListview = GUICtrlCreateListView("col 1  |col 2  |col 3  |col 4  |", 10, 10, 300, 300) ;,$LVS_SORTDESCENDING)
    Local $nP = 0

    ConsoleWrite ("*********************" & @CRLF)
    ConsoleWrite ("Added list view ID's:"& @CRLF)
    For $nN = 0 To 10
        ConsoleWrite($nN & " = " & GUICtrlCreateListViewItem("item "& $nN &"|col "& $nP+1 &"|col "& $nP+2 &"|col "& $nP+3, $idListview) & @CRLF)
        $nP += 1
    Next
    ConsoleWrite ("*********************" & @CRLF)

    GUISetState(@SW_SHOW)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $idButton
                Local $nNr = _GUICtrlListView_GetSelectionMark($idListview)
                Local $idx = _GUICtrlListView_MapIndexToID($idListview, $nNr)
                Local $aItem = _GUICtrlListView_GetItem($idListview, $idx)
                ;_ArrayDisplay ($aItem)
                if IsArray($aItem) Then

                    ConsoleWrite ( "Selected Nr = "& $nNr & @CRLF &"Selected Id = "& $aItem[5] & @CRLF &"Item Text: "& chr(34) &$aItem[3] & chr(34) & @crlf)
                EndIf
                $aItem=""
                ConsoleWrite ("*********************" & @CRLF)
        EndSwitch
    WEnd
EndFunc   ;==>Example

I have, as well, modified the code, and removed the input button so that now you have to select an LW-item with the mouse, and to click on the button, to display some information.

To see all information which _GUICtrlListView outputs, uncomment the _ArrayDisplay line.

I hope this helps you.

Edited by Dan_555

Share this post


Link to post
Share on other sites

I must admit, it is quite confusing at first, as there is 4 types of ID in ListView :

1- GUI IDs : all controls get a separate ID in a given moment.  But a specific ID can be reuse if another control got deleted.

2- LV Index : all list view items get a separate ID in a given moment based on its position in the LV.  If items get inserted then all indexes after insertion point are modified.

3- LV ID : all list view items get a unique internal ID (within the LV, starting at 0) that do not change over lifetime of the GUI.

4- LV Param : all list view items get a place to register a parameter.  If the LV item is created by native GUI function, parameter is automatically assign to the GUI ID of the item.  If the LV item is created by UDF function, parameter is unassigned (0 by default) but is managed by script.

To illustrate this you may take a look at this :

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

Example()

Func Example()
    Local $iID, $idListview

    GUICreate("ListView Map ID To Index", 400, 300)
    $idListview = GUICtrlCreateListView("", 2, 2, 394, 268)
    GUISetState(@SW_SHOW)

    ; Add column
    _GUICtrlListView_AddColumn($idListview, "Items", 100)

  ConsoleWrite ("GUI ID " & GUICtrlCreateListViewItem ("Item 0", $idListview) & @CRLF)

    ; Add items
  For $i = 1 to 4
    ConsoleWrite ("Creation index " & _GUICtrlListView_AddItem($idListview, "Item " & $i, -1, $idListview+$i+1) & @CRLF)
  Next

  ConsoleWrite ("Insertion index " & _GUICtrlListView_InsertItem($idListview, "Item 2-3", 3) & @CRLF)
  ConsoleWrite ("****************" & @CRLF)
  For $i = 0 to 5
    ConsoleWrite ("LV ID " & _GUICtrlListView_MapIndexToID($idListview, $i) & @CRLF)
  Next
  ConsoleWrite ("****************" & @CRLF)

  _GUICtrlListView_DeleteItem($idListview, 2)
  ConsoleWrite ("Insertion index " & _GUICtrlListView_InsertItem($idListview, "Item 3-4", 4) & @CRLF)
  ConsoleWrite ("GUI ID " & GUICtrlCreateListViewItem ("Item 5", $idListview) & @CRLF)

  For $i = 0 to 6
    ConsoleWrite ("LV ID " & _GUICtrlListView_MapIndexToID($idListview, $i) & @CRLF)
  Next

  ConsoleWrite ("****************" & @CRLF)
  For $i = 0 to 6
    ConsoleWrite ("Param " & _GUICtrlListView_GetItemParam($idListview, $i) & @CRLF)
  Next

    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    GUIDelete()
EndFunc   ;==>Example

 

Edited by Nine

Share this post


Link to post
Share on other sites
6 hours ago, Norm73 said:

Is it even possible to find the index from ID-Control in ListView?

It should be possible, by creating a 2D array during the native listview Items creation phase (1st column = item ID-control, 2nd column = listview index), but as Nine just wrote, you better not delete or insert items after this.
The question is : do you have a special need to map all listview indexes to their original creation ID's ?

The only time I used it was before/after a column sort in ListView, because I wanted the cell that was selected before the sort to be focused on after the sort.
As AutoIt changes all indexes of the items during the sort, then these 2 commands did the job :

* _GUICtrlListView_MapIndexToID() used just before the sort, on 1 item.
* _GUICtrlListView_MapIDToIndex() used just after the sort, on 1 item.

In fact it's not AutoIt that changes the indexes, but Windows :

MSDN: "LVM_SORTITEMSEX message will use an application-defined comparison function to sort the items of the list-view control. The index of each item will change to reflect the new sequence."

 

Edited by pixelsearch
typo

Share this post


Link to post
Share on other sites
2 hours ago, Dan_555 said:

I have, as well, modified the code, and removed the input button so that now you have to select an LW-item with the mouse, and to click on the button, to display some information.

many thanks for the explanation and very good example.

I've been busy with the question for a week and now I also know the difference between the Autoit ID and the ID from GuiListView.au3.

I'm making a big list of native features.

If I choose a separate item, this is not a problem. I have to find out without picking a point.

The list is static and does not change, nothing is deleted. I have an array list with all the internal autoit IDs of the list so I don't have to keep track of how the list is sorted. I can read out a point immediately or put a check mark. But that's where it ends. All other options (native or not) work with index and not IDs. I cannot use the _GUICtrlListView_SetItemParam option because I work with it natively. Of course I can query every point in a cycle, but that will take a long time in a large table. The best way would be to get the index directly. But how, I don't know.

Share this post


Link to post
Share on other sites
On 12/6/2020 at 4:22 PM, Norm73 said:

I have an array list with all the internal autoit IDs of the list so I don't have to keep track of how the list is sorted.

Well... maybe one you'll need your listview sorted, who knows... If it happens, please have a look at the 3 pics below :

LV1.png.8f59aa10336e34f8c76999613ce1e6e0.png

The pic above could represent a 2D array of your listview items just after it has been created (with only one data column on the right, to make these explanations simpler)
11 rows, 1 column in LV, content of the column (unsorted) => "CC" , "MM" ... "HH"
Gui ID's for your items start at 7 because :
* Gui ID's always start at 3 and...
* ...you already created 4 controls before ($sLb, $nImp, $idButton, $idListview) which were assigned to GUI ID's 3, 4, 5, 6

LV ID and LV Index got the same value just after the LV is created (from 0 to 10)

1802106098_LV2correct(maybe).png.affd5585162a12b02d9ddae7821fdeed.png

The pic above shows what happens when you sort using the _GUICtrlListView_SimpleSort() function :
Content of cells is now sorted "AA" , "CC" ... "ZZ"
LV ID = LV index because Windows didn't make the sort, all the sorting part is included in the UDF's (it would be same if you ever use one day ArrayMultiColSort() from Melba23 : LV ID = LV Index after the MultiColSort)

LV3.png.780c6a6ef44de5d9f23cf3680978b6d8.png

The pic above shows what happens when you sort using _GUICtrlListView_SortItems()
Content of cells is sorted "AA" , "CC" ... "ZZ" but all LV indexes have changed (they're no more equals to LV ID's) because Windows did the sort when LVM_SORTITEMSEX message was called (MSDN's explanations in my precedent post)

So if you ever use this way of sorting, then you'll need _GUICtrlListView_MapIndexToID() and _GUICtrlListView_MapIDToIndex() to update your array accordingly.

On 12/6/2020 at 4:22 PM, Norm73 said:

The best way would be to get the index directly. But how, I don't know.

I think the quickest way to access a value directly in an Array is to use ArrayBinarySearch() but if you do this, the search column must be sorted in ascending order before the search is done (help file, topic ArrayBinarySearch)

As you're saying that you won't sort the LV, why don't you just use ArrayBinarySearch() in the 1st pic, where both GUI ID column and LV Index column are already sorted ?

Checking quickly a value in the GUI ID column will indicate you its corresponding LV index value... and vice-versa

Hope it helps and good luck :)

Edited by pixelsearch
changed pic #2, it should be ok now.

Share this post


Link to post
Share on other sites

You have done a great job. Many thanks.

I would like to use these functions
_GUICtrlListView_MapIndexToID ()
_GUICtrlListView_MapIDToIndex ()
unfortunately they do not work with natural functions.

I used the _GUICtrlListView_MapIDToIndex in my example above and it only returns -1.

It may be that the control ID is changed in the other script when sorting, but it works for me, as in the instructions.

Quote

_GUICtrlListView_MapIDToIndex

ListView-Controls erfassen Items intern durch einen Index.
Dies kann Probleme verursachen, weil sich Indizes ändern können.
Das ListView-Control kann ein Item mit einer ID kennzeichnen, wenn das Item erstellt wird.
Diese ID kann verwendet werden, um die Eindeutigkeit während der Laufzeit des Controls zu garantieren.

ArrayBinarySearch -> very good advice, I'll keep that out of sight.

Unfortunately, the question is always not resolved whether there is an alternative to the _GUICtrlListView_MapIDToIndex function that will work in my example.😢

Edited by Norm73

Share this post


Link to post
Share on other sites
57 minutes ago, Norm73 said:

I used the _GUICtrlListView_MapIDToIndex in my example above and it only returns -1.

It returns -1 (when you input 4 or more) because you got the 2nd parameter wrong in your script :

Local $nIndex = _GUICtrlListView_MapIndexToID($idListview, $nID) ; ?

2nd parameter should be the "0-based index of an item" (help file) which means 0-10 (as shown in 1st pic of my post), not the controlID of the native-created ListView item (the "GUI ID" column in the pic) which goes from 7 to 17

_GUICtrlListView_MapIDToIndex maps the 2 columns "LV ID" and "LV index", it has nothing to do with the "GUI ID" column. In your script.  When the following line is encountered...

Local $nID = _GUICtrlListView_GetItemParam($idListview, $nNr)

... then $nID contains the "GUI ID" value, which has nothing to do with _GUICtrlListView_MapIndexToID()... I guess :)

Also, please take care of this line :
 

If $nNr > 0 And $nNr < 11 Then ; 1 to 10

Because 0 is a valid item index that can be keyed in the Input field, then it should be :

If $nNr >= 0 And $nNr < 11 Then ; 0 to 10

 

Share this post


Link to post
Share on other sites

Of course my example is not ideal. (It could be better)☹️

I finally found what I needed.

And it was in front of your nose, so to speak, the whole time The _GUICtrlListView_FindParam () function from the same library returns the index of the point from the control-ID (GUI-Autoit).

It also works fine with the sorting.

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

Example()

Func Example()
    GUICreate("listview items", 320, 450, -1, -1, -1, $WS_EX_ACCEPTFILES)
    GUISetBkColor(0x00E0FFFF) ; will change background color
    Local $sLb = GUICtrlCreateLabel("Number Item-Index", 20, 335)
    Local $nImp = GUICtrlCreateInput("", 20, 350, 150, 24, 0x2000) ;$ES_NUMBER
    Local $idButton = GUICtrlCreateButton("Index -> Control-ID"& @CRLF &"Control-ID -> Index ?", 20, 380, 150, 48, BitOR(0x2000, 0x0100)) ;$BS_MULTILINE
    GUICtrlSetFont(-1, 11)
    Global $idListview = GUICtrlCreateListView("col 1  |col 2  |col 3  |col 4  |", 10, 10, 300, 300) ;,$LVS_SORTDESCENDING)
    Local $nP = 0
    For $nN = 0 To 9
        GUICtrlCreateListViewItem("item "& $nN &"|col "& $nP+1 &"|col "& $nP+2 &"|col "& $nP+3, $idListview)
        $nP += 1
    Next

    GUISetState(@SW_SHOW)
    _GUICtrlListView_RegisterSortCallBack($idListview)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                _GUICtrlListView_UnRegisterSortCallBack($idListview)
                GUIDelete()
                ExitLoop
            Case $idButton
                Local $nNr = Number(GUICtrlRead($nImp))
                If $nNr >= 0 And $nNr < 11 Then
                    Local $nID = _GUICtrlListView_GetItemParam($idListview, $nNr)
                    Local $nIndex = _GUICtrlListView_FindParam($idListview, $nID)
                    MsgBox($MB_SYSTEMMODAL, "listview", "Input Index = "& $nNr & @CRLF &"Index To ID-Control -> "& $nID & @CRLF &"ID-Control To Index -> "& $nIndex)
                EndIf
            Case $idListview
                _GUICtrlListView_SortItems($idListview, 0)
        EndSwitch
    WEnd
EndFunc   ;==>Example

 

 

Edited by Norm73

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

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

Create an account

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

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...