本帖最后由 tubaba 于 2017-6-21 10:17 编辑
回复 10# kk_lee69
下面是论坛前辈的一个源码,我对虚拟列表这种风格的认识也是从这位前辈开始的,从那这后也使用这种风格写了不少的代码,累积了不少经验,有了自己的见解.
这种风格的listview的显示是随数组的变化而动态变化.如果它的item和subitem范围超出数组的范围.程序就会崩溃.因此,我添加了几个自己写的函数
#Region AutoIt3Wrapper 预编译参数(常用参数)
#AutoIt3Wrapper_Icon= ;图标,支持EXE,DLL,ICO
#AutoIt3Wrapper_OutFile= ;输出文件名
#AutoIt3Wrapper_OutFile_Type=exe ;文件类型
#AutoIt3Wrapper_Compression=4 ;压缩等级
#AutoIt3Wrapper_UseUpx=y ;使用压缩
#AutoIt3Wrapper_Res_Comment= ;注释
#AutoIt3Wrapper_Res_Description= ;详细信息
#AutoIt3Wrapper_Res_Fileversion= ;文件版本
#AutoIt3Wrapper_Res_FileVersion_AutoIncrement=p ;自动更新版本
#AutoIt3Wrapper_Res_LegalCopyright= ;版权
#AutoIt3Wrapper_Change2CUI=N ;修改输出的程序为CUI(控制台程序)
;#AutoIt3Wrapper_Res_Field=AutoIt Version|%AutoItVer% ;自定义资源段
;#AutoIt3Wrapper_Run_Tidy= ;脚本整理
;#AutoIt3Wrapper_Run_Obfuscator= ;代码迷惑
;#AutoIt3Wrapper_Run_AU3Check= ;语法检查
;#AutoIt3Wrapper_Run_Before= ;运行前
;#AutoIt3Wrapper_Run_After= ;运行后
#EndRegion AutoIt3Wrapper 预编译参数设置完成
#cs ____________________________________
Au3 版本:
脚本作者:
Email:
QQ/TM:
脚本版本:
脚本功能:
#ce _______________脚本开始_________________
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiImageList.au3>
#include <WindowsConstants.au3>
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
Local $tText = DllStructCreate("wchar Text[4096]");建个结构,用来放listview列数据
Local $GUI, $hImage, $iITEM_COUNT = 10000
$hGUI = GUICreate("ListView虚拟列表 加载[" & $iITEM_COUNT & "]数据", 760, 400)
$hListView = GUICtrlCreateListView("Item1|nSubItem1|nSubItem2", 2, 2, 760, 294, $LVS_SHOWSELALWAYS + $LVS_OWNERDATA, $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER)
;设置列宽
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 0, 240)
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 1, 240)
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 2, 240)
;创建并关联图像列表
$hImage = _GUIImageList_Create()
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 115)
_GUICtrlListView_SetImageList($hListView, $hImage, 1)
;===================================================================
$Button1 = GUICtrlCreateButton("数据1", 200, 352, 73, 33)
$Button2 = GUICtrlCreateButton("数据2", 300, 352, 73, 33)
$Button3 = GUICtrlCreateButton("清除 ", 400, 352, 73, 33)
Global $tData1[$iITEM_COUNT][3], $tData2[$iITEM_COUNT][3], $aData
For $i = 0 To $iITEM_COUNT - 1
For $j = 0 To 2
$tData1[$i][$j] = ' 数据 1 $aData [' & $i & '][' & $j & ']'
$tData2[$i][$j] = ' 数据 2 $aData [' & $i & '][' & $j & ']'
Next
Next
GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0)
;===================================================================
GUISetState()
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
ExitLoop
Case $Button1
$aData = $tData1
ListView_MatchArray($hListView, $aData)
Case $Button2
$tData2[1][1] = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
$aData = $tData2
ListView_MatchArray($hListView, $aData);数组大小改变时,一定要及时让listview调整col和row,否则会让程序崩溃
Case $Button3
$aData = 0
ListView_MatchArray($hListView, $aData)
EndSwitch
WEnd
GUIDelete()
Exit
Func ListView_MatchArray($ControlID, $iaData, $aColName = '', $Flag = False)
Local $iUBound2, $ColCount, $ColWidth
$iUBound2 = UBound($iaData, 2)
$ColCount = _GUICtrlListView_GetColumnCount($ControlID)
_GUICtrlListView_BeginUpdate($ControlID)
Select
Case $iUBound2 > $ColCount
$ColWidth = Round((_GUICtrlListView_ApproximateViewWidth($ControlID) + 1) / $iUBound2, 1)
For $i = 0 To $iUBound2 - 1
If $i >= $ColCount Then _GUICtrlListView_InsertColumn($ControlID, $i, $i)
GUICtrlSendMsg($ControlID, $LVM_SETCOLUMNWIDTH, $i, $ColWidth)
Next
Case $iUBound2 < $ColCount
$ColWidth = Round((_GUICtrlListView_ApproximateViewWidth($ControlID) + 1) / $iUBound2, 1)
For $i = ($ColCount - 1) To 0 Step -1
If $i >= $iUBound2 Then GUICtrlSendMsg($ControlID, $LVM_DELETECOLUMN, $i, 0)
GUICtrlSendMsg($ControlID, $LVM_SETCOLUMNWIDTH, $i, $ColWidth)
Next
EndSelect
If IsArray($aColName) Then
For $i = 1 To UBound($aColName) - 1
_GUICtrlListView_SetColumn($ControlID, $i, $aColName[$i])
Next
EndIf
GUICtrlSendMsg($ControlID, $LVM_SETITEMCOUNT, UBound($iaData), 0)
If $Flag Then GUICtrlSendMsg($ControlID, $LVM_ENSUREVISIBLE, 0, 0)
_GUICtrlListView_EndUpdate($ControlID)
Update_ListView($ControlID)
EndFunc ;==>ListView_MatchArray
Func Update_ListView($ControlID)
_GUICtrlListView_BeginUpdate($ControlID)
For $i = 0 To _GUICtrlListView_GetColumnCount($ControlID) - 1
_GUICtrlListView_SetColumnWidth($ControlID, $i, $LVSCW_AUTOSIZE)
_GUICtrlListView_SetColumnWidth($ControlID, $i, _GUICtrlListView_GetColumnWidth($ControlID, $i) + 10)
Next
_GUICtrlListView_EndUpdate($ControlID)
_WinAPI_RedrawWindow(GUICtrlGetHandle($ControlID))
EndFunc ;==>Update_ListView
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
#forceref $hWnd, $iMsg, $iwParam
Local $tNMHDR, $iIDFrom, $iCode, $tInfo, $iItem, $iSubItem
$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
$iCode = DllStructGetData($tNMHDR, "Code")
Switch $iIDFrom
Case $hListView
Switch $iCode
Case $LVN_GETDISPINFOA, $LVN_GETDISPINFOW ;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177
If IsArray($aData) Then
$tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
$iItem = DllStructGetData($tInfo, "Item")
$iSubItem = DllStructGetData($tInfo, "SubItem")
If $iSubItem = 0 Then DllStructSetData($tInfo, "Image", 0)
If $iItem >= UBound($aData) Or $iSubItem >= UBound($aData, 2) Then Return ;一定要加上这句,否则在数组快速变化时候可能会造成访问数组下标超限的运行错误
DllStructSetData($tText, "Text", $aData[$iItem][$iSubItem]);
DllStructSetData($tInfo, "Text", DllStructGetPtr($tText));
EndIf
EndSwitch
EndSwitch
EndFunc ;==>WM_NOTIFY
|