Jump to content
Sign in to follow this  

List view, selected item, and keyboard

Recommended Posts

Hi all,

I have a list view in which I delete items and move items to the end. When items are moved or deleted I want the focused item to be the one following the moved or deleted item. So I delete the item, create one at the end, and use _GUICtrlListView_SetItemState to set selected and focused state on the item following the one that was moved. When I move using the button, it works as desired. However, when I use the CTRL+End key, when I read back the status after setting it it is set, and the state on the last item is clear, but the last item is still highlighted. What do I need to do so that I don't lose my place in the list view when I use the CTRL+END key? Below is a test script that I hope illustrates what I mean. The script initially sets the focus on the second item. Then push the move button. The second item moves to the end and what was the 3rd item is selected as desired. Then restart the script but use the CTRL+END key while focused on the list view. The second item moves to the end of the list and what was the 3rd item should be selected (and focused), but instead the last item is selected.

I'm using WINXP SP3.

[update: I added code (updated below) to allow underline to also move to the end. It does not have the same problem as CTRL+END. It does emit a ding, which CTRL+END does not. Any idea why the ding? I assume CTRL+END is behaving the way it is because the list view processes arrow keys even though I'm catching LVN_KEYDOWN. Is there any way to get it to not do that processing when I catch the key?]

[Okay, I got rid of the references to LbC.au3. (Layout by Code is a library designed to assist blind programmers with GUI layout. It can generate code to make the UI so that it doesn't have to be included.)]



; 6/5/11 Test changing selection in a list view.

#include <GUIConstantsEx.au3>
#include <ListviewConstants.au3>
#include <GuiListview.au3>
#include <WindowsConstants.au3>

Global Const $VK_SHIFT = 16
Global Const $VK_CONTROL = 17
Global Const $VK_MENU = 18
Global Const $VK_SPACE = 0x20
Global Const $VK_PRIOR = 33
Global Const $VK_NEXT = 34
Global Const $VK_END = 35
Global Const $VK_HOME = 36
Global Const $VK_LEFT = 37
Global Const $VK_UP = 38
Global Const $VK_RIGHT = 39
Global Const $VK_DOWN = 40
Global Const $VK_DELETE = 46

Global $ghForm, $gIdLV, $ghLV, $gIdMsg


Func Main()
    $ghForm = GUICreate("Test list view focus and selection change", 531, 372, 246, 181)
    $gIdLV = GUICtrlCreateListView("Item text", 14, 14, 300, 120)
    $ghLV = GUICtrlGetHandle($gIdLV)
    For $i = 0 To 4
        GUICtrlCreateListViewItem("Item " & $i, $gIdLV)
    Next ; $i
    GUICtrlCreateLabel("This tests whether the display changes as a result of programatically setting focus and selected item state.", 14, 148, 497, 16, 0x50020100, 0x00000000)
    GUICtrlCreateLabel("When I delete or move an item to the end I want the focus and selection to be on the item following it.", 14, 172, 478, 16, 0x50000100, 0x00000000)
    Local $IdMoveBtn = GUICtrlCreateButton("Move to end", 14, 196, 100, 16, 0x50010F00, 0x00000000)
    Local $IdDeleteBtn = GUICtrlCreateButton("Delete", 122, 196, 100, 16, 0x50010F00, 0x00000000)
    GUICtrlCreateLabel("Msg", 14, 226, 20, 16, 0x50020100, 0x00000000)
    $gIdMsg = GUICtrlCreateEdit("", 40, 226, 300, 100, 0x503110C4, 0x00000000)

    GUIRegisterMsg($WM_NOTIFY, "WMNotify")

    Msg("Item 1 should have focus and be selected")
    While 1
        Local $iMsg = GUIGetMsg()
        Switch $iMsg
            Case 0

            Case $GUI_EVENT_CLOSE
            Case $IdMoveBtn
                Msg("Move button pressed.")
            Case $IdDeleteBtn
                Msg("Delete button pressed.")
EndFunc   ;==>Main

Func Msg($s)
    GUICtrlSetData($gIdMsg, $s & @CRLF, 1)
EndFunc   ;==>Msg

Func SelItem($iItem, $fFlag = True)
    Local $iState
    If $fFlag Then
        $iState = $giMask
        $iState = 0
    Msg("Setting state of item " & $iItem & " to " & $iState)
    _GUICtrlListView_SetItemState($ghLV, $iItem, $iState, $giMask)
EndFunc   ;==>SelItem

Func Move()
    Local $iFirst = _GUICtrlListView_GetNextItem($ghLV)
    Local $sItm = _GUICtrlListView_GetItemTextString($ghLV, $iFirst)
    Local $iLast = _GUICtrlListView_GetItemCount($ghLV) ; get index of next added item.
    GUICtrlCreateListViewItem($sItm, $gIdLV)
    Msg("After selecting item " & $iFirst & ", its state is " & _GUICtrlListView_GetItemState($ghLV, $iFirst, $giMask))
    Msg("  State of item " & $iLast & ", is " & _GUICtrlListView_GetItemState($ghLV, $iLast, $giMask))
EndFunc   ;==>Move

Func Delete()
    Local $iFirst = _GUICtrlListView_GetNextItem($ghLV)
    Msg("After selecting item " & $iFirst & ", its state is " & _GUICtrlListView_GetItemState($ghLV, $iFirst, $giMask))
EndFunc   ;==>Delete

Func WmNotify($hWnd, $iMsg, $iWParam, $iLParam)
    Local $tagNM = DllStructCreate($tagNMHDR, $iLParam)
    If DllStructGetData($tagNM, "IdFrom") = $gIdLV Then
        Switch DllStructGetData($tagNM, "Code")
            Case $LVN_KEYDOWN
                ;Dbg("LVN_KEYDOWN") ; debug
                $tagNM = DllStructCreate($tagNMLVKEYDOWN, $iLParam)
                Local $iKey = DllStructGetData($tagNM, "VKey")
                Local $fControl = BitAND(GetKeyState($VK_CONTROL), 0x8000)
                Local $fShift = BitAND(GetKeyState($VK_SHIFT), 0x8000)
                Local $fAlt = BitAND(GetKeyState($VK_MENU), 0x8000)
                If Not $fControl And Not $fAlt And Not $fShift Then
                    Switch $iKey
                        Case $VK_DELETE
                            Msg("Delete key")
                            Return 0
                        Case Else
                            Return $GUI_RUNDEFMSG
                EndIf ; no modifiers

                If Not $fControl And Not $fAlt And $fShift Then
                    Msg("Shift+" & $iKey)
                    Switch $iKey
                        Case 189
                            Msg("_ key")
                            Return 0
                        Case Else
                            Return $GUI_RUNDEFMSG
                EndIf ; Shift

                If $fControl And Not $fShift And Not $fAlt Then
                    Msg("CTRL+" & $iKey)
                    Switch $iKey
                        Case $VK_END ; CTRL+END
                            Return 0
                                Case $VK_UP ; CTRL+UP
                                Return 0
                                Case $VK_DOWN ; CTRL+DOWN
                                Return 0
                        Case Else
                            Return $GUI_RUNDEFMSG
                    EndSwitch ; $iKey
                EndIf ; $fControl

        EndSwitch ; code
EndFunc   ;==>WmNotify

; Adapted from WINApi.au3 function _WinAPI_GetAsyncKeyState.
; Return is a short; if MSB (bit 15, 0x8000) is set the key is down, if bit 0 is 1 a toggle key (like caps lock) is toggled (on).
Func GetKeyState($iKey)
    Local $aResult = DllCall("user32.dll", "short", "GetKeyState", "int", $iKey)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc   ;==>GetKeyState
Edited by GaryC

Share this post

Link to post
Share on other sites

Put your demo script in SciTE4AutoIt3 and hit Ctrl-F5 to do syntax check. Re-post it after eliminating the errors.


Edit: Sorry, I missed that you were already going to update it.

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...