Listview - temporär immer die zuletzt angeklickte einzelne Zeile einfärben - WM_NOTIFY ($NM_HOVER + $NM_KLICK)

  • Hallo, ^^

    Ich hab folgendes Problem:

    Ein mehr oder weniger klassischer Laden/Speichern Dialog bei dem der Focus dem Mauszeiger folgt. Es werden jedoch nicht Dateien, sondern Ordnerinhalte geladen bzw. gespeichert. Falls eine *.txt im Ordner, auf den das Listviewitem verweist, vorhanden ist, wird deren Inhalt in einem Edit angezeigt. Wird ein Item angeklickt, wird es in ein Edit übernommen.

    Jetzt aber das eigentliche Problem:

    Bewegt man den Mauszeiger schnell aus dem Listview heraus verbleibt der Focus ja auf dem zuletzt angeklickten Item. Tut man dies allerdings zu langsam, wandert der Focus wieder mit. Ich möchte aber, dass es in diesem Fall farblich hervorgehoben bleibt. Das liess sich per $NM_Click auch realisieren. Wird nun ein weiteres Item angeklickt soll die Farbmarkiereung natürlich dorthin springen. Und das krieg ich nicht hin (bzw. nur wenn ich das Listview bei $NM_Click noch vor dem Einfärben immer neu einlese und das ist suboptimal)

    EDIT: Ich dachte das ginge, geht aber nicht.

    Ich dachte aber eigentlich, dass es gehen müsste, dass ich das Listview bei jedem Klick erst komplett weiss einfärbe und dann das einzelne Item. Das funktioniert aber leider nicht, obwohl ich ehrlich gesagt nicht verseh warum. :(

    Spoiler anzeigen
    [autoit]


    Case $NM_CLICK ; Sent by a list-view control when the user clicks an item with the left mouse button
    Local $i_ListView
    ;-GUICtrlSetBkColor($hListView, 0xFFFFFF)
    ;~GUICtrlSetBkColor($hListView, 0xFFFF00) <===================== Hier ist wahrscheinlich das Problem (?) und ich versteh es net
    $selid = _GUICtrlListView_GetSelectionMark($hListView)
    $sel = _GUICtrlListView_GetItemTextArray($hListView, $selid)
    GUICtrlSetData($i_eingabe, $sel[1]) ; Item in Eingabe übernehmen

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

    If Not $i_ListView = Guictrlread($hListView) Then
    $i_ListView = Guictrlread($hListView)
    GUICtrlSetBkColor($i_ListView, 0x00FF00) ;Item einfärben
    Endif

    [/autoit]

    Es findet zwar ein Einfärben des Listviews statt, aber jedes einzeln eingefärbte Item verhält sich, als würde es nicht mehr zum Listview gehören und behält seine Farbe. Ich hoff jemand hat ne Idee, wie sich das umgehen lässt. :P

    Hier mal noch Screenshot + zip + kompletter Code zum einfachen testen.

    Spoiler anzeigen
    [autoit]

    #include <ButtonConstants.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <Guilistview.au3>
    #include <ListViewConstants.au3>
    #include <WindowsConstants.au3>
    #include <Array.au3>
    #Include <File.au3>

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

    #Region ### Load/Save Dialog ###
    $g_load_save = GUICreate("Test", 535, 296, 275, 190)
    ;+GUICtrlSetDefBkColor(0xFFFFFF, $g_load_save)
    $LVStyle = BitOR($LVS_SHOWSELALWAYS, $LVS_REPORT, $LVS_SINGLESEL, $LVS_NOCOLUMNHEADER, $LVS_NOSORTHEADER)
    $ExStyle = BitOR( $LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $LVS_EX_DOUBLEBUFFER, $LVS_EX_TRACKSELECT)
    $hListView = GUICtrlCreateListView("Name|Datum", 30, 22, 300, 175, $LVStyle, $ExStyle )
    $hLVHandle = GUICtrlGetHandle($hListView)
    _GUICtrlListView_SetColumn($hLVHandle, 0, "Name", 195, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 1, "Datum", 70, 0)
    _GUICtrlListView_RegisterSortCallBack($hLVHandle)
    $e_info = GUICtrlCreateEdit("", 344, 22, 167, 175, $ES_READONLY)
    GUICtrlSetBkColor(-1, 0xFFFFFF)
    $i_eingabe = GUICtrlCreateInput("", 30, 216, 200, 21)
    $Button1 = GUICtrlCreateButton("Listview befüllen", 30, 252, 113, 25, $WS_GROUP)
    $Button2 = GUICtrlCreateButton("Load", 152, 252, 113, 25, $WS_GROUP)
    $Button3 = GUICtrlCreateButton("Save", 278, 252, 113, 25, $WS_GROUP)
    GUISetState(@SW_SHOW)
    #EndRegion ### Load/Save Dialog ###

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

    Global $sel, $selid

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

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

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $Button1
    _gui_load_save()
    Case $GUI_EVENT_CLOSE
    Exit

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

    EndSwitch
    WEnd

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

    ;Listview für Load/save Dialog bestücken
    Func _gui_load_save()
    _GUICtrlListView_BeginUpdate($hLVHandle); Aktionen vor Benutzer verstecken
    _GUICtrlListView_DeleteAllItems($hListView)
    _GUICtrlListView_SetSelectionMark($hListView, -1)
    ;$aFileList=_FileListToArray(@ProgramsDir & "\Autoit3\");Ordner in Array einlesen ;"\[mod_v2_dat]\save_ig2userconfig_spielstaende"
    $aFileList=_FileListToArray(@ScriptDir, "*", 2)
    ;_ArrayDisplay($aFileList,"")
    If IsArray ($aFilelist) Then
    Dim $aFiledate[$aFilelist[0]+1]
    For $i = 1 To $aFilelist[0]
    $aFiledate[$i] = FileGetTime(@ScriptDir & "\" & $aFilelist[$i], 0, 1)
    $new = StringRegExpReplace($aFiledate[$i], "(\d{2})\.(\d{2})\.(\d{4})","$3/$2/$1")
    $aFiledate[$i] = StringTrimLeft(StringLeft($new, 8), 6) & "." & StringTrimLeft(StringLeft($new, 6), 4) & "." & StringTrimRight($new, 10) & " " & StringTrimRight(StringRight($new, 6), 4) & ":" & StringTrimRight(StringRight($new, 4), 2)
    GUICtrlCreateListViewItem($aFilelist[$i] & "|" & $aFiledate[$i], $hListView)
    Next
    Local $iCount = _GUICtrlListView_GetItemCount($hLVHandle) - 1 ; Anzahl der Listview-Einträge holen
    For $i = 0 To $iCount ; Schleife, um alle Listview-Einträge in sortierbares Datum umzuwandeln
    _GUICtrlListView_SetItemText($hLVHandle, $i, Date_German_2_AutoIt(_GUICtrlListView_GetItemText($hLVHandle, $i, 1)), 1)
    Next
    $Aufsteigend = True
    _GUICtrlListView_SimpleSort($hListView, $Aufsteigend,1);Einträge sortieren
    For $i = 0 To $iCount ; Schleife, um alle Listview-Einträge wieder ins das deutsche Format umzuwandeln
    _GUICtrlListView_SetItemText($hLVHandle, $i, Date_AutoIt_2_German(_GUICtrlListView_GetItemText($hLVHandle, $i, 1)), 1)
    Next
    _GUICtrlListView_EndUpdate($hLVHandle); Aktionen wieder sichtbar machen
    EndIf
    $fSelected = False
    _GUICtrlListView_SetItemSelected($hListView, -1, $fSelected)

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

    EndFunc ;==>_gui_load_save

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

    ;Datum von YYYY/MM/DD/HH/MM nach DD.MM.YYYY HH:MM umwandeln==============================================================================
    Func Date_AutoIt_2_German($conv_date)
    $conv_parts = StringSplit($conv_date, "/")
    ;_ArrayDisplay($conv_parts,"")
    Return $conv_parts[3] & "." & $conv_parts[2] & "." & $conv_parts[1] & " " & $conv_parts[4] & ":" & $conv_parts[5]
    EndFunc ;==>Date_AutoIt_2_German============================================================================================================

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

    ;Datum von DD.MM.YYYY HH:MM nach YYYY/MM/DD/HH/MM umwandeln===================================================================================
    Func Date_German_2_AutoIt($conv_date)
    $conv_parts = StringSplit($conv_date, "." & " " & ":")
    Return $conv_parts[3] & "/" & $conv_parts[2] & "/" & $conv_parts[1] & "/" & $conv_parts[4] & "/" & $conv_parts[5]
    EndFunc ;==>Date_German_2_AutoIt==============================================================================================================

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

    Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
    $hWndListView = $hListView
    If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)

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

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
    Case $hWndListView
    Switch $iCode
    Case $NM_CLICK ; Sent by a list-view control when the user clicks an item with the left mouse button
    Local $i_ListView
    ;-GUICtrlSetBkColor($hListView, 0xFFFFFF)
    ;~GUICtrlSetBkColor($hListView, 0xFFFF00) <===================== Hier ist wahrscheinlich das Problem (?) und ich versteh es net
    ;~GUICtrlSetDefBkColor(0xFFFF00, $g_load_save)
    ;~_WinAPI_RedrawWindow($g_load_save)
    $selid = _GUICtrlListView_GetSelectionMark($hListView)
    $sel = _GUICtrlListView_GetItemTextArray($hListView, $selid)

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

    GUICtrlSetData($i_eingabe, $sel[1])

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

    If Not $i_ListView = Guictrlread($hListView) Then
    $i_ListView = Guictrlread($hListView)
    GUICtrlSetBkColor($i_ListView, 0x00FF00)
    Endif
    Case $NM_HOVER
    Sleep(50)
    GUICtrlSetState($e_info , $GUI_ENABLE)
    $selid = _GUICtrlListView_GetSelectionMark($hListView)
    $sel = _GUICtrlListView_GetItemTextArray($hListView, $selid)

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

    If FileExists(@ScriptDir & "\" & $sel[1] & "\TXT.txt") Then
    GUICtrlSetData($e_info , FileRead(@ScriptDir & "\" & $sel[1] & "\TXT.txt"))
    GUICtrlSetState($e_info , $GUI_SHOW)
    Else
    GUICtrlSetState($e_info , $GUI_HIDE)
    Endif
    Case $WM_ERASEBKGND
    return 1
    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_NOTIFY

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

    Func _DebugPrint($s_text, $line = @ScriptLineNumber)
    ConsoleWrite( _
    "!===========================================================" & @LF & _
    "+======================================================" & @LF & _
    "-->Line(" & StringFormat("d", $line) & "):" & @TAB & $s_text & @LF & _
    "+======================================================" & @LF)
    EndFunc ;==>_DebugPrint

    [/autoit]

    autoit.de/wcf/attachment/9456/


    autoit.de/wcf/attachment/9457/


    Ich hab von _WinApi_Redraw (versteh ich aber nicht wirklich die Funktion :huh: ) und auch sonst vieles versucht, leider ohne Erfolg.

    Grüße,
    t002

  • Hallo t002,

    hast du schon den Stil $LVS_SHOWSELALWAYS getestet:

    Zitat von Hilfe

    $LVS_SHOWSELALWAYS 0x0008 Die Markierung, soweit vorhanden, wird immer angezeigt, auch wenn das Control nicht den Fokus hat.

    mfg (Auto)Bert

  • Hi Autobert,

    ja, also das sind die verwendeten Stile.

    [autoit]

    $LVStyle = BitOR($LVS_SHOWSELALWAYS, $LVS_REPORT, $LVS_SINGLESEL, $LVS_NOCOLUMNHEADER, $LVS_NOSORTHEADER)
    $ExStyle = BitOR( $LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $LVS_EX_DOUBLEBUFFER, $LVS_EX_TRACKSELECT)

    [/autoit]

    Soltte eigentlich also kein Stilproblem sein, oder?

    EDIT: Also ich hatte mich in meinem Eingangspost missverständlich ausgedrückt. Bei mir wandern Markierung + Focus mit dem Mauszeiger, um in "Echtzeit" (und ohne Klick auf das Item) den zum Item gehörenden Text im Edit anzuzeigen. Gibts dafür auch eine andere Lösung?

    Einmal editiert, zuletzt von t002 (12. Mai 2010 um 18:57)