Jump to content

Example to manage Clicks and DoubleCliks events on TreeView Items


Recommended Posts

The rules:

-The all TreeviewItems you want to manage must be created in a loop (because next created Ctrl has CtrlID+=1 , then u can get the first and last CtrlId for a faster test in main loop)

-so you may need to store TreeviewItems Ctrl IDs in an array for a faster search.

-$TVS_DISABLEDRAGDROP must be set for your Treeview, why ? answer follows

How it works:

If $TVS_DISABLEDRAGDROP is set for a treeview then the PRIMARYDOWN Msg isn't sent when you click on a Treeview Item, but is sent if you DblClk...

Then i test, when the PRIMARYDOWN comes and mousecursor is over a TVI (TreeviewItem) using the TV_Hittest Msg.

; Exemple to capture TreeViewItem Clicks & DoubleClick without GUIRegisterMsg($WM_NOTIFY, "WM_Notify_Events_manager")
; using AutoIt3 beta
; by Lemon.fr

;#include "C:\Program Files\AutoIt3\Include\GUIConstants.au3"
#include <GUIConstants.au3>
; TV msgs
Const $TV_FIRST = 0x1100
Const $TVM_SELECTITEM = ($TV_FIRST + 11)
Const $TVM_HITTEST = ($TV_FIRST + 17)
Const $TVGN_CARET = 0x9
; TV HitTest Flags
Const $TVHT_ONITEMICON = 2
Const $TVHT_ONITEMLABEL = 4
Const $TVHT_ONITEM = BitOR($TVHT_ONITEMICON, $TVHT_ONITEMLABEL)
; gui size
Global $width = 310
Global $height = 400
; Build GUI
$myGui = GUICreate("TVI Clk&DblClk Exemple", $width, $height, -1, -1,BitOR($WS_SIZEBOX,$WS_MINIMIZEBOX,$WS_MAXIMIZEBOX,$WS_SYSMENU,$WS_CAPTION,$WS_GROUP,$WS_BORDER))
$myLabel = GUICtrlCreateLabel("Last action:",1,1,300)
GUISetState(@SW_SHOW, $myGui)
Build_TV(10, 20, $width-20, $height-40); build a Treeview with random items

; Main event loop
While 1
    $aMsg = GUIGetMsg(1)
    $msg = $aMsg[0]
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
; for TVI Clk
    If $msg >= $SubItems[0] And $msg <= $SubItems[UBound($SubItems) - 1] Then NotifyUs($msg)
; for TVI DblClk
    If $msg = $GUI_EVENT_PRIMARYDOWN Then; If LMB Down
        $mouse = GUIGetCursorInfo($myGui); Get CtrlID under mouse
        If $mouse[4] = $myTreeView Then; to be sure PRIMARYDOWN comes from our TreeView...
            $hitem = TV_Hittest($myTreeView, $aMsg[3], $aMsg[4], $TVHT_ONITEM, 0); test if PRIMARYDOWN was over a TV Item
            $TVI_CtrlID = GUICtrlRead($myTreeView); get the curent TVI CtrlID
    ; If TVI_CtrlID is within first and last CtrlId in the array then notify us
            If $hitem <> 0 And $TVI_CtrlID >= $SubItems[0] And $TVI_CtrlID <= $SubItems[UBound($SubItems) - 1] Then NotifyUs($TVI_CtrlID,True)
        EndIf
    EndIf
WEnd
; ###################################################################
Func Build_TV($x, $y, $w, $h)
; $TVS_DISABLEDRAGDROP is REQUIRED to capture DblClk (PRIMARYDOWN on TVIs), else i think its possible by using PRIMARYUP...
    Global $myTreeView = GUICtrlCreateTreeView($x,$y,$w,$h,BitOr($TVS_HASBUTTONS,$TVS_SHOWSELALWAYS,$TVS_HASLINES,$TVS_LINESATROOT,$TVS_DISABLEDRAGDROP))
    Global $MainItem
    Global $SubItems
    Dim $MainItem[3]
    $MainItem[0] = GUICtrlCreateTreeViewItem("MainItem1", $myTreeView)
    $MainItem[1] = GUICtrlCreateTreeViewItem("MainItem2", $myTreeView)
    $MainItem[2] = GUICtrlCreateTreeViewItem("MainItem3", $myTreeView)
; lots of subitems, Control IDs stored in array
    $MaxSubItems = 100
    Dim $SubItems[$MaxSubItems]
    For $i = 0 To $MaxSubItems - 1
        $r = Random(0, 2, 1); from 0 to 2 and return an Int
        $SubItems[$i] = GUICtrlCreateTreeViewItem("I am SubItem# " & $i, $MainItem[$r])
        GuiCtrlSetState($SubItems[$i], $GUI_DEFBUTTON)
        GUICtrlSetColor($SubItems[$i],0x008800); SetBackColor works also :)
    Next

EndFunc ;==>Build_TV

Func TV_Hittest($TreeView, $x, $y, $hitflag, $focus = 1) 
; Modified useful function from a cool guy on forum, can't remember his name, sorry :)
; His comments now:
    Local $i, $hitinfo, $hit, $tpos
    $i = 0
;get top and left positions of treeview control
    $tpos = ControlGetPos("", "", $TreeView)
    If Not @error Then
        $x = $x - $tpos[0];left offset
        $y = $y - $tpos[1];$top offset
        $hitinfo = DllStructCreate ("int;int;uint;uint");not sure if uint or ptr should go here...will look it up..32 bits is 32 bits
        If Not @error Then
            DllStructSetData ($hitinfo, 1, $x)
            DllStructSetData ($hitinfo, 2, $y)
            DllStructSetData ($hitinfo, 3, 0)
            DllStructSetData ($hitinfo, 4, 0)
            GUICtrlSendMsg($TreeView, $TVM_HITTEST, 0, DllStructGetPtr ($hitinfo))
            $hit = DllStructGetData ($hitinfo, 3);flags returned
            $i = DllStructGetData ($hitinfo, 4);handle
            $hitinfo = 0;DllStructDelete($hitinfo); seems no DllStructDelete in beta version 1.99
            If BitAND($hit, $hitflag) = 0 Then Return 0
            If $i And $focus <> 0 Then GUICtrlSendMsg($TreeView, $TVM_SELECTITEM, $TVGN_CARET, $i)
            Return $i;return control handle if any
        EndIf
    EndIf
EndFunc ;==>TV_Hittest

Func NotifyUs($CtrlId,$DblClick=False)
    Local $MySelectedSubItem= $CtrlId-$SubItems[0]
    Local $txt="Last action:"
    If $DblClick Then $txt&=" Double"
    $txt&=" Click on SubItem# "&$MySelectedSubItem
    GUICtrlSetData($myLabel,$txt)
EndFunc

Because i needed this for my project, this is the only way i found w/o using GuiRegisterMsg which can do strange things on a treeview control.

Hoping it could help someone,

Cheers.

Edited by Lemon.fr
Link to comment
Share on other sites

  • Moderators

Very nice !!!

i like to see something simulair for the listview !!!

is that possible?

jpam

You should try the term "double click" in the search advance options of the GUI forum.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

You should try the term "double click" in the search advance options of the GUI forum.

I did it and they use GuiRegisterMsg() IIRC...

EDIT:

I reported here the problem with GuiRegisterMsg() function and very stranges behavior with TreeView control.

In my project i use a Treeview and a ListView in the same script, GuiRegisterMsg() doesn't allow me to manage both.

Link to comment
Share on other sites

  • Moderators

I did it and they use GuiRegisterMsg() IIRC...

EDIT:

I reported here the problem with GuiRegisterMsg() function and very stranges behavior with TreeView control.

In my project i use a Treeview and a ListView in the same script, GuiRegisterMsg() doesn't allow me to manage both.

I wasn't speaking of yours, I also did a _DoubleClick() with _IsPressed(). I don't know if $GUI_EVENT_PRIMARYDOWN only reports on a doubleclick as you say with ListView as it does with TreeView which is what he was asking. In that case, maybe one of the other alternatives may work for him :(.

I hope the issue you reported is resolved easily :).

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Hoping it could help someone,

Cheers.

This is very nice work. Thank you. I did receive the following error when running it though it did not prevent me from testing it:

>"C:\Program Files\AutoIt3\SciTe\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /beta /ErrorStdOut /in "C:\Program Files\AutoIt3\Examples\TestOfTreeViewWithDoubleclick.au3" /autoit3dir "C:\Program Files\AutoIt3\beta" /UserParams

>Running AU3Check (1.54.1.1) params: from:C:\Program Files\AutoIt3\beta

C:\Program Files\AutoIt3\Examples\TestOfTreeViewWithDoubleclick.au3(31,29) : WARNING: $SubItems: possibly used before declaration.

If $msg >= $SubItems[0]And

~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

C:\Program Files\AutoIt3\Examples\TestOfTreeViewWithDoubleclick.au3(35,36) : WARNING: $myTreeView: possibly used before declaration.

If $mouse[4] = $myTreeView Then

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

C:\Program Files\AutoIt3\Examples\TestOfTreeViewWithDoubleclick.au3 - 0 error(s), 2 warning(s)

->AU3Check ended.rc:1

>Running:(3.1.1.124):C:\Program Files\AutoIt3\beta\autoit3.exe "C:\Program Files\AutoIt3\Examples\TestOfTreeViewWithDoubleclick.au3"

+>AutoIT3.exe ended.rc:0

>Exit code: 0 Time: 38.118

...by the way, it's pronounced: "JIF"... Bob Berry --- inventor of the GIF format
Link to comment
Share on other sites

It seems possible to use the same method without $TVS_DISABLEDRAGDROP (by the way, this is the default styles with autoit) :

By using PRIMARYUP instead of PRIMARYDOWN :)

this little script shows you all messages from GuiGetMsg, and the different reports with both styles.

#include <GUIConstants.au3>
; gui size
Global $width = 800
Global $height = 600
;
$myGui = GUICreate("GetMsg Tester with a Treeview", $width, $height, -1, -1,BitOR($WS_SIZEBOX,$WS_MINIMIZEBOX,$WS_MAXIMIZEBOX,$WS_SYSMENU,$WS_CAPTION,$WS_GROUP,$WS_BORDER))
$myEdit = GUICtrlCreateEdit("", 1, 1, $width - 1, 150)
$myBt_clear = GUICtrlCreateButton("Clear", 1, 152)
$myBt_StyleNoDragDropEnable = GUICtrlCreateButton("GUICtrlSetStyle($myTreeView,$TVS_DISABLEDRAGDROP)", 350, 152)
$myBt_StyleNoDragDropDisable = GUICtrlCreateButton("GUICtrlSetStyle($myTreeView,0)", 350, 182)

GUISetState(@SW_SHOW, $myGui)
; CONTROL TO TEST
Build_TV(10, 200, 300, 300)
; Main event loop
While 1
    $amsg = GUIGetMsg(1)
    $msg = $amsg[0]
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    If $msg = $myBt_clear Then GUICtrlSetData($myEdit, "")
    If $msg = $myBt_StyleNoDragDropEnable Then GUICtrlSetStyle($myTreeView,$TVS_DISABLEDRAGDROP)
    If $msg = $myBt_StyleNoDragDropDisable Then GUICtrlSetStyle($myTreeView,0)
    If $msg<>0 AND $msg<>-11 Then
        $acurs=GUIGetCursorInfo($myGui)
        $curs_over=$acurs[4]
        $txt="Msg:"&$msg
        Switch $msg
            Case -4
                $txt&=" (Minimize)"
            Case -5
                $txt&=" (Restore)"
            Case -6
                $txt&=" (Maximize)"
            Case -7
                $txt&=" (Primary Down)"
            Case -8
                $txt&=" (Primary Up)"
            Case -9
                $txt&=" (Secondary Down)"
            Case -10
                $txt&=" (Secondary Up)"
    ;Case -11
        ;$txt&="(Mouse Move)"; not needed and annoying
            Case -12
                $txt&=" (Resized)"
            Case -13
                $txt&=" (Dropped)"
            Case Else
                $txt&=" (CTRL)"
        EndSwitch
        $txt&="  CursOver:"&$curs_over&"    WinH:"&$amsg[1]&" CtrlH:"&$amsg[2]
        GUICtrlSetData($myEdit,$txt&@CRLF,1)
        EndIf
WEnd
; ###################################################################
Func Build_TV($x, $y, $w, $h)
    Global $myTreeView = GUICtrlCreateTreeView($x,$y,$w,$h)
    Global $MainItem
    Global $SubItems
; few parent items, Control IDs stored in array
    Dim $MainItem[3]
    $MainItem[0] = GUICtrlCreateTreeViewItem("Item1", $myTreeView)
    $MainItem[1] = GUICtrlCreateTreeViewItem("Item2", $myTreeView)
    $MainItem[2] = GUICtrlCreateTreeViewItem("Item3", $myTreeView)
; lots of subitems, Control IDs stored in array
    $MaxSubItems = 300
    Dim $SubItems[$MaxSubItems]
    
    For $i = 0 To $MaxSubItems - 1
        $r = Random(0, 2, 1); from 0 to 2 and return an Int
        $SubItems[$i] = GUICtrlCreateTreeViewItem("SubItem " & $i, $MainItem[$r])
        GuiCtrlSetState($SubItems[$i], $GUI_DEFBUTTON)
        GUICtrlSetColor($SubItems[$i],0x008800)
     Next
EndFunc ;==>Build_TV
Edited by Lemon.fr
Link to comment
Share on other sites

Now with Listview,

As for the treeview without $TVS_DISABLEDRAGDROP, this is possible to capture DoubleClick with a PRIMARYUP over an Item (There's a LVHitTest Msg like for treeviews) but as far as i know there's no way to disable Drag&Drop feature in a Listview, so if the user starts to drag an LV item over another LV item then GuiGetMsg will report a PRIMARYUP and thats not doubleclick :)

#include <GUIConstants.au3>
; gui size
Global $width = 800
Global $height = 600
;
$myGui = GUICreate("GetMsg Tester with a Listview", $width, $height, -1, -1, BitOR($WS_SIZEBOX, $WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_SYSMENU, $WS_CAPTION, $WS_GROUP, $WS_BORDER))
$myEdit = GUICtrlCreateEdit("", 1, 1, $width - 1, 150)
$myBt_clear = GUICtrlCreateButton("Clear", 1, 152)
;$myBt_StyleNoDragDropEnable = GUICtrlCreateButton("GUICtrlSetStyle($myTreeView,$TVS_DISABLEDRAGDROP)", 350, 152)
;$myBt_StyleNoDragDropDisable = GUICtrlCreateButton("GUICtrlSetStyle($myTreeView,0)", 350, 182)

GUISetState(@SW_SHOW, $myGui)
; CONTROL TO TEST
Build_LV (10, 200, 300, 300)
; Main event loop
While 1
    $amsg = GUIGetMsg(1)
    $msg = $amsg[0]
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    If $msg = $myBt_clear Then GUICtrlSetData($myEdit, "")
;If $msg = $myBt_StyleNoDragDropEnable Then GUICtrlSetStyle($myTreeView, $TVS_DISABLEDRAGDROP)
;If $msg = $myBt_StyleNoDragDropDisable Then GUICtrlSetStyle($myTreeView, 0)
    If $msg <> 0 And $msg <> - 11 Then
        $acurs = GUIGetCursorInfo($myGui)
        $curs_over = $acurs[4]
        $txt = "Msg:" & $msg
        Switch $msg
            Case -4
                $txt &= " (Minimize)"
            Case -5
                $txt &= " (Restore)"
            Case -6
                $txt &= " (Maximize)"
            Case -7
                $txt &= " (Primary Down)"
            Case -8
                $txt &= " (Primary Up)"
            Case -9
                $txt &= " (Secondary Down)"
            Case -10
                $txt &= " (Secondary Up)"
            ;Case -11
            ;$txt&="(Mouse Move)"; not needed and annoying
            Case -12
                $txt &= " (Resized)"
            Case -13
                $txt &= " (Dropped)"
            Case Else
                $txt &= " (CTRL)"
        EndSwitch
        $txt &= "  CursOver:" & $curs_over & "  WinH:" & $amsg[1] & " CtrlH:" & $amsg[2]
        GUICtrlSetData($myEdit, $txt & @CRLF, 1)
    EndIf
WEnd
; ###################################################################
Func Build_LV($x, $y, $w, $h)
    Global $myListView = GUICtrlCreateListView("Hello",$x,$y,$w,$h)
    Global $Items
    Global $SubItems
    $MaxSubItems = 300
    Dim $Items[$MaxSubItems]
    For $i = 0 To $MaxSubItems - 1
        $Items[$i] = GUICtrlCreateListViewItem("Item " & $i, $myListView)
        GUICtrlSetColor($Items[$i], 0x008800)
    Next
EndFunc  ;==>Build_TV
Link to comment
Share on other sites

I really would have something to manage DoubleClicks on Treeviews and ListViews Items (both in same window ), my autoit project is stoped (after 3000 lines of code...), i tried many ways, and this forced me (which isn't a bad thing) to learn more about Windows SDK, i even started to learn C++ but this is boring :D (won't recode all the autoit functions + the time needed to be a c++ king...)

Maybe im not alone in this state, we could share solutions here :)

hope here

PS: i know AutoIt3 still under devellopment :(

Edited by Lemon.fr
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...