sh1536 发表于 2020-3-2 14:58:19

【已解决】Treeview树形列表通过事件判断点击项目会响应上一个项目

本帖最后由 sh1536 于 2020-3-2 18:07 编辑

请教问什么通过WM_NOTIFY来捕获点击了哪个项目时,不是响应点击的这个,而是响应的上一个被选中的项目?

如图,我点击了项目二,但是响应的是点击了项目一



#include <TreeViewConstants.au3>
#include <GUIConstants.au3>
#include <GuiTreeView.au3>
#Region
$Form1 = GUICreate("Form1", 600, 400, -1, -1)
$TreeView = GUICtrlCreateTreeView(6, 6, 150, 386, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS, 0x8000)) ;去掉横向滑块
$TreeViewItem1 = GUICtrlCreateTreeViewItem("项目1", $TreeView)
$TreeViewItem2 = GUICtrlCreateTreeViewItem("项目2", $TreeView)
$TreeViewItem3 = GUICtrlCreateTreeViewItem("项目3", $TreeView)

GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ;捕捉窗口控件交互时事件
#EndRegion

While 1
      $nMsg = GUIGetMsg()
      Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit
      EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) ;捕捉窗口控件交互时事件
      Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR
      $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
      $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
      $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
      $iCode = DllStructGetData($tNMHDR, "Code")
      Switch $hWnd
                Case $Form1
                        _Form1_NOTIFY($hWnd, $iIDFrom, $iCode, $ilParam)
      EndSwitch
      Return $GUI_RUNDEFMSG
EndFunc

Func _Form1_NOTIFY($hWnd, $iControl, $iMsg, $ilParam) ;捕捉窗口事件
      Local $Index
      Switch $iControl
                Case $TreeView
                        Switch $iMsg
                              Case $NM_CLICK ;左键单击
                                        ;If _GUICtrlTreeView_GetSelected($TreeView, $TreeViewItem0) Then
                                        MsgBox(0, 0, "单击了" & GUICtrlRead($TreeView, 1), 0, $Form1)
                                        ;EndIf
                              Case $NM_RCLICK ;右键单击事件

                        EndSwitch
      EndSwitch
EndFunc
我想实现分别点击项目执行不同功能,请教解决方法。

chzj589 发表于 2020-3-2 17:32:14

是这样子吗?

#include <TreeViewConstants.au3>
#include <GUIConstants.au3>
#include <GuiTreeView.au3>
#Region
$Form1 = GUICreate("Form1", 600, 400, -1, -1)
$TreeView = GUICtrlCreateTreeView(6, 6, 150, 386, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS, 0x8000)) ;去掉横向滑块
$TreeViewItem1 = GUICtrlCreateTreeViewItem("项目1", $TreeView)
$TreeViewItem2 = GUICtrlCreateTreeViewItem("项目2", $TreeView)
$TreeViewItem3 = GUICtrlCreateTreeViewItem("项目3", $TreeView)
GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ;捕捉窗口控件交互时事件
#EndRegion
While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit
        EndSwitch
WEnd
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) ;捕捉窗口控件交互时事件
        #forceref $hWnd, $iMsg, $iwParam
        Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
        Local $hWndTreeView = $TreeView
        If Not IsHWnd($TreeView) Then $hWndTreeView = GUICtrlGetHandle($TreeView)
        $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
        $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
        $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
        $iCode = DllStructGetData($tNMHDR, "Code")
        Switch $hWndFrom
                Case $hWndTreeView
                        Switch $iCode
                                Case $NM_CLICK ; 鼠标左键单击
                                        Local $mPos = _WinAPI_GetMousePos(True, $hWndTreeView)
                                        Local $mText = _GUICtrlTreeView_HitTestItem($hWndTreeView, DllStructGetData($mPos, "X"), DllStructGetData($mPos, "Y"))
                                        Local $iPos = _GUICtrlTreeView_HitTest($hWndTreeView, DllStructGetData($mPos, "X"), DllStructGetData($mPos, "Y"))
                                        Local $cText = _GUICtrlTreeView_GetText($hWndTreeView, $mText) ;获得当前坐标项目文本
                                        MsgBox(0, 0, "单击了" & $cText)
                        EndSwitch
        EndSwitch
        Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

sh1536 发表于 2020-3-2 18:05:29

chzj589 发表于 2020-3-2 17:32
是这样子吗?

感谢回复!!通过坐标来判断还没用过,又学习到了,非常感谢。



另外我在你的基础上修改了下,用树视图项目(TreeViewItem)控件创建时的控件ID来判断点击了哪一个项目,用文本来判断我感觉不利于后续程序迭代。修改后的源码在下面:
#include <TreeViewConstants.au3>
#include <GUIConstants.au3>
#include <GuiTreeView.au3>
#Region
$Form1 = GUICreate("Form1", 600, 400, -1, -1)
$TreeView = GUICtrlCreateTreeView(6, 6, 150, 386, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS, 0x8000)) ;去掉横向滑块
$TreeViewItem1 = GUICtrlCreateTreeViewItem("项目1", $TreeView)
$TreeViewItem2 = GUICtrlCreateTreeViewItem("项目2", $TreeView)
$TreeViewItem3 = GUICtrlCreateTreeViewItem("项目3", $TreeView)
GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ;捕捉窗口控件交互时事件
#EndRegion
While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit
        EndSwitch
WEnd
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) ;捕捉窗口控件交互时事件
        #forceref $hWnd, $iMsg, $iwParam
        Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
        Local $hWndTreeView = $TreeView
        If Not IsHWnd($TreeView) Then $hWndTreeView = GUICtrlGetHandle($TreeView)
        $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
        $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
        $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
        $iCode = DllStructGetData($tNMHDR, "Code")
        Switch $hWndFrom
                Case $hWndTreeView
                        Switch $iCode
                                Case $NM_CLICK ; 鼠标左键单击
                                        Local $mPos = _WinAPI_GetMousePos(True, $hWndTreeView)
                                        Local $mText = _GUICtrlTreeView_HitTestItem($hWndTreeView, DllStructGetData($mPos, "X"), DllStructGetData($mPos, "Y"))
                                        ;Local $iPos = _GUICtrlTreeView_HitTest($hWndTreeView, DllStructGetData($mPos, "X"), DllStructGetData($mPos, "Y"))
                                        ;Local $cText = _GUICtrlTreeView_GetText($hWndTreeView, $mText) ;获得当前坐标项目文本
                                        ;MsgBox(0, 0, "单击了" & $cText)

                                        Switch $mText
                                                Case _GUICtrlTreeView_GetItemHandle($TreeView, $TreeViewItem1)
                                                        MsgBox(0, 0, "单击了项目一")
                                                Case _GUICtrlTreeView_GetItemHandle($TreeView, $TreeViewItem2)
                                                        MsgBox(0, 0, "单击了项目二")
                                                Case _GUICtrlTreeView_GetItemHandle($TreeView, $TreeViewItem3)
                                                        MsgBox(0, 0, "单击了项目三")
                                        EndSwitch
                        EndSwitch
        EndSwitch
        Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

floor6ggg 发表于 2020-3-3 23:48:59

本帖最后由 floor6ggg 于 2020-3-4 07:28 编辑

http://www.autoitx.com/thread-15253-2-1.html
解法2:可以参考pusofalse大的$TVN_SELCHANGEDW 的方法

floor6ggg 发表于 2020-3-3 23:54:26

测试是可以准确显示出点击的项目名称的
#include <GuiConstantsEx.au3>
#include <GuiTreeView.au3>
#include <GuiImageList.au3>
#include <WindowsConstants.au3>
Global $fClicked = False

#region ### START Koda GUI section ### Form=C:\Documents and Settings\Administrator\Desktop\Linkget\Linkget.kxf
$GUI = GUICreate("", 676, 378, 203, 289)
$hTreeView = _GUICtrlTreeView_Create($GUI, 2, 2, 161, 227)

_GUICtrlTreeView_BeginUpdate($hTreeView)
For $x = 1 To Random(2, 10, 1)
    $hItem = _GUICtrlTreeView_Add($hTreeView, 0, StringFormat("[%02d] New Item", $x))
Next
_GUICtrlTreeView_EndUpdate($hTreeView)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)
#endregion ### START Koda GUI section ### Form=C:\Documents and Settings\Administrator\Desktop\Linkget\Linkget.kxf


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndTreeview
    $hWndTreeview = $hTreeView
    If Not IsHWnd($hTreeView) Then $hWndTreeview = GUICtrlGetHandle($hTreeView)

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
      Case $hWndTreeview
            Switch $iCode
                                Case $TVN_SELCHANGEDW
                                                ConsoleWrite(@ScriptLineNumber&"WM_NOTIFY:-->$TVN_SELCHANGEDW: " &_GUICtrlTreeView_GetText($hWndTreeview, _GUICtrlTreeView_GetSelection($hWndTreeview))& @LF)
                                        Return 0 ; zero to allow the default processing
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
      Case $GUI_EVENT_CLOSE
            Exit
      Case Else
            If $fClicked = True Then
                _TreeView_GetText($hTreeView)
                $fClicked = False
            EndIf
    EndSwitch
WEnd

floor6ggg 发表于 2020-3-3 23:55:52

TVN_SELCHANGED:当所选项目已经改变时,才发送此通知,截取TVN_SELCHANGED是正确的。

floor6ggg 发表于 2020-3-4 00:00:40

本帖最后由 floor6ggg 于 2020-3-4 07:28 编辑

解法3:
Melba23大神在官网的论述,我也看不懂,好在现在的翻译软件很发达…………
https://www.autoitscript.com/for ... ents#comment-676043

floor6ggg 发表于 2020-3-4 00:01:43

#include <GuiConstantsEx.au3>
#include <GuiTreeView.au3>
#include <GuiImageList.au3>
#include <WindowsConstants.au3>
;~ #include <Array.au3>
Global $fClicked = False

#region ### START Koda GUI section ### Form=C:\Documents and Settings\Administrator\Desktop\Linkget\Linkget.kxf
$GUI = GUICreate("", 676, 378, 203, 289)
$hTreeView = _GUICtrlTreeView_Create($GUI, 2, 2, 161, 227)

_GUICtrlTreeView_BeginUpdate($hTreeView)
For $x = 1 To Random(2, 10, 1)
    $hItem = _GUICtrlTreeView_Add($hTreeView, 0, StringFormat("[%02d] New Item", $x))
Next
_GUICtrlTreeView_EndUpdate($hTreeView)

;~_ArrayDisplay($hItem,'')

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)
#endregion ### START Koda GUI section ### Form=C:\Documents and Settings\Administrator\Desktop\Linkget\Linkget.kxf

Func _TreeView_GetText(ByRef $hWndTreeview)
    ConsoleWrite(@ScriptLineNumber&"_TreeView_GetText:-->Selection Text: " & _GUICtrlTreeView_GetText($hWndTreeview, _GUICtrlTreeView_GetSelection($hWndTreeview))& @LF)
EndFunc   ;==>_TreeView_GetText

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndTreeview
    $hWndTreeview = $hTreeView
    If Not IsHWnd($hTreeView) Then $hWndTreeview = GUICtrlGetHandle($hTreeView)

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
      Case $hWndTreeview
            Switch $iCode
                Case $NM_CLICK ; The user has clicked the left mouse button within the control

                  ConsoleWrite("$NM_CLICK" & @LF & "--> hWndFrom:" & @TAB & $hWndFrom & @LF & _
                            "-->IDFrom:" & @TAB & $iIDFrom & @LF & _
                            "-->Code:" & @TAB & $iCode & @LF)
                                                        ConsoleWrite(@ScriptLineNumber&"WM_NOTIFY:-->Selection Text: " & _GUICtrlTreeView_GetText($hWndTreeview, _GUICtrlTreeView_GetSelection($hWndTreeview))& @LF)
                  $fClicked = True
                  Return 0 ; zero to allow the default processing
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
      Case $GUI_EVENT_CLOSE
            Exit
      Case Else
            If $fClicked = True Then
                _TreeView_GetText($hTreeView)
                $fClicked = False
            EndIf
    EndSwitch
WEnd

floor6ggg 发表于 2020-3-4 00:10:45

巧妙的通过$fClicked返回的while循环里面,此时的_GUICtrlTreeView_GetText是准确的…………这种解法也挺赞

floor6ggg 发表于 2020-3-4 00:11:17

本帖最后由 floor6ggg 于 2020-3-4 07:29 编辑

解法4567………………等待高人后续补充…………

sh1536 发表于 2020-3-28 16:05:49

floor6ggg 发表于 2020-3-3 23:54
测试是可以准确显示出点击的项目名称的

都试了下,个人感觉解法二最赞,准确且代码简单
其中这条可以不需要:
_TreeView_GetText($hTreeView)
解法三很巧妙,但是需要额外代码来辅助,没有解法二简单粗暴
感谢帮忙
页: [1]
查看完整版本: 【已解决】Treeview树形列表通过事件判断点击项目会响应上一个项目