Jump to content
Sign in to follow this  
Spiff59

Listview Highlight tracking

Recommended Posts

Spiff59

I chopped up the ListView example script just to show what I'm after. I simply want the script to be aware of which ListView row is selected at all times. Searching, I found a few examples, but some seemed overly complex, some are outdated and don't run under 3.3.0.0.

So, in the example below, a simple WM_NOTIFY function handles mouse clicks just fine. What's the cleanest way to also handle the highlighted row changing due to the up and down arrow keys? I'm guessing I'll be monitoring the listview for some focus event and processing the message with WM_COMMAND?

Or ???

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

Global $listview, $Current_Row = -1

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUICreate("", 220, 180)
$listview = GUICtrlCreateListView("hdg1    |hdg2       |hdg3       ", 10, 10, 200, 120)
$item0 = GUICtrlCreateListViewItem("item0|item0-1|item0-2", $listview)
$item1 = GUICtrlCreateListViewItem("item1|item1-1|item1-2", $listview)
$item2 = GUICtrlCreateListViewItem("item2|item2-1|item2-2", $listview)
$item3 = GUICtrlCreateListViewItem("item3|item3-1|item3-2", $listview)
$item4 = GUICtrlCreateListViewItem("item4|item4-1|item4-2", $listview)
$listview = GUICtrlGetHandle($listview)

GUICtrlCreateLabel("Row selected:", 40, 150, 80, 16)
$Label_Row = GUICtrlCreateLabel("", 125, 150, 40, 16)
GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exitloop
    EndSwitch
    If $Current_Row > -1 Then 
        GUICtrlSetData($Label_Row,$Current_Row)
        $Current_Row = -1
    EndIf
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $listview
            Switch $iCode
                Case -155 
                    Beep(660,50)
                Case $NM_CLICK 
                    Beep(800,50)
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    $aHit = _GUICtrlListView_SubItemHitTest($listview)
                    If $aHit[0] > -1 Then $Current_Row = $aHit[0]
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc
Edited by Spiff59

Share this post


Link to post
Share on other sites
Spiff59

Nevermind!

I found by using _GUICtrlListView_GetSelectionMark I can get the results I'm after with only a few lines of code.

#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>
#include <array.au3>

Global $listview, $Row_Changed

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUICreate("", 220, 180)
$listview = GUICtrlCreateListView("hdg1    |hdg2       |hdg3       ", 10, 10, 200, 120)
$item0 = GUICtrlCreateListViewItem("item0|item0-1|item0-2", $listview)
$item1 = GUICtrlCreateListViewItem("item1|item1-1|item1-2", $listview)
$item2 = GUICtrlCreateListViewItem("item2|item2-1|item2-2", $listview)
$item3 = GUICtrlCreateListViewItem("item3|item3-1|item3-2", $listview)
$item4 = GUICtrlCreateListViewItem("item4|item4-1|item4-2", $listview)
$listview = GUICtrlGetHandle($listview)

GUICtrlCreateLabel("Row selected:", 40, 150, 80, 16)
$Label_Row = GUICtrlCreateLabel("", 125, 150, 40, 16)
GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exitloop
    EndSwitch
    If $Row_Changed Then 
        GUICtrlSetData($Label_Row,_GUICtrlListView_GetSelectionMark($listview))
        $Row_Changed = 0
    EndIf
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $listview
            Switch $iCode
                Case -155 
                    $Row_Changed = 1
                Case $NM_CLICK 
                    $Row_Changed = 1
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Share this post


Link to post
Share on other sites
rover

The listview notification for key events is LVN_KEYDOWN (see _GUICtrlListView_GetHotItem() example)

you could optionally use GUICtrlCreateDummy instead of a global and

filter out all key events from triggering except for arrow/pgup/pgdn/end/home

Cheers

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

;Constants.au3
Global Const $VK_PRIOR = 0x21
Global Const $VK_NEXT = 0x22
Global Const $VK_END = 0x23
Global Const $VK_HOME = 0x24
Global Const $VK_LEFT = 0x25
Global Const $VK_UP = 0x26
Global Const $VK_RIGHT = 0x27
Global Const $VK_DOWN = 0x28

Global $hlistview

GUICreate("", 220, 180)
$clistview = GUICtrlCreateListView("hdg1       |hdg2       |hdg3       ", 10, 10, 200, 120)
$item0 = GUICtrlCreateListViewItem("item0|item0-1|item0-2", $clistview)
$item1 = GUICtrlCreateListViewItem("item1|item1-1|item1-2", $clistview)
$item2 = GUICtrlCreateListViewItem("item2|item2-1|item2-2", $clistview)
$item3 = GUICtrlCreateListViewItem("item3|item3-1|item3-2", $clistview)
$item4 = GUICtrlCreateListViewItem("item4|item4-1|item4-2", $clistview)
$hlistview = GUICtrlGetHandle($clistview)

GUICtrlCreateLabel("Row selected:", 40, 150, 80, 16)
$Label_Row = GUICtrlCreateLabel("", 125, 150, 40, 16)

$cLVKeyDown = GUICtrlCreateDummy()

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exitloop
        Case $cLVKeyDown
            GUICtrlSetData($Label_Row, GUICtrlSendMsg($clistview, $LVM_GETSELECTIONMARK, 0, 0))
    ;GUICtrlSetData($Label_Row, _SendMessage($hlistview, $LVM_GETSELECTIONMARK))
    EndSwitch
WEnd


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $tNMHDR, $hWndFrom, $iIDFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    
    Switch $hWndFrom
        Case $hlistview
            Switch $iCode
                Case $NM_CLICK
                    GUICtrlSendToDummy($cLVKeyDown)
                Case $LVN_KEYDOWN
            ;Virtual-Key Codes
            ;http://msdn.microsoft.com/en-us/library/ms645540(VS.85).aspx
                    Switch BitAND(DllStructGetData(DllStructCreate($tagNMLVKEYDOWN, $ilParam), "VKey"), 0xFFFF);VKey LoWord is keycode
                ;up/dn/pgup/pgdn/home/end keys only
                ;Case $VK_UP, $VK_PRIOR, $VK_DOWN, $VK_NEXT, $VK_END, $VK_HOME
                        Case $VK_PRIOR To $VK_DOWN
                            GUICtrlSendToDummy($cLVKeyDown)
                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc
Edited by rover

I see fascists...

Share this post


Link to post
Share on other sites
Spiff59

Oh, that's pretty slick! This is more in line with what I expected to use when I posted the first message in this thread.

I'd never seen the dummy functions used before, they seem a great way to build and trigger custom events.

I'll certaily be playing with (and using) this.

Thanks.

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  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.