ListView - zählen der "checked Items"

    • Offizieller Beitrag

    Ich habe ein Problem mit der Geschwindigkeit eines Scripts. Und zwar geht es darum die Anzahl der angehakten Listview-Items herauszubekommen.
    Dazu habe ich mir das folgende Script geschrieben:

    Spoiler anzeigen
    [autoit]


    #include<StaticConstants.au3>
    #include<ListViewConstants.au3>
    #include<WindowsConstants.au3>
    #include<GuiConstantsEx.au3>
    #include<GuiListView.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt('GUIOnEventMode', 1)

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("ListView", 400, 380)
    GUISetOnEvent($GUI_EVENT_CLOSE, '_End')

    [/autoit] [autoit][/autoit] [autoit]

    $LVStyle = BitOR($LVS_NOCOLUMNHEADER, $LVS_REPORT, $LVS_SINGLESEL)
    $ExStyle = BitOR($LVS_EX_FULLROWSELECT, $WS_EX_DLGMODALFRAME, $LVS_EX_CHECKBOXES, $LVS_EX_DOUBLEBUFFER)
    $hListView = GUICtrlCreateListView(' ', 5, 5, 390, 320, $LVStyle, $ExStyle)
    For $i = 0 To 9999
    GUICtrlCreateListViewItem("data1", $hListView)
    GUICtrlSetOnEvent(-1, '_RefreshCounter')
    Next
    _GUICtrlListView_SetColumnWidth($hListview, 0, 365)

    [/autoit] [autoit][/autoit] [autoit]

    $hLabel = GUICtrlCreateLabel('0', 10, 340, 90, 24, $SS_CENTER, $WS_EX_DLGMODALFRAME)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _End()
    Exit
    EndFunc ;==>_End

    [/autoit] [autoit][/autoit] [autoit]

    Func _RefreshCounter()
    Local $iCount = _GUICtrlListView_GetCheckedCount($hListview)
    GUICtrlSetData($hLabel, $iCount)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _GUICtrlListView_GetCheckedCount($hListview)
    Local $iCount = _GUICtrlListView_GetItemCount($hListview), $iCheckedCount = 0
    For $i = 0 To $iCount
    $iCheckedCount += _GUICtrlListView_GetItemChecked($hListview, $i)
    Next
    Return $iCheckedCount
    EndFunc ;==>_GUICtrlListView_GetCheckedCount

    [/autoit]

    Das funktioniert auch so, wie ich mir das vorstelle, aber es ist etwas langsam. Wenn man einen Haken setzt oder entfernt wird die Anzeige erst verzögert aktualisiert.
    Meine Frage ist nun: Kennt jemand eine schnellere Lösung dafür?

    • Offizieller Beitrag

    Hallo,

    Es gibt doch die Funktion _GUICtrlListViewGetSelectedCount.

    • Offizieller Beitrag

    Das habe ich schon probiert. Hätte ich noch dazu schreiben können...vergessen. :rolleyes:

    Die Funktion "_GUICtrlListViewGetSelectedCount" gibt nur die markierten Einträge zurück. Das markieren ist aber ein Unterschied zu den angehakten.

    Edit: Um den Unterschied zu verdeutlichen, hier ein Testscript:

    Spoiler anzeigen
    [autoit]


    #include<StaticConstants.au3>
    #include<ListViewConstants.au3>
    #include<WindowsConstants.au3>
    #include<GuiConstantsEx.au3>
    #include<GuiListView.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt('GUIOnEventMode', 1)

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("ListView", 400, 380)
    GUISetOnEvent($GUI_EVENT_CLOSE, '_End')

    [/autoit] [autoit][/autoit] [autoit]

    $LVStyle = BitOR($LVS_NOCOLUMNHEADER, $LVS_REPORT)
    $ExStyle = BitOR($LVS_EX_FULLROWSELECT, $WS_EX_DLGMODALFRAME, $LVS_EX_CHECKBOXES, $LVS_EX_DOUBLEBUFFER)
    $hListView = GUICtrlCreateListView(' ', 5, 5, 390, 320, $LVStyle, $ExStyle)
    For $i = 0 To 9999
    GUICtrlCreateListViewItem("data1", $hListView)
    GUICtrlSetOnEvent(-1, '_RefreshCounter')
    Next
    _GUICtrlListView_SetColumnWidth($hListview, 0, 365)

    [/autoit] [autoit][/autoit] [autoit]

    $hLabel1 = GUICtrlCreateLabel('0', 10, 340, 90, 24, $SS_CENTER, $WS_EX_DLGMODALFRAME)
    $hLabel2 = GUICtrlCreateLabel('0', 120, 340, 90, 24, $SS_CENTER, $WS_EX_DLGMODALFRAME)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _End()
    Exit
    EndFunc ;==>_End

    [/autoit] [autoit][/autoit] [autoit]

    Func _RefreshCounter()
    Local $iCount = _GUICtrlListView_GetSelectedCount($hListview)
    GUICtrlSetData($hLabel2, $iCount)
    Local $iCount = _GUICtrlListView_GetCheckedCount($hListview)
    GUICtrlSetData($hLabel1, $iCount)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _GUICtrlListView_GetCheckedCount($hListview)
    Local $iCount = _GUICtrlListView_GetItemCount($hListview), $iCheckedCount = 0
    For $i = 0 To $iCount
    $iCheckedCount += _GUICtrlListView_GetItemChecked($hListview, $i)
    Next
    Return $iCheckedCount
    EndFunc ;==>_GUICtrlListView_GetCheckedCount

    [/autoit]
  • wieso muss denn in dieser zeile : For $i = 0 To 9999 der zweite wert so hoch sein?
    wenn man den runter setzt wirds deutlich flotter.

    die funktion gefällt mir aber, ich glaube das kann ich für meinen skript zum erstellen einer winamp playliste gebrauchen.

    • Offizieller Beitrag

    Ich brauche diese Funktion für mein Programm (AIPM). In dem Listview werden Dateinamen von Bildern angezeigt, die rekursiv aus einem Quellverzeichnis gelesen werden und ein Wert von 10000 Einträgen ist dort durchaus möglich.
    Aber wenn es dafür keine schnellere Lösung gibt, muss ich wohl mit der Verzögerung leben. :huh:

    Ich habe auch noch eine Funktion zum auslesen der "angehakten" Items erstellt. Wenn Du die auch haben willst, sag Bescheid.

    • Offizieller Beitrag

    Edit: Hatte vergessen, das war ja nur für die Indices. Hier mal ein paar mehr Funktionen (mit Beispiel):

    Edit2: Jetzt alles mit "0"-basierten-Arrays:

    Spoiler anzeigen
    [autoit]


    #include<StaticConstants.au3>
    #include<Array.au3>
    #include<ListViewConstants.au3>
    #include<WindowsConstants.au3>
    #include<GuiConstantsEx.au3>
    #include<GuiListView.au3>
    Opt('GUIOnEventMode', 1) ; OnEvent-Mode einschalten

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate('ListView mit Checkboxen', 400, 380)
    GUISetOnEvent($GUI_EVENT_CLOSE, '_End')

    [/autoit] [autoit][/autoit] [autoit]

    $LVStyle = BitOR($LVS_NOCOLUMNHEADER, $LVS_REPORT, $LVS_SINGLESEL)
    $ExStyle = BitOR($LVS_EX_FULLROWSELECT, $WS_EX_DLGMODALFRAME, $LVS_EX_CHECKBOXES, $LVS_EX_DOUBLEBUFFER)
    $hListView = GUICtrlCreateListView(' | ', 5, 5, 390, 320, $LVStyle, $ExStyle)
    For $i = 0 To 19
    GUICtrlCreateListViewItem($i & '|Number' & Random(100, 999, 1), $hListView)
    GUICtrlSetOnEvent(-1, '_RefreshCounter')
    Next
    _GUICtrlListView_SetColumnWidth($hListView, 0, 50)
    _GUICtrlListView_SetColumnWidth($hListView, 1, 365)

    [/autoit] [autoit][/autoit] [autoit]

    $contextmenu = GUICtrlCreateContextMenu($hListView)
    GUICtrlCreateMenuItem('Mark All', $contextmenu)
    GUICtrlSetOnEvent(-1, '_MarkAll')
    GUICtrlCreateMenuItem('Mark Nothing', $contextmenu)
    GUICtrlSetOnEvent(-1, '_MarkNothing')

    [/autoit] [autoit][/autoit] [autoit]

    $hLabel = GUICtrlCreateLabel('0', 10, 340, 90, 24, $SS_CENTER, $WS_EX_DLGMODALFRAME)
    $hButton1 = GUICtrlCreateButton('Show All', 110, 340, 80, 24)
    GUICtrlSetOnEvent(-1, '_ShowAll')
    $hButton2 = GUICtrlCreateButton('Show checked Items', 200, 340, 120, 24)
    GUICtrlSetOnEvent(-1, '_ShowChecked')

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Sleep(20)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _End()
    Exit
    EndFunc ;==>_End

    [/autoit] [autoit][/autoit] [autoit]

    Func _RefreshCounter()
    Local $iCount = _GUICtrlListView_GetCheckedCount($hListView)
    GUICtrlSetData($hLabel, $iCount)
    EndFunc ;==>_RefreshCounter

    [/autoit] [autoit][/autoit] [autoit]

    Func _ShowAll()
    Local $aItems = _GUICtrlListView_GetAllItems($hListView)
    If IsArray($aItems) Then _ArrayDisplay($aItems)
    EndFunc ;==>_ShowAll

    [/autoit] [autoit][/autoit] [autoit]

    Func _ShowChecked()
    Local $aItems = _GUICtrlListView_GetCheckedItemsTextArray($hListView)
    If IsArray($aItems) Then _ArrayDisplay($aItems)
    EndFunc ;==>_ShowChecked

    [/autoit] [autoit][/autoit] [autoit]

    Func _MarkAll()
    _GUICtrlListView_SetItemChecked($hListView, -1, True)
    _RefreshCounter()
    EndFunc ;==>_MarkAll

    [/autoit] [autoit][/autoit] [autoit]

    Func _MarkNothing()
    _GUICtrlListView_SetItemChecked($hListView, -1, False)
    _RefreshCounter()
    EndFunc ;==>_MarkNothing

    [/autoit] [autoit][/autoit] [autoit]

    Func _GUICtrlListView_GetAllItems($hListView)
    Local $iCount = _GUICtrlListView_GetItemCount($hListView)
    Local $iColCount = _GUICtrlListView_GetColumnCount($hListView)
    If $iCount = 0 Then Return SetError(1, 0, 0)
    Local $aAllItems[$iCount][$iColCount], $aTemp
    For $i = 0 To $iCount - 1
    $aTemp = _GUICtrlListView_GetItemTextArray($hListView, $i)
    For $j = 1 To $aTemp[0]
    $aAllItems[$i][$j - 1] = $aTemp[$j]
    Next
    Next
    Return $aAllItems
    EndFunc ;==>_GUICtrlListView_GetAllItems

    [/autoit] [autoit][/autoit] [autoit]

    Func _GUICtrlListView_GetCheckedItemsTextArray($hListView)
    Local $aCheckedItems = _GUICtrlListView_GetCheckedIndices($hListView)
    Local $iCheckedCount = UBound($aCheckedItems)
    If $iCheckedCount = 0 Then Return SetError(1, 0, 0)
    Local $iColCount = _GUICtrlListView_GetColumnCount($hListView)
    Local $aCheckedItemsText[$iCheckedCount][$iColCount], $aTemp
    For $i = 0 To $iCheckedCount - 1
    $aTemp = _GUICtrlListView_GetItemTextArray($hListView, $aCheckedItems[$i])
    For $j = 1 To $aTemp[0]
    $aCheckedItemsText[$i][$j-1] = $aTemp[$j]
    Next
    Next
    Return $aCheckedItemsText
    EndFunc ;==>_GUICtrlListView_GetCheckedItemTextArray

    [/autoit] [autoit][/autoit] [autoit]

    Func _GUICtrlListView_GetCheckedIndices($hListView)
    Local $iCount = _GUICtrlListView_GetItemCount($hListView)
    Local $iCheckedCount = _GUICtrlListView_GetCheckedCount($hListView)
    If $iCheckedCount = 0 Then Return SetError(1, 0, 0)
    Local $aCheckedItems[$iCheckedCount]
    $iCheckedCount = 0
    For $i = 0 To $iCount - 1
    If _GUICtrlListView_GetItemChecked($hListView, $i) Then
    $aCheckedItems[$iCheckedCount] = $i
    $iCheckedCount += 1
    EndIf
    Next
    Return $aCheckedItems
    EndFunc ;==>_GUICtrlListView_GetCheckedIndices

    [/autoit] [autoit][/autoit] [autoit]

    Func _GUICtrlListView_GetCheckedCount($hListView)
    Local $iCount = _GUICtrlListView_GetItemCount($hListView), $iCheckedCount = 0
    If $iCount = 0 Then Return SetError(1, 0, 0)
    For $i = 0 To $iCount - 1
    $iCheckedCount += _GUICtrlListView_GetItemChecked($hListView, $i)
    Next
    Return $iCheckedCount
    EndFunc ;==>_GUICtrlListView_GetCheckedCount

    [/autoit]
    • Offizieller Beitrag

    Gefällt mir dein Beispiel. Hat aber einen Fehler, wenn kein Item angehakt ist ,kommt bei Show checked Items folgender Fehler :

    (90) : ==> Subscript used with non-Array variable.:

    • Offizieller Beitrag

    Nee, an der Stelle ist das ohne "-1" schon richtig. Ich habe nur ein wenig Error-Handling vergessen. :rolleyes:

    Hab's jetzt aber mal korrigiert.

    Edit: Du hattest recht mit dem "-1". Ich war schon völlig durcheinander mit dem einmal "0"-basierten-Array und einmal "1"-basierten-Array. Habe jetzt alles auf "0"-basierte-Arrays umgeschrieben.

  • Du kannst die ListView so noch beschleunigen beim hinzufügen:

    Spoiler anzeigen
    [autoit]

    _GUICtrlListView_BeginUpdate($LVHandle)
    _GUICtrlListView_SetItemCount($LVHandle,65000)
    For $i = 0 To 65000
    GUICtrlCreateListViewItem("data"&$i, $hListView)
    GUICtrlSetOnEvent(-1, '_RefreshCounter')
    Next
    _GUICtrlListView_SetColumnWidth($hListview, 0, 365)
    _GUICtrlListView_EndUpdate($LVHandle)

    [/autoit]


    ( aber maximal kannst du mit dieser Methode etwa 65000 Einträge machen. Für mehr musst du dann mit den UDF Inserts arbeiten, da AutoIt nicht mehr ControlIDs bereitstellt)
    //Edit: So geht die Abfrage etwas schneller:

    Spoiler anzeigen
    [autoit]

    ; Author: Oscar
    ; modified: Prog@ndy, used code from Gary Frost and Siao
    Func _GUICtrlListView_GetCheckedCount($hWnd)
    Local $iCount = _GUICtrlListView_GetItemCount($hWnd), $iCheckedCount = 0

    Local $tLVITEM = DllStructCreate($tagLVITEM)
    Local $iResult, $tMemMap, $pMemory, $pItem, $iSize
    $iSize = DllStructGetSize($tLVITEM)
    $pItem = DllStructGetPtr($tLVITEM)
    If @error Then Return SetError($LV_ERR, $LV_ERR, False)

    For $iIndex = 0 To $iCount-1
    DllStructSetData($tLVITEM, "Mask", $LVIF_STATE)
    DllStructSetData($tLVITEM, "Item", $iIndex)
    DllStructSetData($tLVITEM, "StateMask", 0x2000)
    If IsHWnd($hWnd) Then
    If _WinAPI_InProcess($hWnd, $_lv_ghLastWnd) Then
    If @AutoItUnicode Then
    $iResult = _SendMessage($hWnd, $LVM_GETITEMW, 0, $pItem, 0, "wparam", "ptr") <> 0
    Else
    $iResult = _SendMessage($hWnd, $LVM_GETITEMA, 0, $pItem, 0, "wparam", "ptr") <> 0
    EndIf
    Else
    $pMemory = _MemInit($hWnd, $iSize, $tMemMap)
    _MemWrite($tMemMap, $pItem)
    If @AutoItUnicode Then
    $iResult = _SendMessage($hWnd, $LVM_GETITEMW, 0, $pMemory, 0, "wparam", "ptr") <> 0
    Else
    $iResult = _SendMessage($hWnd, $LVM_GETITEMA, 0, $pMemory, 0, "wparam", "ptr") <> 0
    EndIf
    _MemRead($tMemMap, $pMemory, $pItem, $iSize)
    _MemFree($tMemMap)
    EndIf
    Else
    If @AutoItUnicode Then
    $iResult = GUICtrlSendMsg($hWnd, $LVM_GETITEMW, 0, $pItem) <> 0
    Else
    $iResult = GUICtrlSendMsg($hWnd, $LVM_GETITEMA, 0, $pItem) <> 0
    EndIf
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If Not $iResult Then ContinueLoop
    $iCheckedCount += (DllStructGetData($tLVITEM, "State")= 0x2000)
    Next
    Return $iCheckedCount
    EndFunc ;==>_GUICtrlListView_GetCheckedCount

    [/autoit]

    Einmal editiert, zuletzt von progandy (16. Dezember 2008 um 19:02)