Sign in to follow this  
Followers 0
Metal

ListView get change in checking items

13 posts in this topic

in my script i made a listview with checkboxes for each item. Now, i need to know if one of the checkboxes change it's status, how can i do?

my first try was to save the starting checkboxes status, then (in gui's while1-loop) confronting actual checkboxes status with the starting-saved one, so i can catch check-status changes.

But that's not so performant...

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

in my script i made a listview with checkboxes for each item. Now, i need to know if one of the checkboxes change it's status, how can i do?

my first try was to save the starting checkboxes status, then (in gui's while1-loop) confronting actual checkboxes status with the starting-saved one, so i can catch check-status changes.

But that's not so performant...

First register WM_NOTIFY if is isn't already,

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

then I think this works

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

    $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, $NM_DBLCLK; Sent by a list-view control when the user clicks an item with the left mouse button
    Local $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
    Local $iIndex = DllStructGetData($tInfo, "Index")

    If $iIndex <> -1 Then
    Local $iX = DllStructGetData($tInfo, "X")
    Local $iPart = 1
    If _GUICtrlListView_GetView($hListView1) = 1 Then $iPart = 2 ;for large icons view

    Local $aIconRect = _GUICtrlListView_GetItemRect($hListView1, $iIndex, $iPart)
    
    If $iX < $aIconRect[0] And $iX >= 4 Then;not sure about 4, but if in this range of x then click is on icon
 somefunctionToRecordCheckBoxChange($iIndex)
    ; Return 1
    EndIf
    EndIf

    
    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY

EDIT: Maybe LVN_ITEMCHANGED works for checkboxes as PsaltyDS suggested, but it doesn't work if you have icons and click on them. (Tested on a script where I uses my own icons for checkboxes.)

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

ok, i think i'm understanding.

To have no doubt, "somefunctionToRecordCheckBoxChange($iIndex)" is where i pass the index (0-based or 1-based?) of the clicked checkbox (the one that changed it's state) to another function i made?

Share this post


Link to post
Share on other sites

Can't he just use the GUICtrlSetOnEvent? This is given you use GUI OnEvent-mode, but I always do :mellow:

$checkbox = GUICtrlCreateCheckbox("", 0, 0, 20)
GUICtrlSetOnEvent($checkbox, "HandleCheckbox")

Can you show the way you would do that for checkboxes in a listview?

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Use both messages: $LVN_ITEMCHANGING and $LVN_ITEMCHANGED.

#Include <GUIConstantsEx.au3>
#Include <GUIListView.au3>
#Include <WindowsConstants.au3>

Opt('MustDeclareVars', 1)

Global $State, $Button, $ListView, $hListView

GUICreate('MyGUI', 280, 391)
$ListView = GUICtrlCreateListView('', 10, 10, 260, 344, BitOR($LVS_DEFAULT, $LVS_NOCOLUMNHEADER), $WS_EX_CLIENTEDGE)
$hListView = GUICtrlGetHandle(-1)
_GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_CHECKBOXES, $LVS_EX_DOUBLEBUFFER, $LVS_EX_INFOTIP))
_GUICtrlListView_InsertColumn($hListView, 0, '', 234)
$Button = GUICtrlCreateButton('OK', 105, 361, 70, 23)

For $i = 1 To 5
    _GUICtrlListView_AddItem($hListView, 'Item' & $i)
Next

_GUICtrlListView_SetItemChecked($hListView, 1, 1)
_GUICtrlListView_SetItemChecked($hListView, 2, 1)
_GUICtrlListView_SetItemChecked($hListView, 4, 1)

GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')

GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

    Local $tNMITEMACTIVATE = DllStructCreate($tagNMITEMACTIVATE, $lParam)
    Local $hWndFrom = DllStructGetData($tNMITEMACTIVATE, 'hWndFrom')
    Local $Index = DllStructGetData($tNMITEMACTIVATE, 'Index')
    Local $Code = DllStructGetData($tNMITEMACTIVATE, 'Code')

    Switch $hWndFrom
        Case $hListView
            Switch $Code
                Case $LVN_ITEMCHANGING
                    $State = _GUICtrlListView_GetItemChecked($hListView, $Index)
                Case $LVN_ITEMCHANGED
                    If $State <> _GUICtrlListView_GetItemChecked($hListView, $Index) Then
                        ConsoleWrite('Item' & ($Index + 1) & ' - ' & (Not $State) & @CR)
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
1 person likes this

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Can you show the way you would do that for checkboxes in a listview?

Like this:

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

Opt("GUIOnEventMode", 1)

$gui = GUICreate("test", 250, 250)
GUISetOnEvent($GUI_EVENT_CLOSE, "ExitGUI")

$listView = GUICtrlCreateListView("test", 10, 10, 200, 200, Default, $LVS_EX_CHECKBOXES)
For $x = 1 To 5
  $item = GUICtrlCreateListViewItem("item_" & $x, $listView)
  GUICtrlSetOnEvent($item, "HandleClicks")
Next

GUISetState()

Do
  Sleep(100) ; wait for events
Until 0 = 1

Func ExitGUI()
  GUIDelete(@GUI_WinHandle)
  Exit
EndFunc

Func HandleClicks()
  MsgBox(0,0, @GUI_CtrlID)
EndFunc

You could also use @GUI_CtrlHandle in the HandleClicks() function.

~ edit

Hm, as I now add the listener to the ListView-item rather than only the checkbox (not possible in this situation), it also triggers when you simply click the item text instead of the checkbox. That seems undesirable. I initially didn't read the checkboxes are inside a Listview, so perhaps the message stuff is better. Though this is easier :mellow:

Edited by d4ni

Share this post


Link to post
Share on other sites

Like this:

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

Opt("GUIOnEventMode", 1)

$gui = GUICreate("test", 250, 250)
GUISetOnEvent($GUI_EVENT_CLOSE, "ExitGUI")

$listView = GUICtrlCreateListView("test", 10, 10, 200, 200, Default, $LVS_EX_CHECKBOXES)
For $x = 1 To 5
 $item = GUICtrlCreateListViewItem("item_" & $x, $listView)
 GUICtrlSetOnEvent($item, "HandleClicks")
Next

GUISetState()

Do
 Sleep(100) ; wait for events
Until 0 = 1

Func ExitGUI()
 GUIDelete(@GUI_WinHandle)
 Exit
EndFunc

Func HandleClicks()
 MsgBox(0,0, @GUI_CtrlID)
EndFunc

You could also use @GUI_CtrlHandle in the HandleClicks() function.

~ edit

Hm, as I now add the listener to the ListView-item rather than only the checkbox (not possible in this situation), it also triggers when you simply click the item text instead of the checkbox. That seems undesirable. I initially didn't read the checkboxes are inside a Listview, so perhaps the message stuff is better. Though this is easier :mellow:

Ok, but that doesn't tell if the checkbox was ticked so you would still need to add some extra code to read the state of the checkbox. But even so, it could be that this would be easier than what I suggested.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Easier isn't always better though :mellow: As I pointed out in my previous post; the HandleClicks() function is called even when you only click the text, not the checkbox. Therefore it might not be providing the exact functionality he wants. If your solution does only do something when you click the checkbox, yours should be preferred.

Share this post


Link to post
Share on other sites

Hello,

I adopted the script with the HandleClick for my own script, and it works ... but I can't differ if the checkbox is checked or not.

I tested the other code with the notify, but this works only on Item1 to set it true or not.

It doesn't matter which examples of these I use, but one of them should work.

Any Ideas, to get one of them work full ?

Share this post


Link to post
Share on other sites

Oh, I just find out, that the WM_Notify Version does it job, if I compile it without x64

Share this post


Link to post
Share on other sites

this is what i use

you can eliminate sendmessage to get checked state by using LVN_ITEMCHANGED NMLISTVIEW struct

use GetItemState* or LVN_ITEMCHANGED to get state

added martins replacement state image icons to example

martin, i think the problem your having is the image index is set by SetItemStateImage,

but not the state value (8192 or 4096) in _GUICtrlListView_SetItemStateImage

i dont think you need SetItemStateImage once you change the imagelist,

just use _GUICtrlListView_SetItemChecked

*for on demand checkbox state:

use _GUICtrlListView_GetItemState($hWndFrom, $iItem, $LVIS_STATEIMAGEMASK)

instead of _GUICtrlListView_GetItemChecked to get checkbox state

(less code - one sendmessage instead of struct and sendmessage)

returns 8192 for checked or 4096 for unchecked

#Include <GUIConstantsEx.au3>
#Include <GUIListView.au3>
#Include <WindowsConstants.au3>
#include <GuiImageList.au3>


Opt('MustDeclareVars', 1)

Global $State, $Button, $ListView, $hListView

GUICreate('MyGUI', 280, 391)
$ListView = GUICtrlCreateListView('', 10, 10, 260, 344, BitOR($LVS_DEFAULT, $LVS_NOCOLUMNHEADER), $WS_EX_CLIENTEDGE)
$hListView = GUICtrlGetHandle(-1)
_GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_CHECKBOXES, $LVS_EX_DOUBLEBUFFER, $LVS_EX_INFOTIP))
_GUICtrlListView_InsertColumn($hListView, 0, '', 234)
$Button = GUICtrlCreateButton('OK', 105, 361, 70, 23)

Global $hImage = _GUIImageList_Create(16, 16, 5, 3)
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 131)
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 110)
_GUICtrlListView_SetImageList($hListView, $hImage, 2)


For $i = 1 To 5
    _GUICtrlListView_AddItem($hListView, 'Item' & $i)
Next

_GUICtrlListView_SetItemChecked($hListView, 1, 1)
_GUICtrlListView_SetItemChecked($hListView, 2, 1)
_GUICtrlListView_SetItemChecked($hListView, 4, 1)

ConsoleWrite('+ ItemState 4 = ' & _GUICtrlListView_GetItemState($hListView, 4, $LVIS_STATEIMAGEMASK) & @crlf )

GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

    Local $tNMHDR, $hWndFrom, $IDFrom, $Code, $tNMLISTVIEW, $iItem
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $Code = DllStructGetData($tNMHDR, "Code")
    ;$IDFrom = DllStructGetData($tNMHDR, "IDFrom")

    Switch $hWndFrom
        Case $hListView
            Switch $Code
                Case $LVN_ITEMCHANGED
                    $tNMLISTVIEW = DllStructCreate($tagNMLISTVIEW, $lParam)
                    $iItem = DllStructGetData($tNMLISTVIEW, "Item")
                    If BitAND(DllStructGetData($tNMLISTVIEW, "Changed"), $LVIF_STATE) = $LVIF_STATE Then
                        Switch DllStructGetData($tNMLISTVIEW, "NewState")
                            Case 8192 ;item checked
                                ConsoleWrite('Item ' & $iItem & ' - ' & True & @CR)
                            Case 4096 ;item unchecked
                                ConsoleWrite('Item ' & $iItem & ' - ' & False & @CR)
                        EndSwitch
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
1 person likes this

I see fascists...

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  
Followers 0