Anfängerfragen zu Listen in GUIs

  • Hallo Zusammen,

    bisher bin ich in meinen AutoIt-Scripten immer um GUIs herumgekommen, doch nun habe ich mich rangewagt und je mehr Beispiele ich mir anschaue und ausprobiere, desto weniger funktioniert in meinem ersten Versuch :(

    Ich möchte einfach eine Liste erzeugen, wo jede einzelne Zeile angehakt werden kann. Anhaken sollte auch durch nen Doppelklick passieren. Zum Schluß will ich irgendwie abfragen, welches Element angehakt ist.

    Gibt es irgendwo noch schöne Beispiele? In der FAQ und im Tutorial habe ich zu anhakbaren Listen nichts gefunden.

    So sieht mein Gerüst aus:

    Spoiler anzeigen
    [autoit]


    #include <GuiConstants.au3>

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

    Dim $MyArray[4]
    $MyArray[0] = "|Software 1|Version 1| Datum 1|"
    $MyArray[1] = "|Software 2 mit ganz langem|Version 2| Datum 2|"
    $MyArray[2] = "|Software 3|Version 3| Datum 3|"
    $MyArray[3] = "|Software 4|Version 4| Datum 4|"

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

    GUICreate("Softwareliste", 400, 400)

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

    ; LIST VIEW
    $listView = GUICtrlCreateListView("Auswahl|Software|Version|Datum|", 20, 20, 350, 200, BitOR($LVS_SHOWSELALWAYS, $LBS_MULTIPLESEL ), BitOR( $LVS_EX_CHECKBOXES, $LVS_EX_FULLROWSELECT))

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

    ; ListeItems erzeugen
    For $i = 0 To UBound($MyArray) - 1
    GUICtrlCreateListViewItem($MyArray[$i], $listView)
    Next

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

    ; Run the GUI until the dialog is closed
    GUISetState()
    While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    Wend

    [/autoit]


    - Wie schaffe ich es, daß die CheckBoxen auch angehakt werden, wenn ich die Zeile markiere? Oder erst bei einem Doppelklick?

    - Wie frage ich die CheckBoxen ab bzw. kann man die CheckBoxen geschickter lösen?

    - Wie schaffe ich unterschiedliche Farben für die Zeilen, also immer abwechselnd? Im Help steht was von $GUI_BKCOLOR_LV_ALTERNATE, doch wenn ich das in der Option Style oder ExStyle setze, dann erscheint garnichts mehr.

    - Wie macht man einen Resize des Fensters, sodaß die Spalten die optimale Breite haben bzw. das ganze Listitem

    Besten Dank schon mal
    skyteddy

    • Offizieller Beitrag

    Mit ListView hast Du dir gleiche eine schwersten ausgesucht!

    Um hier klicks abzufangen muss man einen neuen Eventhandle registrieren. Ich habe mal die Grundfunktion hinzugefügt.

    Schau die in der Hilfe mal die Funktionen an die mit _GUICtrlListView... beginnen!

    Spoiler anzeigen
    [autoit]


    #include <GuiConstants.au3>
    #Include <GuiListView.au3>

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

    Global Const $WM_NOTIFY = 0x004E
    ;ListView Events
    Global Const $NM_FIRST = 0
    Global Const $NM_LAST = (-99)
    Global Const $NM_OUTOFMEMORY = ($NM_FIRST - 1)
    Global Const $NM_CLICK = ($NM_FIRST - 2)
    Global Const $NM_DBLCLK = ($NM_FIRST - 3)
    Global Const $NM_RETURN = ($NM_FIRST - 4)
    Global Const $NM_RCLICK = ($NM_FIRST - 5)
    Global Const $NM_RDBLCLK = ($NM_FIRST - 6)
    Global Const $NM_SETFOCUS = ($NM_FIRST - 7)
    Global Const $NM_KILLFOCUS = ($NM_FIRST - 8)
    Global Const $NM_CUSTOMDRAW = ($NM_FIRST - 12)
    Global Const $NM_HOVER = ($NM_FIRST - 13)
    Global Const $NM_NCHITTEST = ($NM_FIRST - 14)
    Global Const $NM_KEYDOWN = ($NM_FIRST - 15)
    Global Const $NM_RELEASEDCAPTURE = ($NM_FIRST - 16)
    Global Const $NM_SETCURSOR = ($NM_FIRST - 17)
    Global Const $NM_CHAR = ($NM_FIRST - 18)
    Global Const $NM_TOOLTIPSCREATED = ($NM_FIRST - 19)

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

    Dim $MyArray[4]
    $MyArray[0] = "|Software 1|Version 1| Datum 1|"
    $MyArray[1] = "|Software 2 mit ganz langem|Version 2| Datum 2|"
    $MyArray[2] = "|Software 3|Version 3| Datum 3|"
    $MyArray[3] = "|Software 4|Version 4| Datum 4|"

    GUICreate("Softwareliste", 400, 400)

    ; LIST VIEW
    $listView = GUICtrlCreateListView("Auswahl|Software|Version|Datum|", 20, 20, 350, 200, BitOR($LVS_SHOWSELALWAYS, $LBS_MULTIPLESEL ), BitOR($LVS_EX_CHECKBOXES, $WS_EX_CLIENTEDGE, $LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))

    ; ListeItems erzeugen
    For $i = 0 To UBound($MyArray) - 1
    GUICtrlCreateListViewItem($MyArray[$i], $listView)
    If Mod($i,2) Then GUICtrlSetBkColor(-1, 0xdddddd) ; jede 2. Zeile grau färben
    Next

    ; Run the GUI until the dialog is closed
    GUISetState()

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

    ;Register WM_NOTIFY events
    GUIRegisterMsg($WM_NOTIFY, "WM_Notify_Events")

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

    While 1
    $msg = GUIGetMsg()
    Select
    case $msg = $GUI_EVENT_CLOSE
    ExitLoop

    case $msg = $listView
    MsgBox(0,"","ListView")

    EndSelect
    Wend

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

    ; WM_NOTIFY event handler
    Func WM_Notify_Events($hWndGUI, $MsgID, $wParam, $lParam)
    #forceref $hWndGUI, $MsgID, $wParam
    Local $tagNMHDR, $event, $hwndFrom, $code
    $tagNMHDR = DllStructCreate("int;int;int", $lParam);NMHDR (hwndFrom, idFrom, code)
    If @error Then Return
    $event = DllStructGetData($tagNMHDR, 3)
    Switch $wParam

    Case $listView

    If $event = $NM_CLICK Then ; Doppelklick ist $NM_DBLCLK
    If _GUICtrlListViewGetCheckedState ($listView, _GUICtrlListViewGetCurSel($listView)) Then
    _GUICtrlListViewSetCheckState ( $listView, _GUICtrlListViewGetCurSel($listView), 0) ; Checkbox deaktivieren
    Else
    _GUICtrlListViewSetCheckState ( $listView, _GUICtrlListViewGetCurSel($listView), 1) ; Checkbox aktivieren
    Endif
    EndIf

    EndSwitch
    $tagNMHDR = 0
    $event = 0
    $lParam = 0
    EndFunc ;==>WM_Notify_Events

    [/autoit]
  • Hallo Ihr Zwei!

    Vielen Dank erstmal.

    BugFix . Dein Script ist ja so komplex, daß ich bis jetzt noch nicht durchgestiegen bin. Fast jeden 2ten Befehl muß ich im Help nachschauen. Umpf :)

    Bernd. Jow, deine Ergänzungen haben schon mal was! Danke :)
    Aber es hat noch irgendwie nen gravierenden Fehler, nämlich immer dann, wenn ich nicht den Doppelklick benutze, sondern die Haken einzeln setze, dann werden manchmal ganz wüste Mehrfachselektionen gemacht. Weißt Du warum?

    Nen Finish-Knopf einbauen schaffe ich wahrscheinlich noch, aber wie frage ich dann die angehakten Elemente ab?

    Besten Dank nochmal!
    R@iner

    • Offizieller Beitrag
    Zitat

    Original von skyteddy
    ...

    Bernd. Jow, deine Ergänzungen haben schon mal was! Danke :)
    Aber es hat noch irgendwie nen gravierenden Fehler, nämlich immer dann, wenn ich nicht den Doppelklick benutze, sondern die Haken einzeln setze, dann werden manchmal ganz wüste Mehrfachselektionen gemacht. Weißt Du warum?

    Nen Finish-Knopf einbauen schaffe ich wahrscheinlich noch, aber wie frage ich dann die angehakten Elemente ab?

    Besten Dank nochmal!
    R@iner

    Für

    Doppelklick muss Du

    [autoit]

    If $event = $NM_CLICK Then

    [/autoit]


    durch

    [autoit]

    If $event = $NM_DBLCLK Then

    [/autoit]


    ersetzen

    auf die angehakten Elemente kann man z.B. so zugreifen:

    [autoit]

    For $iIndex = 0 To _GUICtrlListViewGetItemCount($listView) - 1
    If _GUICtrlListViewGetCheckedState($listView,$iIndex) Then
    <Aktionen>
    EndIf
    Next

    [/autoit]


    Spoiler anzeigen
    [autoit]


    #include <GuiConstants.au3>
    #Include <GuiListView.au3>

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

    Global Const $WM_NOTIFY = 0x004E
    ;ListView Events
    Global Const $NM_FIRST = 0
    Global Const $NM_LAST = (-99)
    Global Const $NM_OUTOFMEMORY = ($NM_FIRST - 1)
    Global Const $NM_CLICK = ($NM_FIRST - 2)
    Global Const $NM_DBLCLK = ($NM_FIRST - 3)
    Global Const $NM_RETURN = ($NM_FIRST - 4)
    Global Const $NM_RCLICK = ($NM_FIRST - 5)
    Global Const $NM_RDBLCLK = ($NM_FIRST - 6)
    Global Const $NM_SETFOCUS = ($NM_FIRST - 7)
    Global Const $NM_KILLFOCUS = ($NM_FIRST - 8)
    Global Const $NM_CUSTOMDRAW = ($NM_FIRST - 12)
    Global Const $NM_HOVER = ($NM_FIRST - 13)
    Global Const $NM_NCHITTEST = ($NM_FIRST - 14)
    Global Const $NM_KEYDOWN = ($NM_FIRST - 15)
    Global Const $NM_RELEASEDCAPTURE = ($NM_FIRST - 16)
    Global Const $NM_SETCURSOR = ($NM_FIRST - 17)
    Global Const $NM_CHAR = ($NM_FIRST - 18)
    Global Const $NM_TOOLTIPSCREATED = ($NM_FIRST - 19)

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

    Dim $MyArray[4]
    $MyArray[0] = "|Software 1|Version 1| Datum 1|"
    $MyArray[1] = "|Software 2 mit ganz langem|Version 2| Datum 2|"
    $MyArray[2] = "|Software 3|Version 3| Datum 3|"
    $MyArray[3] = "|Software 4|Version 4| Datum 4|"

    GUICreate("Softwareliste", 400, 400)

    ; LIST VIEW
    $listView = GUICtrlCreateListView("Auswahl|Software|Version|Datum|", 20, 20, 350, 200, BitOR($LVS_SHOWSELALWAYS, $LBS_MULTIPLESEL ), BitOR($LVS_EX_CHECKBOXES, $WS_EX_CLIENTEDGE, $LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))

    ; ListeItems erzeugen
    For $i = 0 To UBound($MyArray) - 1
    GUICtrlCreateListViewItem($MyArray[$i], $listView)
    If Mod($i,2) Then GUICtrlSetBkColor(-1, 0xdddddd) ; jede 2. Zeile grau färben
    Next

    $ButSelAll = GUICtrlCreateCheckbox("Alle de-/markieren", 25, 225)
    $ButFinish = GUICtrlCreateButton("Finish",25,300,80)

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

    ; Run the GUI until the dialog is closed
    GUISetState()

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

    ;Register WM_NOTIFY events
    GUIRegisterMsg($WM_NOTIFY, "WM_Notify_Events")

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

    While 1
    $msg = GUIGetMsg()
    Select
    case $msg = $GUI_EVENT_CLOSE
    ExitLoop

    case $msg = $listView
    MsgBox(0,"","ListView")

    Case $msg = $ButSelAll
    if BitAND(GUICtrlRead($ButSelAll),$GUI_CHECKED) = $GUI_CHECKED Then
    $bAllChecked = 1
    Else
    $bAllChecked = 0
    Endif

    For $iIndex = 0 To _GUICtrlListViewGetItemCount($listView) - 1
    _GUICtrlListViewSetCheckState ( $listView, $iIndex, $bAllChecked)
    Next

    Case $msg = $ButFinish
    $Output = ""
    For $iIndex = 0 To _GUICtrlListViewGetItemCount($listView) - 1
    If _GUICtrlListViewGetCheckedState($listView,$iIndex) Then $Output &= String($iIndex + 1) & " "
    Next

    If StringLen($Output) Then
    MsgBox(0,"","Zeilen " & $Output & "sind markiert!")

    EndIf

    case Else
    ;;;;;;;;

    EndSelect
    Wend

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

    ; WM_NOTIFY event handler
    Func WM_Notify_Events($hWndGUI, $MsgID, $wParam, $lParam)
    #forceref $hWndGUI, $MsgID, $wParam
    Local $tagNMHDR, $event, $hwndFrom, $code
    $tagNMHDR = DllStructCreate("int;int;int", $lParam);NMHDR (hwndFrom, idFrom, code)
    If @error Then Return
    $event = DllStructGetData($tagNMHDR, 3)
    Switch $wParam

    Case $listView

    If $event = $NM_CLICK Then ; Doppelklick ist $NM_DBLCLK
    If _GUICtrlListViewGetCheckedState ($listView, _GUICtrlListViewGetCurSel($listView)) Then
    _GUICtrlListViewSetCheckState ( $listView, _GUICtrlListViewGetCurSel($listView), 0) ; Checkbox deaktivieren
    Else
    _GUICtrlListViewSetCheckState ( $listView, _GUICtrlListViewGetCurSel($listView), 1) ; Checkbox aktivieren
    Endif
    _GUICtrlListViewSetItemSelState($listView, _GUICtrlListViewGetCurSel($listView), 0) ; Zeilenmarkierung aufheben, kann bei Doppelklick deaktiviert werden
    EndIf

    EndSwitch
    $tagNMHDR = 0
    $event = 0
    $lParam = 0
    EndFunc ;==>WM_Notify_Events

    [/autoit]
  • Hallo Bernd,

    vielen Dank für Deinen Code. Das hätte ich in Tagen nicht hinbekommen. Damit komme ich jetzt schon irgendwie klar, allerdings suche ich seit einer Stunde den Fehler, daß keine mehrfaches Häckchensetzen in der linken Spalte möglich ist. Es geht immer nur einen Haken zu setzen, dann werden alle anderen gelöscht. Das Hakensetzen über nen Click funktioniert schon mal ganz gut.

    Danke schon mal!
    skyteddy

    @huggy. Danke für Deinen Tipp, aber das Hilfebeispiel hilft mir da noch nicht. Das Tutorial hatte ich vorher schon durch. Es ist leider auch etwas mager, genauso wie die FAQ. Das Thema GUI ist halt sehr komplex, da werde ich noch ein paar Abende brauchen, um mich da durchzufieseln. Die Beispiele in der Hilfe sind ja nicht schlecht, aber manchmal halt zu simpel. Aber das wird schon :)

    Einmal editiert, zuletzt von skyteddy (10. Mai 2007 um 17:46)

    • Offizieller Beitrag
    Zitat

    Original von skyteddy
    Es geht immer nur einen Haken zu setzen, dann werden alle anderen gelöscht.

    Hmm, poste doch mal deinen aktuellen Code.

    Hier mal ein einfaches Beispiel, mehrfaches markieren geht hier problemlos.

    Spoiler anzeigen
    [autoit]


    #include <guiconstants.au3>
    #Include <GuiListView.au3>
    GUICreate("ListView Test", 600, 400)
    $lvTEST = GUICtrlCreateListView("Out|Gerätename|Herst.-SN|Info", 10, 10, 580, 385,BitOR($LVS_SHOWSELALWAYS, $LBS_MULTIPLESEL ), _
    BitOR($LVS_EX_CHECKBOXES, $WS_EX_CLIENTEDGE, $LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))
    GUICtrlSetTip(-1, "Sortieren mit Klick auf den Spaltenkopf")
    _GUICtrlListViewSetColumnWidth(-1,0,40)
    _GUICtrlListViewSetColumnWidth(-1,1,150)
    _GUICtrlListViewSetColumnWidth(-1,2,150)
    _GUICtrlListViewSetColumnWidth(-1,3,236)
    _GUICtrlListViewJustifyColumn (-1, 0, 2)
    _GUICtrlListViewJustifyColumn (-1, 2, 1)
    _SetData()
    Dim $DESCENDING[_GUICtrlListViewGetSubItemsCount ($lvTEST) ] ; notwendig für sortieren durch Klick auf Spaltenkopf

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

    GUISetState()

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

    While 1
    $msg = GUIGetMsg()
    Select
    Case $msg = $GUI_EVENT_CLOSE
    Exit
    Case $msg = $lvTEST
    ; Sortierung mit Klick auf Spaltenkopf
    ; ACHTUNG!! Checkbox wird NICHT mitsortiert, wenn nichts weiter in der Spalte steht!!
    _GUICtrlListViewSort($lvTEST, $DESCENDING, GUICtrlGetState($lvTEST))

    EndSelect
    WEnd

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

    Func _SetData()
    GUICtrlCreateListViewItem("A|Gerät1|123456|blabla", $lvTEST)
    GUICtrlCreateListViewItem("B|Gerät2|123457|hlahhw", $lvTEST)
    GUICtrlCreateListViewItem("C|Gerät3|123458|b,sa,dm", $lvTEST)
    GUICtrlCreateListViewItem("D|Gerät4|123459|wtrrew", $lvTEST)
    GUICtrlCreateListViewItem("E|Gerät5|123450|adsgw", $lvTEST)
    GUICtrlCreateListViewItem("F|Gerät6|123410|lqopwhs", $lvTEST)
    GUICtrlCreateListViewItem("G|Gerät7|123411|mybffa", $lvTEST)
    GUICtrlCreateListViewItem("H|Gerät8|123412|qqwtze", $lvTEST)
    EndFunc

    [/autoit]
  • Hallo bugfix,

    das Beispiel schaue ich mir nach dem Abendessen gleich nochmal an. Mein aktueller Code ist immer noch der von Bernd. Dort funktioniert das Setzen des Hakens durch Anklicken der Reihe, leider aber nicht das Setzen der Haken durch klicken auf den Haken selber. Wahrscheinlich ist es nur ne Kleinigkeit. Aber je mehr ich dort bei den Styles rumexperimentiere, desto schlimmer wird es.

    Besten Dank und viele Grüße!
    skyteddy

    • Offizieller Beitrag

    Das Problem liegt in der Funktion WM_Notify_Events, einfach die Funktion durch diese ersetzen dann sollte es gehen!

    [autoit]

    ; WM_NOTIFY event handler
    Func WM_Notify_Events($hWndGUI, $MsgID, $wParam, $lParam)
    #forceref $hWndGUI, $MsgID, $wParam
    Local $tagNMHDR, $event, $hwndFrom, $code
    $tagNMHDR = DllStructCreate("int;int;int", $lParam);NMHDR (hwndFrom, idFrom, code)
    If @error Then Return
    $event = DllStructGetData($tagNMHDR, 3)
    Switch $wParam

    Case $listView
    If $event = $NM_CLICK And _GUICtrlListViewGetCurSel($listView) > -1 Then ; Einfachklick links auf eine Zeile -> für Doppelklick $NM_CLICK duch $NM_DBCLCK ersetzen
    If _GUICtrlListViewGetCheckedState ($listView, _GUICtrlListViewGetCurSel($listView)) Then
    _GUICtrlListViewSetCheckState ( $listView, _GUICtrlListViewGetCurSel($listView), 0) ; Checkbox deaktivieren
    Else
    _GUICtrlListViewSetCheckState ( $listView, _GUICtrlListViewGetCurSel($listView), 1) ; Checkbox aktivieren
    Endif
    _GUICtrlListViewSetItemSelState($listView, _GUICtrlListViewGetCurSel($listView), 0) ; Zeilenmarkierung aufheben
    EndIf

    EndSwitch
    $tagNMHDR = 0
    $event = 0
    $lParam = 0
    EndFunc ;==>WM_Notify_Events

    [/autoit]
  • Hallo Bernd,

    super, vielen Dank, jetzt funktioniert es und ich versteh zunehmend Deinen Code. Ich werd mal am Wochenende weiterschreiben und bei Problemen melde ich mich wieder.

    Nochmals herzlichen Dank und viele Grüße nach W.
    skyteddy