ListView - Editieren von N SubItems in N ListViews

  • Hallo,

    basierend auf BugFix's Code von hier, habe ich etwas geschrieben, womit sich die SubItems mehrerer ListViews editieren lassen. Etwas unschön ist die Verwendung globaler Variablen, aber mir ist leider keine bessere Lösung eingefallen. Es werden nun aber keine Hotkeys mehr verwendet und der Code wurde an ein paar Stellen verbessert.

    Ein Problem besteht allerdings noch: Und zwar erscheint das Input-Feld auch dann, wenn ich auf leere ListView-SubItems klicke (d.h. nicht existente Items) das Editieren ist dann natürlich nicht möglich. Hat jemand eine Idee, wie man dies abfangen könnte? Hier erstmal der Code:

    Spoiler anzeigen
    [autoit]

    #include-once
    #include <GUIConstantsEx.au3>
    #include <GUIListView.au3>
    #include <WindowsConstants.au3>

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

    ;~ Script by BugFix <autoit.de> - Modified by teh_hahn

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

    Global $ah_lviews[2] ;~ Required for WM_NOTIFY
    Global $ah_lvedit = 0 ;~ Required for _GUICtrlListView_EditShow
    Global $ai_guiopts = 0, $h_gui = 0 ;~ Required for _GUICtrlListView_EditHide
    Global $i_idfrom = 0, $i_index = 0, $i_subitem = 0 ;~ Required for _GUICtrlListView_EditEnter

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

    Exit main()

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

    Func OnAutoItStart()
    Opt("MustDeclareVars", 1)
    EndFunc ;==>OnAutoItStart

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

    Func main()
    Local $h_lview0 = 0, $h_lview1 = 0
    Local $as_data0[3][3] = [["Hans Meiser", "12345", "Musterstadt"],["Hans Meiser", "12345", "Musterstadt"],["Hans Meiser", "12345", "Musterstadt"]]
    Local $as_data1[1][3] = [["Ilona Christen", "09876", "Testhausen"]]

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

    $h_gui = GUICreate("GUICtrlCreateListView Edit", 640, 480)
    GUICtrlCreateTab(0, 0, 640, 480)

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

    GUICtrlCreateTabItem("First")
    $h_lview0 = GUICtrlCreateListView("", 10, 30, 620, 400, $LVS_REPORT)
    _GUICtrlListView_AddColumn($h_lview0, "Name", 70)
    _GUICtrlListView_AddColumn($h_lview0, "PLZ", 140)
    _GUICtrlListView_AddColumn($h_lview0, "Ort", 70)
    _GUICtrlListView_AddArray($h_lview0, $as_data0)

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

    GUICtrlCreateTabItem("Second")
    $h_lview1 = GUICtrlCreateListView("", 10, 30, 620, 400, $LVS_REPORT)
    _GUICtrlListView_AddColumn($h_lview1, "Name", 70)
    _GUICtrlListView_AddColumn($h_lview1, "PLZ", 140)
    _GUICtrlListView_AddColumn($h_lview1, "Ort", 70)
    _GUICtrlListView_AddArray($h_lview1, $as_data1)
    GUICtrlCreateTabItem("")
    $ah_lvedit = _GUICtrlListView_EditCreate($h_gui)

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

    $ah_lviews[0] = $h_lview0
    $ah_lviews[1] = $h_lview1
    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

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

    GUISetState()

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

    While 1
    If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
    WEnd
    EndFunc ;==>main

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

    Func _GUICtrlListView_EditCreate(ByRef Const $H_PARENT)
    Local Const $I_OPTGCM = Opt("GUICoordMode")
    Local Const $I_OPTGOEM = Opt("GUIOnEventMode")
    Opt("GUICoordMode", 1)
    Opt("GUIOnEventMode", 1)

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

    Local $ah_lvedit[2]
    $ah_lvedit[0] = GUICreate("", 20, 17, -1, -1, $WS_POPUP, $WS_EX_TOPMOST, $H_PARENT)
    $ah_lvedit[1] = GUICtrlCreateInput("", 0, 0, 20, 17)
    GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)
    GUICtrlSetOnEvent(-1, "_GUICtrlListView_EditEnter")

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

    GUISetOnEvent($GUI_EVENT_CLOSE, "_GUICtrlListView_EditHide")
    GUISwitch($H_PARENT)

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

    Opt("GUICoordMode", $I_OPTGCM)
    Opt("GUIOnEventMode", $I_OPTGOEM)
    Return $ah_lvedit
    EndFunc ;==>_GUICtrlListView_EditCreate

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

    Func _GUICtrlListView_EditEnter()
    _GUICtrlListView_EditHide()
    _GUICtrlListView_SetItemText($i_idfrom, $i_index, GUICtrlRead(@GUI_CtrlId), $i_subitem) ;~ ToDo: Global variablea!
    EndFunc ;==>_GUICtrlListView_EditEnter

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

    Func _GUICtrlListView_EditHide()
    GUISetState(@SW_ENABLE, $h_gui) ;~ ToDo: Global variable!
    GUISetState(@SW_HIDE, @GUI_WinHandle)
    Opt("GUICloseOnESC", $ai_guiopts[0]) ;~ ToDo: Global variable!
    Opt("GUICoordMode", $ai_guiopts[1]) ;~ ToDo: Global variable!
    Opt("GUIOnEventMode", $ai_guiopts[2]) ;~ ToDo: Global variable!
    EndFunc ;==>_GUICtrlListView_EditHide

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

    Func _GUICtrlListView_EditShow(ByRef Const $H_LVIEW, ByRef Const $i_idfrom, ByRef Const $i_index, ByRef Const $i_subitem)
    Local Const $H_HWND = WinGetHandle("[ACTIVE]")
    GUISetState(@SW_DISABLE, $H_HWND)

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

    Global $ai_guiopts[3] = [Opt("GUICloseOnESC"), Opt("GUICoordMode"), Opt("GUIOnEventMode")] ;~ ToDo: Global variable!
    Opt("GUICloseOnESC", 1)
    Opt("GUICoordMode", 1)
    Opt("GUIOnEventMode", 1)

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

    Local Const $AI_POSGUI = WinGetPos($H_HWND)
    Local Const $AI_POSLVIEW = ControlGetPos($H_HWND, "", $H_LVIEW)
    Local Const $AV_LVIEWCOL = _GUICtrlListView_GetColumn($i_idfrom, $i_subitem)

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

    Local $i_width = 0
    For $i = 0 To $i_subitem - 1
    $i_width += _GUICtrlListView_GetColumnWidth($i_idfrom, $i)
    Next

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

    Local Const $I_POSX = $AI_POSGUI[0] + $AI_POSLVIEW[0] + $i_width + 5
    WinMove($ah_lvedit[0], "", $I_POSX, MouseGetPos(1), $AV_LVIEWCOL[4], 17)
    GUICtrlSetData($ah_lvedit[1], _GUICtrlListView_GetItemText($i_idfrom, $i_index, $i_subitem))

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

    GUISetState(@SW_SHOW, $ah_lvedit[0])
    EndFunc ;==>_GUICtrlListView_EditShow

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

    Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $wParam

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

    Local Const $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local Const $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    Local Const $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    Local Const $iCode = DllStructGetData($tNMHDR, "Code")

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

    Local $hWndListView = 0
    For $i = 0 To UBound($ah_lviews) - 1
    $hWndListView = $ah_lviews[$i]
    If Not IsHWnd($hWndListView) Then $hWndListView = GUICtrlGetHandle($hWndListView)
    If $hWndFrom = $hWndListView Then
    Switch $iCode
    Case $NM_CLICK ;~ Single click
    Case $NM_DBLCLK ;~ Double click
    Local $tInfo = DllStructCreate($tagNMITEMACTIVATE, $lParam)
    $i_idfrom = $iIDFrom ;~ ToDo: Global variable!
    $i_index = DllStructGetData($tInfo, "Index") ;~ ToDo: Global variable!
    $i_subitem = DllStructGetData($tInfo, "SubItem") ;~ ToDo: Global variable!
    Return _GUICtrlListView_EditShow($hWndListView, $i_idfrom, $i_index, $i_subitem)
    EndSwitch
    EndIf
    Next

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

    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_NOTIFY

    [/autoit]

    • Offizieller Beitrag

    Hallo teh_hahn,
    die Lösung liegt, wie meist, ganz in der Nähe. Wenn du außerhalb des existierenden Listviewbereiches klickst wird Index -1 zurückgegeben. Das Abfragen und schon klappts:

    Spoiler anzeigen
    [autoit]

    Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $wParam

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

    Local Const $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local Const $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    Local Const $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    Local Const $iCode = DllStructGetData($tNMHDR, "Code")

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

    Local $hWndListView = 0
    For $i = 0 To UBound($ah_lviews) - 1
    $hWndListView = $ah_lviews[$i]
    If Not IsHWnd($hWndListView) Then $hWndListView = GUICtrlGetHandle($hWndListView)
    If $hWndFrom = $hWndListView Then
    Switch $iCode
    Case $NM_CLICK ;~ Single click
    Case $NM_DBLCLK ;~ Double click
    Local $tInfo = DllStructCreate($tagNMITEMACTIVATE, $lParam)
    $i_idfrom = $iIDFrom ;~ ToDo: Global variable!
    $i_index = DllStructGetData($tInfo, "Index") ;~ ToDo: Global variable!
    $i_subitem = DllStructGetData($tInfo, "SubItem") ;~ ToDo: Global variable!
    If $i_index < 0 Then Return ; ####### Das ist die Lösung #############################
    Return _GUICtrlListView_EditShow($hWndListView, $i_idfrom, $i_index, $i_subitem)
    EndSwitch
    EndIf
    Next

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

    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_NOTIFY

    [/autoit]