实现TreeListView,TreeView+ListView
这些代码是从外网抄来的。把TreeView和ListView合在了一起。但是实际使用过程中仍存在瑕疵,如TreeView和ListView滚轮事件未能完全同步,TreeView当建到第三层的时候可能出现折叠不同步现象。另外选中项目后两个控件颜色有偏差,看起来就像是硬凑在一起的控件。 本人新手一枚,能力有限。把代码放上来望大神们进行完善。目前效果如图代码如下,另附件同代码:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <FontConstants.au3>
#Include <ScrollBarConstants.au3>
#Include <GUIScrollBars.au3>
#include <GUIListView.au3>
#include <GUITreeView.au3>
#include <WinAPI.au3>
Global $i_TLV_CHANGING = False
Global $i_TLV_SEL_CHANGED = False
Global $a_TLV_DATA
;Global $h_TLV_FONT = _WinAPI_CreateFont(14, 6, 0, 0, 0, False, False, False, $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Arial')
$hGUI = GUICreate("TreeListView Test", 700, 500)
$anTLV = _GUICtrlTreeListView_Create($hGUI, 10, 10, 680, 480)
For $i = 1 To 5
$anTLV_Item = _GUICtrlTreeListView_AddItem($anTLV, "My Folder " & $i & "|Folder|" & Round(Random(1, 5), 1) & " mb")
$anTLV_SubItem1 = _GUICtrlTreeListView_AddItem($anTLV, "My Script " & $i & ".au3|File|" &Round(Random(1, 5), 1) & " kb", $anTLV_Item)
$anTLV_SubItem2 = _GUICtrlTreeListView_AddItem($anTLV, "My File " & $i & ".txt|File|" &Round(Random(1, 5), 1) & " kb", $anTLV_Item)
_GUICtrlTreeListView_ExpandItem($anTLV, $anTLV_Item, True)
Next
GUISetState(@SW_SHOW, $hGUI)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
EndSwitch
WEnd
Func _GUICtrlTreeListView_Create($hWnd, $iLeft, $iTop, $iWidth, $iHeight)
Local $anTLV, $hTV, $aTVPos, $aLVPos, $iColsCount, $iLVWidth, $iColWidth
$anTLV = GUICtrlCreateTreeView($iLeft + 5, $iTop + 25, ($iWidth / 2) + 10, $iHeight - 35, BitOr($GUI_SS_DEFAULT_TREEVIEW, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_NOSCROLL, $TVS_NONEVENHEIGHT))
$anTLV = GUICtrlCreateListView("Name|Type|Size", $iLeft, $iTop, $iWidth, $iHeight, BitOr($LVS_SHOWSELALWAYS, $LVS_SINGLESEL, $WS_CLIPSIBLINGS, $LVS_NOSORTHEADER))
$hTV = GUICtrlGetHandle($anTLV)
__GUICtrlTreeListView_SetFont($anTLV, _SendMessage($hTV, $WM_GETFONT))
;_GUICtrlListView_SetExtendedListViewStyle($anTLV, $LVS_EX_GRIDLINES, $LVS_EX_GRIDLINES)
_GUICtrlTreeView_SetHeight($hTV, 21)
_GUIScrollBars_EnableScrollBar($hTV, $SB_BOTH, $ESB_DISABLE_BOTH)
_GUIScrollBars_ShowScrollBar($hTV, $SB_VERT, False)
$aTVPos = ControlGetPos($hWnd, "", $anTLV)
$aLVPos = ControlGetPos($hWnd, "", $anTLV)
If UBound($aTVPos) > 2 And UBound($aLVPos) > 2 Then
$iColsCount = _GUICtrlListView_GetColumnCount($anTLV)
$iLVWidth = $aLVPos - ($aTVPos + 10) - 15
$iColWidth = Floor($iLVWidth / ($iColsCount - 1))
For $i = 1 To $iColsCount - 1
_GUICtrlListView_SetColumnWidth($anTLV, $i, $iColWidth)
Next
_GUICtrlListView_SetColumnWidth($anTLV, 0, $aTVPos)
EndIf
GUIRegisterMsg($WM_NOTIFY, "__GUICtrlTreeListView_WM_NOTIFY")
Return $anTLV
EndFunc
Func _GUICtrlTreeListView_AddItem($anTLV, $sItemText, $nTVCtrl = -1)
Local $anTLV_Item, $iItem, $aTVPos
$i_TLV_CHANGING = True
If $nTVCtrl = -1 Then
$nTVCtrl = $anTLV
EndIf
$anTLV_Item = GUICtrlCreateTreeViewItem(StringRegExpReplace($sItemText, '^([^|]*)\|.*', '\1'), $nTVCtrl)
$anTLV_Item = GUICtrlCreateListViewItem(StringRegExpReplace($sItemText, '^[^|]*', ''), $anTLV)
$a_TLV_DATA += 1
ReDim $a_TLV_DATA[$a_TLV_DATA + 1]
$a_TLV_DATA[$a_TLV_DATA] = $anTLV ;TreeView ID
$a_TLV_DATA[$a_TLV_DATA] = $anTLV ;ListView ID
$a_TLV_DATA[$a_TLV_DATA] = $anTLV_Item ;Added TV Item ID
$a_TLV_DATA[$a_TLV_DATA] = $anTLV_Item ;Added LV Item ID
$a_TLV_DATA[$a_TLV_DATA] = $sItemText ;LV Item Text (including SubItems delimited with |)
$a_TLV_DATA[$a_TLV_DATA] = $nTVCtrl ;TV Item Parent ID
$i_TLV_CHANGING = False
Return $anTLV_Item
EndFunc
Func _GUICtrlTreeListView_ExpandItem($anTLV, $nTVCtrl, $bExpand)
$i_TLV_CHANGING = True
_GUICtrlTreeView_Expand($anTLV, $nTVCtrl, $bExpand)
$i_TLV_CHANGING = False
EndFunc
Func __GUICtrlTreeListView_WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hTreeView, $hListView, $hLVHeader
Global $iLastScrollPos
If $i_TLV_CHANGING Then
Return $GUI_RUNDEFMSG
EndIf
$tNMHDR = DllStructCreate($tagNMHDR, $lParam)
$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
$iCode = DllStructGetData($tNMHDR, "Code")
For $i = 1 To $a_TLV_DATA
$hTreeView = GUICtrlGetHandle($a_TLV_DATA[$i])
$hListView = GUICtrlGetHandle($a_TLV_DATA[$i])
$hLVHeader = _GUICtrlListView_GetHeader($hListView)
Switch $hWndFrom
Case $hLVHeader
Switch $iCode
Case $HDN_ITEMCHANGING, $HDN_ITEMCHANGINGW
Return 1
EndSwitch
ExitLoop
Case $hListView
Switch $iCode
Case $LVN_ITEMCHANGING, $LVN_BEGINDRAG, $LVN_MARQUEEBEGIN
Return 1
Case $LVN_BEGINSCROLL
$tSCROLLINFO = DllStructCreate($tagSCROLLINFO)
DllStructSetData($tSCROLLINFO, "cbSize", DllStructGetSize($tSCROLLINFO))
DllStructSetData($tSCROLLINFO, "fMask", $_SCROLLBARCONSTANTS_SIF_ALL) ;如果在这行报错就改成 $SIF_ALL 试试
_GUIScrollBars_GetScrollInfo($hListView, $SB_VERT, $tSCROLLINFO)
$nPage = DllStructGetData($tSCROLLINFO, "nPage")
$nPos = DllStructGetData($tSCROLLINFO, "nPos")
$nMin = DllStructGetData($tSCROLLINFO, "nMin")
$nMax = DllStructGetData($tSCROLLINFO, "nMax")
$nTrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
GUICtrlSetStyle($a_TLV_DATA[$i], BitOr($GUI_SS_DEFAULT_TREEVIEW, $TVS_HASLINES, $TVS_LINESATROOT))
_GUIScrollBars_SetScrollInfo($hTreeView, $SB_VERT, $tSCROLLINFO)
For $j = 1 To $nPos
GUICtrlSendMsg($a_TLV_DATA[$i], $WM_VSCROLL, $SB_LINEDOWN, 0)
Next
_GUIScrollBars_ShowScrollBar($hTreeView, $SB_BOTH, False)
Case $LVN_ENDSCROLL
_GUIScrollBars_ShowScrollBar($hTreeView, $SB_BOTH, False)
EndSwitch
ExitLoop
Case $hTreeView
Switch $iCode
Case $TVN_SELCHANGEDA, $TVN_SELCHANGEDW
Local $hTVItem = _GUICtrlTreeView_GetSelection($a_TLV_DATA[$i])
Local $iTVItemIndx = 0
While 1
$hTVItem = _GUICtrlTreeView_GetPrevVisible($a_TLV_DATA[$i], $hTVItem)
If $hTVItem = 0 Then ExitLoop
$iTVItemIndx += 1
WEnd
$i_TLV_CHANGING = True
;ControlListView($hWnd, '', $a_TLV_DATA[$i], 'SelectClear')
_GUICtrlListView_SetItemSelected($hListView, $iTVItemIndx)
$i_TLV_CHANGING = False
Case $TVN_ITEMEXPANDINGA, $TVN_ITEMEXPANDINGW
$i_TLV_CHANGING = True
Local $tPOINT = DllStructCreate("int X;int Y")
DllStructSetData($tPOINT, "X", MouseGetPos(0))
DllStructSetData($tPOINT, "Y", MouseGetPos(1))
_WinAPI_ScreenToClient($hTreeView, $tPOINT)
Local $iX = DllStructGetData($tPOINT, "X")
Local $iY = DllStructGetData($tPOINT, "Y")
Local $hTVItem = _GUICtrlTreeView_HitTestItem($hTreeView, $iX, $iY)
If $hTVItem = 0 Then
$hTVItem = _GUICtrlTreeView_GetSelection($hTreeView)
EndIf
If $hTVItem <> 0 Then
Local $iTVItemIndx = _GUICtrlTreeView_Index($hTreeView, $hTVItem) ;$aLVItem
Local $iTVItemID = _GUICtrlTreeView_GetItemParam($hTreeView, $hTVItem) ;$aLVItem
For $j = 1 To $a_TLV_DATA
If $iTVItemID = $a_TLV_DATA[$j] Then
Local $iChilds = _GUICtrlTreeView_GetChildCount($hTreeView, $hTVItem)
If _GUICtrlTreeView_GetExpanded($hTreeView, $hTVItem) Then
For $x = $j + $iChilds To $j + 1 Step -1
GUICtrlDelete($a_TLV_DATA[$x])
$a_TLV_DATA[$x] = 0
Next
Else
Local $iLVSelItem = _GUICtrlListView_GetSelectedIndices($hListView)
_GUICtrlListView_DeleteAllItems($hListView)
For $x = 1 To $a_TLV_DATA
$hParent = _GUICtrlTreeView_GetParentHandle($a_TLV_DATA[$i], $a_TLV_DATA[$x])
;It's a child item, it's not hitted parent item (expanded), and the parent of this item is expanded
If $hParent And $hParent <> $hTVItem And Not _GUICtrlTreeView_GetExpanded($a_TLV_DATA[$i], $hParent) Then
ContinueLoop
EndIf
;Otherwise we create the item (it's visible) and reset the LV Item ID
$a_TLV_DATA[$x] = GUICtrlCreateListViewItem($a_TLV_DATA[$x], $a_TLV_DATA[$i])
Next
_GUICtrlListView_SetItemSelected($hListView, Int($iLVSelItem))
_GUICtrlTreeView_ClickItem($hTreeView, $hTVItem)
EndIf
ExitLoop
EndIf
Next
EndIf
$i_TLV_CHANGING = False
EndSwitch
ExitLoop
EndSwitch
Next
Return $GUI_RUNDEFMSG
EndFunc
; =========================================================================================
; Name...........: _GUICtrlListView_SetFont
; Description ...: Set font for a list-view controls items and header text
; Syntax.........: _GUICtrlListView_SetFont($hWnd, $hFontLV, $hFontHD = 0)
; Parameters ....: $hWnd - Handle to the control
; $hFontLV - Handle to font
; $hFontHD - Handle to header font (Optional)
; Return values .: Success - True
; Failure - False
; Author ........: rover
; Remarks .......: Use optional header font parameter for a different font/size of header
; =========================================================================================
Func __GUICtrlTreeListView_SetFont($hWnd, $hFontLV, $hFontHD = 0)
;If $Debug_LV Then __UDF_ValidateClassName($hWnd, $__LISTVIEWCONSTANT_ClassName)
If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
Local $aReturn, $hHeader, $hDLL
$hHeader = HWnd(_GUICtrlListView_GetHeader($hWnd)) ; get handle to header control
If Not IsHWnd($hWnd) Or Not IsPtr($hFontLV) Or Not IsHWnd($hHeader) Then Return SetError(1, 0, False)
_SendMessage($hWnd, $__LISTVIEWCONSTANT_WM_SETREDRAW, 0) ; disable repainting
$hDLL = DllOpen("UxTheme.dll")
; turn off theme for header control to enable header autosizing
$aReturn = DllCall($hDLL, "int", "SetWindowTheme", "hwnd", $hHeader, "wstr", "", "wstr", "")
If @error Or $aReturn Then
DllClose($hDLL)
Return SetError(2, 0, False)
EndIf
If IsPtr($hFontHD) Then ; set font for items and if available separate font for header
_SendMessage($hWnd, $__LISTVIEWCONSTANT_WM_SETFONT, $hFontLV, True, 0, "hwnd")
_SendMessage($hHeader, $__LISTVIEWCONSTANT_WM_SETFONT, $hFontHD, True, 0, "hwnd")
Else ; set same font for header and items
; resizing header down to a smaller font size causes listview repaint problems, so repainting is enabled
_SendMessage($hWnd, $__LISTVIEWCONSTANT_WM_SETREDRAW, 1) ; enable repainting
_SendMessage($hWnd, $__LISTVIEWCONSTANT_WM_SETFONT, $hFontLV, True, 0, "hwnd")
EndIf
; restore control theme painting
$aReturn = DllCall($hDLL, "int", "SetWindowTheme", "hwnd", $hHeader, "ptr", 0, "ptr", 0)
If @error Or $aReturn Then
DllClose($hDLL)
Return SetError(3, 0, False)
EndIf
DllClose($hDLL)
_SendMessage($hWnd, $__LISTVIEWCONSTANT_WM_SETREDRAW, 1) ; enable repainting
_WinAPI_RedrawWindow($hWnd, 0, 0, $RDW_INVALIDATE)
Return SetError(0, 0, $aReturn <> 1)
EndFunc
下载看看,谢谢,。。
之前也在愁这个,后期就放弃弄这个了
:face (2): 本帖最后由 afan 于 2021-3-29 13:30 编辑
这个可能费力不讨好……除了可折叠,光 ListView 也可以做得更好。当然 ListView 使点劲肯定也能达到折叠效果
比如我的 iWheel 配置界面
谢谢楼主慷慨分享。 afan 发表于 2021-3-29 13:12
这个可能费力不讨好……除了可折叠,光 ListView 也可以做得更好。当然 ListView 使点劲肯定也能达到折叠效 ...
主要是有些场景用这种tree+listview的方式呈现的数据更整洁。 单纯一个listview表现不出层级关系来 afan 发表于 2021-3-29 13:12
这个可能费力不讨好……除了可折叠,光 ListView 也可以做得更好。当然 ListView 使点劲肯定也能达到折叠效 ...
图标都不一样,就很高大上 .
页:
[1]