dhlhmgc 发表于 2023-4-4 11:01:59

[已解决]求解TreeView如何取得鼠标所在节点信息HotTrack形式

本帖最后由 dhlhmgc 于 2023-4-5 09:42 编辑

目标想得到 TreeView 的鼠标移入、移出消息事件,求出当前鼠标下的节点信息!
就是HotTrack形式,在处理TREEVIEW控件又遇到问题 ,GUI消息事件:WM_NOTIFY

====================================
$tNMHdr = DllStructCreate("hwnd hWndFrom;int IDFrom;int Code;dword dwFlags"
已经知道:鼠标移入,移出的动态值就是在 dwFlags 里面,调试输出也有变化
但case的事件常量不知道用什么,求指教:

      Switch $iIDFrom
                Case $TreeView1
                        Switch $iCode
                              Case $NM_CLICK                ;左键单击
============================================
鼠标移入\移出 试过:
               ;Case $BCN_HOTITEMCHANGE ; Win XP and Above
               ;    If BitAND($dwFlags, 0x10) = 0x10 Then
         ;            $sText = "$BCN_HOTITEMCHANGE - Entering:当鼠标进入 "
         ;            WinSetTitle($fm1, "", "dw : " & $dwFlags)
                ;    ElseIf BitAND($dwFlags, 0x20) = 0x20 Then
         ;            $sText = "$BCN_HOTITEMCHANGE - Leaving: 当鼠标移出"
         ;            WinSetTitle($fm1, "", "dw : " & $dwFlags)
         ;      EndIf
貌似不起作用,这个是不是只对Button等控件起作用!?

TVN_开头的也看了一堆,但不确定移入、移出的CODE代码常量是哪个!?
求高人指点!

[已解决]
==============
非常感谢各位大神无私的指导,虽然对WM_NOTIFY、WM_COMMAND的消息机构还不是太熟悉,但目前的问题已基本得到解决!现次感谢!
==============
;---------------------------------------------------------------------------------------
; 功能: 对 TreeView项目的鼠标跟踪
; 语法:
;---------------------------------------------------------------------------------------
#include <WinAPI.au3>
#include <WinAPISys.au3>

#include <GuiTreeView.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <date.au3>

OnAutoItExitRegister('OnAutoItExit')

dim $hGUI = GUICreate('', 400, 300)
$iStyle = BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS, $TVS_CHECKBOXES)

;$TreeView1 = GUICtrlCreateTreeView(5, 5, 390, 280, $iStyle, $WS_EX_CLIENTEDGE)
$TreeView1 = GUICtrlCreateTreeView(5, 5, 390, 280, -1, $WS_EX_CLIENTEDGE )
$hTreeView = GUICtrlGetHandle(-1)
GUICtrlSetFont(-1, 12, 400, 0, "宋体")
$TreeViewItem1 = GUICtrlCreateTreeViewItem('TreeViewItem1', $TreeView1)
GUICtrlCreateTreeViewItem('TreeViewItem1-1', $TreeViewItem1)
GUICtrlCreateTreeViewItem('TreeViewItem1-2', $TreeViewItem1)
GUICtrlCreateTreeViewItem('TreeViewItem1-3', $TreeViewItem1)
$TreeViewItem2 = GUICtrlCreateTreeViewItem('TreeViewItem2', $TreeView1)
GUICtrlCreateTreeViewItem('TreeViewItem2-1', $TreeViewItem2)
GUICtrlCreateTreeViewItem('TreeViewItem2-2', $TreeViewItem2)
GUICtrlCreateTreeViewItem('TreeViewItem2-3', $TreeViewItem2)
$TreeViewItem3 = GUICtrlCreateTreeViewItem('TreeViewItem3', $TreeView1)
GUICtrlCreateTreeViewItem('TreeViewItem3-1', $TreeViewItem3)
GUICtrlCreateTreeViewItem('TreeViewItem3-2', $TreeViewItem3)
GUICtrlCreateTreeViewItem('TreeViewItem3-3', $TreeViewItem3)
;~ GUICtrlSetState($TreeViewItem1, $GUI_EXPAND)
;~ GUICtrlSetState($TreeViewItem2, $GUI_EXPAND)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")                ;捕捉窗口控件交互时事件
GUISetState()
While 1
      $nMsg = GUIGetMsg()
      Switch $nMsg
                Case -3
                        Exit
      EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $wParam
    Local Const $BCN_HOTITEMCHANGE = -1249
    Local $tNMBHOTITEM = DllStructCreate("hwnd hWndFrom;int IDFrom;int Code;dword dwFlags", $lParam)
    Local $nNotifyCode = DllStructGetData($tNMBHOTITEM, "Code")
    Local $nID = DllStructGetData($tNMBHOTITEM, "IDFrom")
    Local $hCtrl = DllStructGetData($tNMBHOTITEM, "hWndFrom")
    Local $dwFlags = DllStructGetData($tNMBHOTITEM, "dwFlags")
      
      ;Local $iMousePosX = BitAND($lParam, 0xFFFF)         ;低位字,鼠标的 X 位置
      ;Local $iMousePosY = BitShift($lParam, 16)               ;高位字,鼠标的 Y 位置
      
      local $hForm = _WinAPI_GetParent( $hCtrl )      ;//检索指定子窗口的父窗口句柄.
   
    Switch $nNotifyCode
            Case $NM_CLICK
            Case $NM_SETCURSOR
                  if $dwFlags Then
                Local $tMPos= _WinAPI_GetMousePos(True, $hCtrl)
                Local $tHit   = _GUICtrlTreeView_HitTestEx($hCtrl, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2))
                Local $hItem= DllStructGetData($tHit, "Item")                  
                _GUICtrlTreeView_SelectItem ($TreeView1, $hItem, $TVGN_CARET)      ;选中
                            $s = _GUICtrlTreeView_GetText ($TreeView1, $hItem)
                            $hItem = _GUICtrlTreeView_GetSelection($hCtrl)
                            if $hItem Then
                                    $ss = " 热点:" & _GUICtrlTreeView_GetText ($TreeView1, $hItem)
                            else
                                    $ss = ""
                            Endif
                            WinSetTitle($hForm, "", Random(10, 20, 1) & ' 鼠标:' & $s & $ss)
                            Return $GUI_RUNDEFMSG
                  Endif
      EndSwitch
EndFunc



tubaba 发表于 2023-4-4 12:11:54





自己完善下吧,大致思路就是回调函数中修改


#include <WinAPISysWin.au3>
#include <GUIConstantsEx.au3>
#include <GuiTreeView.au3>
#include <WindowsConstants.au3>

Global $g_hTreeView


Local $hGUI = GUICreate("TreeView Create (v" & @AutoItVersion & ")", 400, 300)

Local $iStyle = BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS, $TVS_CHECKBOXES)
$g_hTreeView = _GUICtrlTreeView_Create($hGUI, 2, 2, 396, 268, $iStyle, $WS_EX_CLIENTEDGE)
GUISetState(@SW_SHOW)

;~         GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

_GUICtrlTreeView_BeginUpdate($g_hTreeView)
Local $hItem
For $x = 0 To 5
        $hItem = _GUICtrlTreeView_Add($g_hTreeView, 0, StringFormat("[%02d] New Item", $x))
        For $y = 0 To 3
                _GUICtrlTreeView_AddChild($g_hTreeView, $hItem, StringFormat("[%02d] New Child", $y))
        Next
Next
_GUICtrlTreeView_EndUpdate($g_hTreeView)

$hProcNew = DllCallbackRegister("_MyWindowProc", "ptr", "hwnd;uint;long;ptr")
$g_hProcOld = _WinAPI_SetWindowLong($g_hTreeView, $GWL_WNDPROC, DllCallbackGetPtr($hProcNew))


; Loop until the user exits.
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
GUIDelete()


Func _MyWindowProc($hWnd, $iMsg, $wParam, $lParam)
        Local $iCtrl = _WinAPI_GetDlgCtrlID($hWnd)
        Local Const $TME_HOVER = 0x00000001
        Local Const $TME_LEAVE = 0x00000002
        Switch $iMsg
                Case $WM_MOUSEHOVER ;鼠标悬停
                        Local Static $cur = 0
                        Local $hot = _TreeItemFromPoint($hWnd)
                        If $hot <> 0 Then
                                If $hot <> $cur Then
                                        ConsoleWrite('移入' & $hot & @CRLF)
                                        $cur = $hot
                                EndIf
                        EndIf
                Case $WM_MOUSELEAVE ;鼠标离开
                Case $WM_MOUSEMOVE ;鼠标移动
                        __TrackMouseEvent($hWnd, BitOR($TME_HOVER, $TME_LEAVE), 1) ;//MOUSELEAVE|MOUSEHOVER消息由此函数触发
                Case $WM_LBUTTONUP ;弹起鼠标左键
                Case $WM_LBUTTONDOWN ;按下鼠标左键
        EndSwitch
        Return _WinAPI_CallWindowProc($g_hProcOld, $hWnd, $iMsg, $wParam, $lParam)
EndFunc   ;==>_MyWindowProc

Func __TrackMouseEvent($hWnd, $iFlags, $iTime = -1)
        Local $tTME = DllStructCreate('dword;dword;hwnd;dword')
        DllStructSetData($tTME, 1, DllStructGetSize($tTME))
        DllStructSetData($tTME, 2, $iFlags)
        DllStructSetData($tTME, 3, $hWnd)
        DllStructSetData($tTME, 4, $iTime)
        Local $aRet = DllCall('user32.dll', 'bool', 'TrackMouseEvent', 'struct*', $tTME)
        If @error Then Return SetError(@error, @extended, 0)
        Return $aRet
EndFunc   ;==>__TrackMouseEvent

Func _TreeItemFromPoint($hWnd)
        Local $tMPos = _WinAPI_GetMousePos(True, $hWnd)
        Return _GUICtrlTreeView_HitTestItem($hWnd, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2))
EndFunc   ;==>_TreeItemFromPoint


chzj589 发表于 2023-4-4 13:14:59

可用
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
        If Not IsHWnd($TreeView) Then $hWndTreeView = GUICtrlGetHandle($TreeView)
        $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
        $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
        $iCode = DllStructGetData($tNMHDR, "Code")
        Switch $hWndFrom
                Case $hWndTreeView
                        Switch $iCode
                                Case $NM_CLICK ; 鼠标左键单击

                        EndSwitch
        EndSwitch
        Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
页: [1]
查看完整版本: [已解决]求解TreeView如何取得鼠标所在节点信息HotTrack形式