Jump to content
Sign in to follow this  
Warpi

How to send a click to a SysListView32 Control

Recommended Posts

Warpi

Hi all!

I spent the whole day on searching and reading about how can I send a mouse double click SysListView32 Control, with a selected item, but cannot find anything.

Someone on this forum asked about the same problem a long time ago, but finally ... well I didn't read a solution in that thread.

I read a lot about windows msgs, may be I have to learn more about that because I am not familiar with them.

What I have is a window that opens a SysListView32 control. Using the ControlListView commands I can, for instance, read and select the items on the list.

The way to trigger an action from this control is to double click in one of its items. MouseClick is not good for this because the items change from time to time and same for the control position. Even more, the windows has scrollbars, so the item I need may be is not on sight. More or less the same for ControlClick, as it need some coords, if not it will click in the center of the control, hence, selecting a wrong item.

So, once I have selected the right item, how can I trigger a double click for the SysListView32 control, cannot I just "Send({DOUBLE_CLICK})" to it?

Thanks in advance.

Share this post


Link to post
Share on other sites
PsaltyDS

Get the control ID or ClassNameNN of the control with AutoItInfo tool and use it with ControlClick():

ControlClick("Your Window", "Some window text", "SysListView321", "Left", 2)

:)


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
Warpi

Get the control ID or ClassNameNN of the control with AutoItInfo tool and use it with ControlClick():

That was what I first thought, and I started coding with that in mind ... but it does not work as I expected :)

ControlClick() without coords just click in the center position of the control, so it select the item under its click which is 99.999% of the time the one I do not want :D

Giving the right coordinates to it is a pain, as they are not fixed :D

An option is to check in which row is the item I want to select, to calculate the coords and to use ControlClick crossing your fingers. A problem with this approach is that the control has scroll bars, so I have to be able to move them too :D

Share this post


Link to post
Share on other sites
PaulIA

That was what I first thought, and I started coding with that in mind ... but it does not work as I expected :)

ControlClick() without coords just click in the center position of the control, so it select the item under its click which is 99.999% of the time the one I do not want :D

Giving the right coordinates to it is a pain, as they are not fixed :D

An option is to check in which row is the item I want to select, to calculate the coords and to use ControlClick crossing your fingers. A problem with this approach is that the control has scroll bars, so I have to be able to move them too :D

Welcome to the forum. ControlClick is virtually useless on a ListView control and I'm not sure why it was even offered as a solution. You have to get the bounding rectangle of the item you want to click on and the only reliable way to do that is through the ListView API.

Auto3Lib has full support for the ListView control, including the ability to right/left/double click, etc. You can also right click an item in a ListView and control any popup menus. Plenty of examples and an AutoIt style help file are included. Check my signature for the download and feel free to PM me if you have any problems.

Edited by PaulIA

Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites
Warpi

Welcome to the forum.

Thanks :)

Auto3Lib has full support for the ListView control, including the ability to right/left/double click, etc.

Thank you very much for pointing me to your lib, Paul, it seems you have done a very good job, I will PM you if I cannot find a solution on myself.

Share this post


Link to post
Share on other sites
PsaltyDS

ControlClick is virtually useless on a ListView control and I'm not sure why it was even offered as a solution. You have to get the bounding rectangle of the item you want to click on and the only reliable way to do that is through the ListView API.

Although I put "SysListView321" in my example, I was actually thinking of the control ID of the ListViewItem, not the parent ListView. Does that still present the same problem using ControlClick() with the control ID of the ListViewItem?

:)


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
PaulIA

Although I put "SysListView321" in my example, I was actually thinking of the control ID of the ListViewItem, not the parent ListView. Does that still present the same problem using ControlClick() with the control ID of the ListViewItem?

:)

AutoIt does a lot of things to native Windows controls to make them easier for people to use. Assigning control IDs to ListView items is one of them. In the world outside of AutoIt, ListView items do not have control IDs and you reference them by their zero based index in the control. To click on an item, you have to make sure that it is visible, get the bounding rectangle of the item and then click within that rectangle. The _ListView_ClickItem UDF in Auto3Lib does all that for you. Edited by PaulIA

Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites
PsaltyDS

I see, said the blind man... :)

Thanks for the clarification.

:D


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
eltorro

Here's something to try:

Func ListClick($hListView, $iItem = 0)
    Local $x, $y, $pos = _GuiCtrlListViewGetSubItemRect($hListView,$iItem)
    if IsArray($pos) Then
        Local $mPos = MouseGetPos()
        Local $wPos = _WinGetClientPos("","")
        Local $cPos = ControlGetPos("","",$hListView)
        $x = $wPos[0]+$cpos[0]+$pos[0]+10 ;this will check a check box
        $y = $wPos[1]+$cpos[1]+$pos[1]+7
        MouseClick("primary",$x,$y,1,0)
        MouseMove($mPos[0],$mPos[1],0)
    EndIf
EndFunc

;get the client pos relative to the desktop.
Func _WinGetClientPos($sTitle="",$sText= "")
       Local $aPos[2]
        Local $wPos = WinGetPos($sTitle,$sText)
        Local $wSize = WinGetClientSize($sTitle,$sText)
         $aPos[0] = $wPos[0]+($wPos[2]-$wSize[0])
         $aPos[1] = $wPos[1]+($wPos[3]-$wSize[1])
         Return $aPos
EndFunc
;===============================================================================
; Function Name:    _GUICtrlListViewGetSubItemRect
; Description:     Get the bounding rect of a listview item
; Parameter(s):    $h_listview    - IN -
;                        $row            - IN -
;                        $col             - IN -
; Requirement(s):
; Return Value(s):  an array with x ,y (relative to control), w,h or 0 on failure
; User CallTip:
; Author(s):
; Note(s):
;===============================================================================
Func _GUICtrlListViewGetSubItemRect($hlistview, $row, $col=0)
    Local $h_listview = 0
    If Not IsHWnd($hlistview) then 
        $h_ListView = HWnd($hListView)
        If @error then Return SetError(1,0,0)
    Else
        $h_listview = $hListView
    EndIf

    Local $rectangle, $rv,$aRect[4]
    $rectangle = DllStructCreate("int;int;int;int") ;left, top, right, bottom
    DllStructSetData($rectangle, 1, $LVIR_BOUNDS)
    DllStructSetData($rectangle, 2, $col)
    If IsHWnd($h_listview) Then
        Local $a_ret = DllCall("user32.dll", "int", "SendMessage", "hwnd", $h_listview, "int", $LVM_GETSUBITEMRECT, "int", $row, "ptr", DllStructGetPtr($rectangle))
        $rv = $a_ret[0]
    Else
        $rv = GUICtrlSendMsg($h_listview, $LVM_GETSUBITEMRECT, $row, DllStructGetPtr($rectangle))
    EndIf
    if $rv Then
        ReDim $aRect[4]
        $aRect[0] = DllStructGetData($rectangle, 1)
        $aRect[1] = DllStructGetData($rectangle, 2)
        $aRect[2] = DllStructGetData($rectangle, 3)
        $aRect[3] = DllStructGetData($rectangle, 4) - $aRect[1]
        $rectangle = 0
        Sleep(10)
        Return $aRect
    EndIf
    Return 0
EndFunc   ;==>_GUICtrlListViewGetSubItemRec
;===============================================================================

Edit: removed a gui name.

Edited by eltorro

Share this post


Link to post
Share on other sites
Warpi

Auto3Lib has full support for the ListView control, ...

Just one word: impressive.

It works, with just one function: _ListView_ClickItem()

Many many thanks, Paul.

BTW, eltoro, thanks for you code, however I prefer instead to use just a function call :)

Share this post


Link to post
Share on other sites
eltorro

That's ok. :)

Essentially, it is one call though.

ListClick($hListView, $iItem )

Share this post


Link to post
Share on other sites
RS200Z

I have been using _ListView_ClickItem function from A3Lib for some time now. With the release of AutoIt v3.2.10.0, almost all functions of A3Lib (except String) are suppose to be included in AutoIt already. However, I couldn't find a similar function for this. Can some expert point me to the right direction?

Share this post


Link to post
Share on other sites
PsaltyDS

I have been using _ListView_ClickItem function from A3Lib for some time now. With the release of AutoIt v3.2.10.0, almost all functions of A3Lib (except String) are suppose to be included in AutoIt already. However, I couldn't find a similar function for this. Can some expert point me to the right direction?

There are now functions in the _GuiCtrlListView_* section to select items (which is what happens when you click on them). Because a ListView can have multiple items selected, and the item wanted may not be visible (if the ListView is scrolled), I think the process is to select the item(s) with _GuiCtrlListView_SetItemSelected() instead.

:P


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
LOULOU

There are now functions in the _GuiCtrlListView_* section to select items (which is what happens when you click on them). Because a ListView can have multiple items selected, and the item wanted may not be visible (if the ListView is scrolled), I think the process is to select the item(s) with _GuiCtrlListView_SetItemSelected() instead.

:P

It dosen't work with _GuiCtrlListView_SetItemSelected() , only the item is selected not like in library from Paul1A

May be ithis function has to be supported in udf but actually not .

Share this post


Link to post
Share on other sites
PsaltyDS

It dosen't work with _GuiCtrlListView_SetItemSelected() , only the item is selected not like in library from Paul1A

May be ithis function has to be supported in udf but actually not .

I don't have time to set up a demo script to test with right now, my theory was that you would _GuiCtrlListView_SetItemSelected() any item(s) you want selected (which works for you, it appears) and then just ControlClick() the ListView itself (not trying to hit an item). Your scripts GuiGetMsg() loop or event function would be responsible to read the control for which item(s) selected (or the app you are automating).

Even if I code a demo, it will be with an internal AuotIt GUI and may not show your situation in automating an external GUI from another app.

:P


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
Fossil Rock

Apparently I'm not the only one having to adjust to the new version (nothing wrong with it, just have to modify some code).

Well I have this;

_ListView_ClickItem($list, _ListView_FindInText($list, $results[$row][1]), "left", False, 2)

which double clicks on an item when it finds it (all in one statement).

So now I need to replace it with something in the new version. _GuiCtrlListView_SetItemSelected() will select it, the question is... is there a _GUICtrlListView_ClickItem or do I now have to send the clicks separately? I haven't found it in the help file yet, so if you already know - please share.

Edited by Fossil Rock

Agreement is not necessary - thinking for one's self is!

My-Colors.jpg

cuniform2.gif

Share this post


Link to post
Share on other sites
LOULOU

Apparently I'm not the only one having to adjust to the new version (nothing wrong with it, just have to modify some code).

Well I have this;

_ListView_ClickItem($list, _ListView_FindInText($list, $results[$row][1]), "left", False, 2)

which double clicks on an item when it finds it (all in one statement).

So now I need to replace it with something in the new version. _GuiCtrlListView_SetItemSelected() will select it, the question is... is there a _GUICtrlListView_ClickItem or do I now have to send the clicks separately? I haven't found it in the help file yet, so if you already know - please share.

]_ListView_ClickItem was in the old version of paul1A lib but now can't be use and was not ported in UDF. Maybe if you are strong in programming you can port the function from the lib to an UDF? For my own i try but i fail to port.

Share this post


Link to post
Share on other sites
PsaltyDS

I'm not having any trouble selecting items, or reading the selections on command, but I can't figure out how to get any events to fire on the ListView. This is the demo being played with:

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

Opt('MustDeclareVars', 1)
Opt("GuiOnEventMode", 1)

Global $hGUI, $hListView, $IdButton

$hGUI = GUICreate("(Internal) ListView Set Item Selected", 400, 300)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Quit")

GUICtrlCreateLabel("UDF ListView:", 10, 10, 380, 20)
$hListView = _GUICtrlListView_Create($hGUI, "", 10, 40, 380, 200, BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS))
GUICtrlSetOnEvent($hListView, "_ListViewEvent")
_GUICtrlListView_AddColumn($hListView, "Items", 100)
For $n = 0 To 19
    _GUICtrlListView_AddItem($hListView, "Item " & $n)
    ; Select all even 6 thru 14
    If ($n > 5) And ($n < 15) And (Mod($n, 2) = 0) Then _GUICtrlListView_SetItemSelected($hListView, $n)
Next

$IdButton = GUICtrlCreateButton("Read Data", 150, 260, 100, 30)
GUICtrlSetOnEvent(-1, "_ButtonHit")

GUISetState()

While 1
    Sleep(20)
WEnd

Func _ListViewEvent()
    ConsoleWrite("Debug: _ListViewEvent() triggered" & @LF)
    Local $sSelected = _GUICtrlListView_GetSelectedIndices($hListView, False)
    TrayTip("Selected", $sSelected, 5)
EndFunc   ;==>_ListViewEvent

Func _ButtonHit()
    ConsoleWrite("Debug: _ButtonHit() triggered" & @LF)
    Local $sSelected = _GUICtrlListView_GetSelectedIndices($hListView, False)
    TrayTip("Selected", $sSelected, 5)
EndFunc   ;==>_ButtonHit

Func _Quit()
    Exit
EndFunc   ;==>_Quit

:P


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
Fossil Rock

ControlClick(_GuiCtrlListView_SetItemSelected($list, _GUICtrlListView_FindInText($list, $results[$row][1])), "", "left", 2)

This is my replacement line that selects the correct item, but it doesn't double click it.

I'm testing send("{ENTER}") for the click now, but it seems to send the enter before the line is selected.

Gotta love those workarounds.... :P


Agreement is not necessary - thinking for one's self is!

My-Colors.jpg

cuniform2.gif

Share this post


Link to post
Share on other sites
PsaltyDS

ControlClick(_GuiCtrlListView_SetItemSelected($list, _GUICtrlListView_FindInText($list, $results[$row][1])), "", "left", 2)

This is my replacement line that selects the correct item, but it doesn't double click it.

I'm testing send("{ENTER}") for the click now, but it seems to send the enter before the line is selected.

Gotta love those workarounds.... :P

The _GuiCtrlListView_SetItemSelected() only returns True or False. How do you use that for WinTitle in your ControlClick()?

;)


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  

×