找回密码  加入

AUTOIT CN

搜索
楼主: 298311657

[原创] ListView虚表 复选框 原地编辑例子 By_Crossdoor(2015-11-03更新)

[复制链接]
发表于 2015-10-31 22:30:58 | 显示全部楼层
回复 59# chzj589

chzj589  兄

手上有 INPUT 框 重繪 相關的消息範例嗎??
 楼主| 发表于 2015-11-1 22:27:47 | 显示全部楼层
回复 58# kk_lee69

你的这个问题,可以试试这份代码

#cs ______________________
        Au3 版本: 3.3.14.2
        脚本作?? CrossDoor
        电子邮件: [email]382869232@qq.com[/email]
        QQ/TM: 382869232
#ce _______________脚本开始_________________
#PRE_UseX64=n
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <WinAPITheme.au3>
#include <GuiListView.au3>
#include <WinAPISys.au3>
#include <WinAPI.au3>
#include <GuiEdit.au3>
#include <array.au3>
#include <Misc.au3>

Global $B_DESCENDING[3] ; 排序用数组

Global $bCtrlDown = False;listview控件ctrl键按下标识
Global $hEdit, $Item = -1, $SubItem = 0
Global $hEditForm, $hEnter, $aAccelKeys[1][2] = [["{ENTER}", $hEnter]];虚拟控件的句柄和绑定的快捷键

Local $hUser32 = DllOpen("user32.dll")
Local $ichked = 0;勾选的行数
Local $tText = DllStructCreate("wchar Text[256]");建个结构,用来放listview列数据
Local $GUI, $hImage
Local $iITEM_COUNT = 94304, $aShowdata[$iITEM_COUNT][4];注意数组最大项目数为2^24(16777216),所以$iITEM_COUNT = 4194304为二维数组$aShowdata最大行数
Local $sSomeString = ""

GUIRegisterMsg($WM_KEYDOWN, "WM_KEYDOWN")
GUIRegisterMsg($WM_KEYUP, "WM_KEYUP")
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
$hGUI = GUICreate("ListView虚表 加载[" & UBound($aShowdata) & "]数据 复选框 原地编辑例子 By_Crossdoor", 500, 350)

$hListView = GUICtrlCreateListView("Item1|nSubItem1|nSubItem2", 2, 2, 494, 296, BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_OWNERDATA), $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER + $LVS_EX_CHECKBOXES)
;~ _WinAPI_SetWindowTheme(GUICtrlGetHandle($hListView), 'Explorer');设置主题

;设置列宽
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 0, 150)
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 1, 150)
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 2, 150)
GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0);设定数据总数

;===========创建并关联图像列表
$hImage = _GUIImageList_Create()
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 110)
_GUICtrlListView_SetImageList($hListView, $hImage, 1);分配图像列表到列表视图控件

$Button1 = GUICtrlCreateButton("选中行", 20, 310, 75, 25)
$Button2 = GUICtrlCreateButton("未选行", 100, 310, 75, 25)
$Button3 = GUICtrlCreateButton("修改", 180, 310, 75, 25)
$Button4 = GUICtrlCreateButton("清空", 260, 310, 75, 25)
GUISetState()

;==================在窗体显示后再初始化数据,因为初始化数组数据比较慢
;如果先初始化数组后显示窗口,会卡很久,就造成虚表也很慢的假象
For $i = 0 To $iITEM_COUNT - 1
        ;重绘 刷新 listview 0-13行(让ListView显示数组数据),不用太多行,只需要一屏的行数就就可以
        ;因为下拉滚动的时候listview会收到LVN_GETDISPINFO消息,这个消息我们在WM_NOTIFY内处理过了
        If $i = 18 Then GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, $i)
        
        $aShowdata[$i][0] = "爷爷" & $i
        $aShowdata[$i][1] = "爸爸" & $i
        $aShowdata[$i][2] = "儿子" & $i
        $aShowdata[$i][3] = 4096;复选框状态4096未选中 8192选中
Next

While 1
        $bCtrlDown = _IsPressed("11", $hUser32);取ctrl按键的状态
        Switch GUIGetMsg()
                Case -3
                        ExitLoop
                Case $Button1
                        $aShowdata[3][3] = 8192
                        $aShowdata[7][3] = 8192
                        GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 3, 7)
                        
;~                         $a = _GetChkIndex(8192)
;~                         If $a[0] = -1 Then
;~                                 MsgBox(32, "提示", "未勾选任何数据")
;~                         Else
;~                                 _ArrayDisplay($a, "勾选行的索引");数组很大时,_ArrayDisplay会非常耗时
;~                         EndIf
                Case $Button2
                        $a = _GetChkIndex(4096)
                        If $a[0] = -1 Then
                                 MsgBox(32, "提示", "数据全都被勾选了。")
                        Else
                                ;MsgBox(32, "提示", "未勾选的数据有" & UBound($a) & "行")
                                _ArrayDisplay($a, "未勾选行的索");数组很大时,_ArrayDisplay会非常耗时
                        EndIf
                Case $Button3
                        If StringLen($sSomeString) Then
                                $sSomeString = ""
                        Else
                                $sSomeString = Asc(Random(48, 255, 1))
                        EndIf
                        For $i = 0 To $iITEM_COUNT - 1
                                $aShowdata[$i][0] = "爷爷" & $i & "-" & $sSomeString
                                $aShowdata[$i][1] = "爸爸" & $i & "-" & $sSomeString
                                $aShowdata[$i][2] = "儿子" & $i & "-" & $sSomeString
                        Next
                        GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
                        GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
                Case $Button4
                        $aShowdata = 0
                        $iITEM_COUNT = 0
                        GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0)
                        GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
                        GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
        EndSwitch
WEnd
GUIDelete()
DllClose($hUser32)

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
        #forceref $hWnd, $iMsg, $iwParam
        Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo

        $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
        $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
        $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
        $iCode = DllStructGetData($tNMHDR, "Code")
        Local $iIndex = DllStructGetData($tNMHDR, 'Index')
        Switch $iIDFrom
                Case $hListView
                        Switch $iCode
                                Case $LVN_COLUMNCLICK ; 点击列头排序
                                        $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                                        $iSub = DllStructGetData($tInfo, "SubItem")
                                        _ArraySort($aShowdata, $B_DESCENDING[$iSub], 0, 0, $iSub)
                                        GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
                                        GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
                                        $B_DESCENDING[$iSub] = Not $B_DESCENDING[$iSub]
                                Case $NM_CUSTOMDRAW;自绘消息  处理选中行背景色
                                        Local $tCustDraw = DllStructCreate('hwnd hwndFrom;int idFrom;int code;dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;dword clrText;dword clrTextBk;int SubItem; dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align', $ilParam)
                                        Local $iDrawStage = DllStructGetData($tCustDraw, 'DrawStage')
                                        If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
                                        If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
                                        If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
                                        $iIndex = DllStructGetData($tCustDraw, 'ItemSpec')
                                        If $aShowdata[$iIndex][3] = 4096 Then
                                                DllStructSetData($tCustDraw, 'clrTextBk', 0xFFFFFF);BGR格式颜色值
                                        Else
                                                DllStructSetData($tCustDraw, 'clrTextBk', 0xF7D3AD);BGR格式颜色值
                                        EndIf
                                        Return $CDRF_NEWFONT
                                Case $LVN_ITEMCHANGED ; An item has changed
                                        If $bCtrlDown Then;ctrl键按下
                                                $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                                                Local $iIndex = DllStructGetData($tInfo, "Item")
                                                Local $iNewState = DllStructGetData($tInfo, "NewState")
                                                If $iIndex > -1 And $iNewState = BitOR($LVIS_FOCUSED, $LVIS_SELECTED) Then
                                                        If $aShowdata[$iIndex][3] = 4096 Then
                                                                $ichked+=1
                                                                $aShowdata[$iIndex][3] = 8192;4096未选中 8192选中
                                                        Else
                                                                $ichked-=1
                                                                $aShowdata[$iIndex][3] = 4096;4096未选中 8192选中
                                                        EndIf
                                                        $tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
                                                        DllStructSetData($tInfo, "State", $aShowdata[$iIndex][3]);设置复选框状态
                                                        ;====立刻刷新复选框显示状态 重绘$iIndex-1到iIndex+20的项
                                                        GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, $iIndex - 1, $iIndex + 20)
                                                EndIf
                                        EndIf
                Case $LVN_BEGINSCROLL ; 滚动事件开始
                                        If IsHWnd($hEdit) Then _EndItemEdit();如果存在$hEdit控件,则结束编辑
;~                                         $tInfo = DllStructCreate($tagNMLVSCROLL, $ilParam)
;~                                         ToolTip("$LVN_BEGINSCROLL" & @CRLF & "--> hWndFrom:" & @TAB & $hWndFrom & @CRLF & _
;~                                         "-->IDFrom:" & @TAB & $iIDFrom & @CRLF & _
;~                                         "-->Code:" & @TAB & $iCode & @CRLF & _
;~                                         "-->DX:" & @TAB & DllStructGetData($tInfo, "DX") & @CRLF & _
;~                                         "-->DY:" & @TAB & DllStructGetData($tInfo, "DY"))
                ; ; No return value                                        
                                Case $NM_CLICK;单击
                                        If IsHWnd($hEdit) Then _EndItemEdit()
                                        $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                                        $iIndex = DllStructGetData($tInfo, "Index")
                                        $x = DllStructGetData($tInfo, "X")
                                        If ($x < 16) And (3 < $x) And (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hListView), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then;使用点击的x坐标来判断是否在复选框上点击
                                                If $aShowdata[$iIndex][3] = 4096 Then
                                                        $ichked+=1
                                                        $aShowdata[$iIndex][3] = 8192;4096未选中 8192选中
                                                Else
                                                        $ichked-=1
                                                        $aShowdata[$iIndex][3] = 4096;4096未选中 8192选中
                                                EndIf
                                                ;====立刻刷新复选框显示状态 重绘$iIndex-1至iIndex+20的项
                                                GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, $iIndex - 1, $iIndex + 20)
                                        EndIf
                                Case $NM_DBLCLK ; 双击
                                        $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                                        $iIndex = DllStructGetData($tInfo, "Index")
                                        $iSub = DllStructGetData($tInfo, "SubItem")
                                        $x = DllStructGetData($tInfo, "X")
                                        If ($iIndex <> -1) And ($iSub >= 0) And ($x > 16) Then;点击的x>16才响应原地编辑
                                                Local $aformPos = WinGetPos($hGUI)
                                                Local $SM_CYCAPTION = 4
                                                Local $iCaptionH = _WinAPI_GetSystemMetrics($SM_CYCAPTION);获取以像素计算的普通窗口标题的高度
                                                $Item = $iIndex
                                                $SubItem = $iSub
                                                ;==========计算编辑框坐标
                                                Local $aRect = _GUICtrlListView_GetSubItemRect($hListView, $iIndex, $iSub)
                                                Local $iEdit_X = $aRect[0] + 8 + $aformPos[0]
                                                Local $iEdit_Y = $aRect[1] + 7 + $aformPos[1] + $iCaptionH
                                                Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($hListView, $iSub)
                                                Local $iEdit_Height = $aRect[3] - $aRect[1]
                                                If $iSub = 0 Then
                                                        Local $i1 = 0, $i2 = 0
                                                        If (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hListView), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then $i1 = 18;判断是否有复选框
                                                        If _GUICtrlListView_GetImageList($hListView, 1) Then $i2 = 20;判断是否有分配图像列表到列表视图控件
                                                        $iEdit_X += ($i2 + $i1)
                                                        $iEdit_Width -= ($i2 + $i1)
                                                EndIf
                                                $hEditForm = GUICreate("", $iEdit_Width, $iEdit_Height, $iEdit_X, $iEdit_Y, $WS_POPUP, -1, $hGUI);创建一个子窗口用于装载input控件
                                                Local $iEdit = GUICtrlCreateInput($aShowdata[$iIndex][$iSub], 0, 0, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_LEFT))
                                                GUICtrlSetFont($iEdit, 12)
                                                GUICtrlSetState($iEdit, $GUI_FOCUS)
                                                $hEdit = GUICtrlGetHandle($iEdit)
                                                _GUICtrlEdit_SetSel($hEdit, 0, -1) ;全选编辑框文字
                                                Local $iEnter = GUICtrlCreateDummy()
                                                $hEnter = GUICtrlGetHandle($iEnter)
                                                GUISetAccelerators($aAccelKeys, $hWnd);在虚拟控件上绑定一个回车快捷按键
                                                GUISetState(@SW_SHOW, $hEditForm)
                                        EndIf

                                Case -150, -177 ;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177   请求显示数据
                                        If Not IsArray($aShowdata) Then ContinueCase
                                        $tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
                                        $iIndex = Int(DllStructGetData($tInfo, "Item"))
                                        $iSub = Int(DllStructGetData($tInfo, "SubItem"))

                                        If BitAND(DllStructGetData($tInfo, "Mask"), $LVIF_IMAGE) And $iSub = 0 Then DllStructSetData($tInfo, "Image", 0);判断是否有LVIF_IMAGE属性,有则设置列图像。不设置_GUICtrlListView_SetImageList则无

                                        If (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hListView), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then
                                                ;===============设置复选框信息
                                                DllStructSetData($tInfo, "Mask", BitOR($LVIF_STATE, DllStructGetData($tInfo, "Mask")))
                                                DllStructSetData($tInfo, "StateMask", $LVIS_STATEIMAGEMASK)
                                                DllStructSetData($tInfo, "State", $aShowdata[$iIndex][3])
                                        EndIf

                                        DllStructSetData($tText, "Text", $aShowdata[$iIndex][$iSub]);列数据放入$tText结构
                                        DllStructSetData($tInfo, "Text", DllStructGetPtr($tText));$tText结构的指针来设置列数据
                                        DllStructSetData($tInfo, "TextMax", StringLen($aShowdata[$iIndex][$iSub]));设置列数据字串长
                        EndSwitch
        EndSwitch
        Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY


Func WM_KEYDOWN($hWnd, $iMsg, $wParam, $lParam)
        If $wParam = 27 Then $bCtrlDown = True
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_KEYDOWN

Func WM_KEYUP($hWnd, $iMsg, $wParam, $lParam)
        If $wParam = 27 Then $bCtrlDown = False
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_KEYUP

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
        $iIDFrom = _WinAPI_LoWord($wParam)
        $iCode = _WinAPI_HiWord($wParam)
        Switch $lParam
                Case $hEdit
                        Switch $iCode
                                Case $EN_KILLFOCUS
                                        
                                Case $EN_UPDATE

                        EndSwitch
                Case $hEnter;虚拟控件消息触发  收到回车消息才触发
                        If IsHWnd($hEdit) Then
                                _EndItemEdit()
                        EndIf
        EndSwitch
        Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

Func _EndItemEdit()
        If ($Item < UBound($aShowdata, 1)) And ($SubItem < UBound($aShowdata, 2)) Then
                Local $sText = _GUICtrlEdit_GetText($hEdit)
                _GUICtrlListView_SetItemText($hListView, $Item, $sText, $SubItem)
                If IsHWnd($hEdit) Then _WinAPI_DestroyWindow($hEdit)
                If IsHWnd($hEnter) Then _WinAPI_DestroyWindow($hEnter)
                If IsHWnd($hEditForm) Then GUIDelete($hEditForm)
                $hEditForm = Null
                $hEnter = Null
                $hEdit = Null
                If ($Item >= 0) Then
                        $aShowdata[$Item][$SubItem] = $sText
                        GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
                EndIf
                $Item = -1
                $SubItem = 0
        EndIf
EndFunc   ;==>_EndItemEdit

Func _GetChkIndex($iChkState)
        Local $aIndex[1] = [-1], $j = 0
        If $ichked = 0 Then Return $aIndex
        If $iChkState = 8192 Then
                ReDim $aIndex[$ichked]
        Else
                ReDim $aIndex[UBound($aShowdata)-$ichked]
        EndIf
        For $i = 0 To UBound($aShowdata) -1
                If $aShowdata[$i][3] == $iChkState Then
                        $aIndex[$j] = $i
                        $j+=1
                EndIf
        Next
        Return $aIndex
EndFunc
发表于 2015-11-1 23:54:15 | 显示全部楼层
回复 62# 298311657
OK 老大 太感謝您了 ~~

原來再多加一個透明的 $hEditForm  就可以解決掉 很多殘影了問題

太感謝了~~~
发表于 2015-11-2 01:23:02 | 显示全部楼层
回复 62# 298311657

老大 有個地方搞不懂 還真的有點怪
新舊方法 在計算 INPUT框 位置的時候  有問題

原本的範例裡面 沒有考慮進去 如果 LISTVIEW 的位置 不是從最上面開始的話
所以 我後來改了計算法法
OK 了

改成 新版的 方式 可是框的位置不對了
程式沒變動到  但是位置 不對了 我不知道是何原因




計算位置的算法如下

[AU3]
;==========計算編輯方塊座標
Local $aPos = ControlGetPos("", "", $hVListView);獲取Listview座標
Local $aRect = _GUICtrlListView_GetSubItemRect($hVListView, $Item, $SubItem)
       
Local $iEdit_X = $aRect[0]+$aPos[0] + 4
Local $iEdit_Y = $aRect[1]+$aPos[1] + 3
Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($hVListView, $SubItem) ;+ 3
Local $iEdit_Height = $aRect[3] - $aRect[1]; + 3
       
If $SubItem = 0 Then
        Local $i1 = 0, $i2 = 0
        If (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hVListView), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then $i1 = 18;判斷是否有核取方塊
        If _GUICtrlListView_GetImageList($hVListView, 1) Then $i2 = $hImageX;判斷是否有分配圖像清單到清單視圖控制項
        $iEdit_X += ($i2 + $i1)
        $iEdit_Width -= ($i2 + $i1)
EndIf


;新版程式的寫法
$hEditForm = GUICreate("", $iEdit_Width, $iEdit_Height, $iEdit_X, $iEdit_Y, $WS_POPUP, -1, $WinMain);創建一個子視窗用於裝載input控制項
$iEdit = GUICtrlCreateInput($aShowdata2[$Item][$SubItem], 0, 0, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_LEFT));BitOR($WS_CHILD, $WS_VISIBLE, $ES_AUTOHSCROLL, $ES_LEFT )



;舊版程式的寫法
$hEdit = GUICtrlCreateInput( $aShowdata2[$Item][$SubItem], $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height );,$ES_RIGHT 右對齊[/AU3]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?加入

x
发表于 2015-11-2 02:06:35 | 显示全部楼层
回复 64# kk_lee69

老大找到方法了  原來你的範例裡面有考慮到 剛剛沒注意
Local $aformPos = WinGetPos($WinMain)

這個加上去就可以了 感謝  另外

有個問一可以請教嗎??

這個我想只有您能解決這個問題

一個畫面裡面  如果同時要兩個 LISTVIEW 就得要兩個 $aShowdata
一個程式裡面  如果 會用到10個 就得要10個 $aShowdata
因為 每個LISTVIEW 的單擊 雙擊 的需求都不一樣

這樣寫下來 程式好長喔

有辦法縮短 或者弄成 UDF 嗎??

譬如 _EndItemEdit 這個是 一個 函數
我有10個 LISTVIEW 都要共用這個 所以 我設了第11個 共用的 LISTVIEW 譬如叫做 HLISTVIEW
這樣我只要  HLISTVIEW=ListView1  或者 HLISTVIEW=ListView2
這樣在 函數裡面就可以用
但是  $aShowdata  卻不能這樣用.......
目前的做法只好是

Select
        Case $hVListView = $VListView1
                $aShowdata1
        Case $hVListView = $VListView2
                $aShowdata2
        Case $hVListView = $VListView3
                $aShowdata3
               
EndSelect

這樣一個一個寫

所以 想請教 您在實際應用上 有更好的簡便寫法 可學習嗎??
发表于 2015-11-2 08:13:56 | 显示全部楼层
谢谢LZ分享~!
 楼主| 发表于 2015-11-2 21:57:48 | 显示全部楼层
本帖最后由 298311657 于 2015-11-3 13:43 编辑

回复 65# kk_lee69

对数据进行判断并没有简洁的写法,因为不同的数据对应不同的处理方法。
UDF只是把可以重复的代码打包成函数,以便调用。数据判断显然不是可以重复的代码,每一个数据都是独立的。

比如我们可以把listview请求数据显示部分写成函数:
Func _LVN_GETDISPINFO($hlst, $ilParam, ByRef $aDataArray)
        If Not IsArray($aDataArray) Then Return
        $tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
        $iIndex = Int(DllStructGetData($tInfo, "Item"))
        $iSub = Int(DllStructGetData($tInfo, "SubItem"))

        If BitAND(DllStructGetData($tInfo, "Mask"), $LVIF_IMAGE) And $iSub = 0 Then DllStructSetData($tInfo, "Image", 0);判断是否有LVIF_IMAGE属性,有则设置列图像。不设置_GUICtrlListView_SetImageList则无

        If (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hlst), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then
                ;===============设置复选框信息
                DllStructSetData($tInfo, "Mask", BitOR($LVIF_STATE, DllStructGetData($tInfo, "Mask")))
                DllStructSetData($tInfo, "StateMask", $LVIS_STATEIMAGEMASK)
                DllStructSetData($tInfo, "State", $aDataArray[$iIndex][3])
        EndIf

        DllStructSetData($tText, "Text", $aDataArray[$iIndex][$iSub]);列数据放入$tText结构
        DllStructSetData($tInfo, "Text", DllStructGetPtr($tText));$tText结构的指针来设置列数据
        DllStructSetData($tInfo, "TextMax", StringLen($aDataArray[$iIndex][$iSub]));设置列数据字串长
EndFunc

   
然后再调用:
Case -150, -177 ;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177   请求显示数据
        _LVN_GETDISPINFO($iIDFrom, $ilParam, $aShowdata3)



这是一份完整的代码,我在这里使用了3个listview控件:
#cs ______________________
    Au3 版本: 3.3.14.2
    脚本作?? CrossDoor
    电子邮件: [email]382869232@qq.com[/email]
    QQ/TM: 382869232
#ce _______________脚本开始_________________
#PRE_UseX64=n
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <WinAPITheme.au3>
#include <GuiListView.au3>
#include <WinAPISys.au3>
#include <WinAPI.au3>
#include <GuiEdit.au3>
#include <array.au3>
#include <Misc.au3>

Global $B_DESCENDING[3] ; 排序用数组

Global $hActLst
Global $bCtrlDown = False;listview控件ctrl键按下标识
Global $hEdit, $Item = -1, $SubItem = 0
Global $hEnter, $aAccelKeys[1][2] = [["{ENTER}", $hEnter]];虚拟控件的句柄和绑定的快捷键

Local $hUser32 = DllOpen("user32.dll")
Local $ichked = 0;勾选的行数
Local $tText = DllStructCreate("wchar Text[256]");建个结构,用来放listview列数据
Local $GUI, $hImage
Local $iITEM_COUNT = 1000, $aShowdata[$iITEM_COUNT][4], $aShowdata2[$iITEM_COUNT][4], $aShowdata3[$iITEM_COUNT][4];注意数组最大项目数为2^24(16777216),所以$iITEM_COUNT = 4194304为二维数组$aShowdata最大行数
Local $sSomeString = ""
Local $hGUI, $hListView, $hListView2, $hListView3

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
$hGUI = GUICreate("ListView虚表 加载[" & UBound($aShowdata) & "]数据 复选框 原地编辑例子 By_Crossdoor", 600, 605)

$hListView = GUICtrlCreateListView("$hListView| | ", 2, 2, 295, 296, BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_OWNERDATA), $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER + $LVS_EX_CHECKBOXES)
;~ _WinAPI_SetWindowTheme(GUICtrlGetHandle($hListView), "Explorer");设置主题

;设置列宽
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 0, 110)
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 1, 80)
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 2, 80)
GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0);设定数据总数



$hListView2 = GUICtrlCreateListView("$hListView2| | ", 300, 2, 295, 296, BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_OWNERDATA), $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER)
;~ _WinAPI_SetWindowTheme(GUICtrlGetHandle($hListView), "Explorer");设置主题

;设置列宽
GUICtrlSendMsg($hListView2, $LVM_SETCOLUMNWIDTH, 0, 110)
GUICtrlSendMsg($hListView2, $LVM_SETCOLUMNWIDTH, 1, 80)
GUICtrlSendMsg($hListView2, $LVM_SETCOLUMNWIDTH, 2, 80)
GUICtrlSendMsg($hListView2, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0);设定数据总数


$hListView3 = GUICtrlCreateListView("$hListView3| | ", 300, 300, 295, 296, BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_OWNERDATA), $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER + $LVS_EX_CHECKBOXES)
;~ _WinAPI_SetWindowTheme(GUICtrlGetHandle($hListView), "Explorer");设置主题

;设置列宽
GUICtrlSendMsg($hListView3, $LVM_SETCOLUMNWIDTH, 0, 110)
GUICtrlSendMsg($hListView3, $LVM_SETCOLUMNWIDTH, 1, 80)
GUICtrlSendMsg($hListView3, $LVM_SETCOLUMNWIDTH, 2, 80)
GUICtrlSendMsg($hListView3, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0);设定数据总数

;===========创建并关联图像列表
$hImage = _GUIImageList_Create()
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 110)
_GUICtrlListView_SetImageList($hListView, $hImage, 1);分配图像列表到列表视图控件$hListView
_GUICtrlListView_SetImageList($hListView2, $hImage, 1);分配图像列表到列表视图控件$hListView2

$Button1 = GUICtrlCreateButton("选中行", 10, 310, 70, 25)
$Button2 = GUICtrlCreateButton("未选行", 80, 310, 70, 25)
$Button3 = GUICtrlCreateButton("修改", 150, 310, 70, 25)
$Button4 = GUICtrlCreateButton("清空", 220, 310, 70, 25)
GUISetState()

;==================在窗体显示后再初始化数据,因为初始化数组数据比较慢
;如果先初始化数组后显示窗口,会卡很久,就造成虚表也很慢的假象
For $i = 0 To $iITEM_COUNT - 1
    ;重绘 刷新 listview 0-13行(让ListView显示数组数据),不用太多行,只需要一屏的行数就就可以
    ;因为下拉滚动的时候listview会收到LVN_GETDISPINFO消息,这个消息我们在WM_NOTIFY内处理过了
    If $i = 18 Then
        GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, $i)
        GUICtrlSendMsg($hListView2, $LVM_REDRAWITEMS, 0, $i)
        GUICtrlSendMsg($hListView3, $LVM_REDRAWITEMS, 0, $i)
    EndIf
    
    $aShowdata[$i][0] = "爷爷" & $i
    $aShowdata[$i][1] = "爸爸" & $i
    $aShowdata[$i][2] = "儿子" & $i
    $aShowdata[$i][3] = 4096;复选框状态4096未选中 8192选中
    
    $aShowdata2[$i][0] = "2爷爷" & $i
    $aShowdata2[$i][1] = "2爸爸" & $i
    $aShowdata2[$i][2] = "2儿子" & $i
    $aShowdata2[$i][3] = 4096;复选框状态4096未选中 8192选中
    
    
    $aShowdata3[$i][0] = "3爷爷" & $i
    $aShowdata3[$i][1] = "3爸爸" & $i
    $aShowdata3[$i][2] = "3儿子" & $i
    $aShowdata3[$i][3] = 4096;复选框状态4096未选中 8192选中
Next

While 1
    $bCtrlDown = _IsPressed("11", $hUser32);取ctrl按键的状态
    Switch GUIGetMsg()
        Case -3
            ExitLoop
        Case $Button1
            $aShowdata[3][3] = 8192
            $aShowdata[7][3] = 8192
            GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 3, 7)
            
;~             $a = _GetChkIndex(8192)
;~             If $a[0] = -1 Then
;~                 MsgBox(32, "提示", "未勾选任何数据")
;~             Else
;~                 _ArrayDisplay($a, "勾选行的索引");数组很大时,_ArrayDisplay会非常耗时
;~             EndIf
        Case $Button2
            $a = _GetChkIndex(4096)
            If $a[0] = -1 Then
                 MsgBox(32, "提示", "数据全都被勾选了。")
            Else
                ;MsgBox(32, "提示", "未勾选的数据有" & UBound($a) & "行")
                _ArrayDisplay($a, "未勾选行的索");数组很大时,_ArrayDisplay会非常耗时
            EndIf
        Case $Button3
            If StringLen($sSomeString) Then
                $sSomeString = ""
            Else
                $sSomeString = Asc(Random(48, 255, 1))
            EndIf
            For $i = 0 To $iITEM_COUNT - 1
                $aShowdata[$i][0] = "爷爷" & $i & "-" & $sSomeString
                $aShowdata[$i][1] = "爸爸" & $i & "-" & $sSomeString
                $aShowdata[$i][2] = "儿子" & $i & "-" & $sSomeString
            Next
            GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
            GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
        Case $Button4
            $aShowdata = 0
            $iITEM_COUNT = 0
            GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0)
            GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
            GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
    EndSwitch
WEnd
GUIDelete()
DllClose($hUser32)

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    
    Local $iIndex = DllStructGetData($tNMHDR, "Index")
    Switch $iIDFrom
        Case $hListView
            Switch $iCode
                Case $LVN_COLUMNCLICK ; 点击列头排序
                    _SortItems($iIDFrom, $ilParam, $aShowdata)
                Case $NM_CUSTOMDRAW;自绘消息  处理选中行背景色
;~                     _SetchkboxBkClr($ilParam, $aShowdata)
                    Local $tCustDraw = DllStructCreate("hwnd hwndFrom;int idFrom;int code;dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;dword clrText;dword clrTextBk;int SubItem; dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align", $ilParam)
;~                     
                    Local $iDrawStage = DllStructGetData($tCustDraw, "DrawStage")
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
                    If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
                    $iIndex = DllStructGetData($tCustDraw, "ItemSpec")
                    If $aShowdata[$iIndex][3] = 4096 Then
                        DllStructSetData($tCustDraw, "clrTextBk", 0xFFFFFF);BGR格式颜色值
                    Else
                        DllStructSetData($tCustDraw, "clrTextBk", 0xF7D3AD);BGR格式颜色值
                    EndIf
                    Return $CDRF_NEWFONT
                Case $LVN_ITEMCHANGED ; An item has changed
                    _CtrlSel($iIDFrom, $ilParam, $aShowdata)
                Case $LVN_BEGINSCROLL ; 滚动事件开始
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata);如果存在$hEdit控件,则结束编辑                           
                Case $NM_CLICK;单击
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata)
                    _chkboxState($iIDFrom, $ilParam, $aShowdata);刷新复选框状态
                Case $NM_DBLCLK ; 双击
                    _StartItemEdit($iIDFrom, $ilParam, $aShowdata);开始原地编辑
                Case -150, -177 ;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177   请求显示数据
                    _LVN_GETDISPINFO($iIDFrom, $ilParam, $aShowdata)
            EndSwitch
        Case $hListView2
            Switch $iCode
                Case -150, -177 ;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177   请求显示数据
                    _LVN_GETDISPINFO($iIDFrom, $ilParam, $aShowdata2)
                Case $LVN_COLUMNCLICK ; 点击列头排序
                    _SortItems($iIDFrom, $ilParam, $aShowdata2)
                Case $NM_CUSTOMDRAW;自绘消息  处理选中行背景色
                    Local $tCustDraw = DllStructCreate("hwnd hwndFrom;int idFrom;int code;dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;dword clrText;dword clrTextBk;int SubItem; dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align", $ilParam)
                    Local $iDrawStage = DllStructGetData($tCustDraw, "DrawStage")
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
                    If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
                    $iIndex = DllStructGetData($tCustDraw, "ItemSpec")
                    If $aShowdata2[$iIndex][3] = 4096 Then
                        DllStructSetData($tCustDraw, "clrTextBk", 0xFFFFFF);BGR格式颜色值
                    Else
                        DllStructSetData($tCustDraw, "clrTextBk", 0xF7D3AD);BGR格式颜色值
                    EndIf
                    Return $CDRF_NEWFONT
                Case $LVN_ITEMCHANGED ; An item has changed
                    _CtrlSel($iIDFrom, $ilParam, $aShowdata2)
                Case $LVN_BEGINSCROLL ; 滚动事件开始
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata2);如果存在$hEdit控件,则结束编辑
                Case $NM_CLICK;单击
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata2)
                    _chkboxState($iIDFrom, $ilParam, $aShowdata2)
                Case $NM_DBLCLK ; 双击
                    _StartItemEdit($iIDFrom, $ilParam, $aShowdata2)
            EndSwitch
        Case $hListView3
            Switch $iCode
                Case -150, -177 ;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177   请求显示数据
                    _LVN_GETDISPINFO($iIDFrom, $ilParam, $aShowdata3)
                Case $LVN_COLUMNCLICK ; 点击列头排序
                    _SortItems($iIDFrom, $ilParam, $aShowdata3)
                Case $NM_CUSTOMDRAW;自绘消息  处理选中行背景色
                    Local $tCustDraw = DllStructCreate("hwnd hwndFrom;int idFrom;int code;dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;dword clrText;dword clrTextBk;int SubItem; dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align", $ilParam)
                    Local $iDrawStage = DllStructGetData($tCustDraw, "DrawStage")
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
                    If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
                    $iIndex = DllStructGetData($tCustDraw, "ItemSpec")
                    If $aShowdata3[$iIndex][3] = 4096 Then
                        DllStructSetData($tCustDraw, "clrTextBk", 0xFFFFFF);BGR格式颜色值
                    Else
                        DllStructSetData($tCustDraw, "clrTextBk", 0xF7D3AD);BGR格式颜色值
                    EndIf
                    Return $CDRF_NEWFONT
                Case $LVN_ITEMCHANGED ; An item has changed
                    _CtrlSel($iIDFrom, $ilParam, $aShowdata3)
                Case $LVN_BEGINSCROLL ; 滚动事件开始
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata3);如果存在$hEdit控件,则结束编辑
                Case $NM_CLICK;单击
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata3)
                    _chkboxState($iIDFrom, $ilParam, $aShowdata3)
                Case $NM_DBLCLK ; 双击
                    _StartItemEdit($iIDFrom, $ilParam, $aShowdata3)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc
 
Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $iIDFrom = _WinAPI_LoWord($wParam)
    $iCode = _WinAPI_HiWord($wParam)
    Switch $lParam
        Case $hEdit
            Switch $iCode
                Case $EN_KILLFOCUS;编辑框失去焦点,结束编辑
                    Switch $hActLst
                        Case $hListView
                            _EndItemEdit($hListView, $aShowdata)
                        Case $hListView2
                            _EndItemEdit($hListView2, $aShowdata2)
                        Case $hListView3
                            _EndItemEdit($hListView3, $aShowdata3)
                    EndSwitch
                Case $EN_UPDATE

            EndSwitch
        Case $hEnter;虚拟控件消息触发  收到回车消息才触发
            If IsHWnd($hEdit) Then
                If $SubItem = 0 Then
                    __ClickListViewItem($hActLst, $Item, True);使用点击来结束编辑,省去判断listview的数据数组
                Else
                    __ClickListViewItem($hActLst, $Item)
                EndIf
            EndIf
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _SetchkboxBkClr(ByRef $ilParam, ByRef $aDataArray)
    Local $tCustDraw = DllStructCreate("hwnd hwndFrom;int idFrom;int code;dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;dword clrText;dword clrTextBk;int SubItem; dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align", $ilParam)
    Local $iDrawStage = DllStructGetData($tCustDraw, "DrawStage")
    
    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
    If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
    $iIndex = DllStructGetData($tCustDraw, "ItemSpec")
    If $aDataArray[$iIndex][3] = 4096 Then
        DllStructSetData($tCustDraw, "clrTextBk", 0xFFFFFF);BGR格式颜色值
    Else
        DllStructSetData($tCustDraw, "clrTextBk", 0xF7D3AD);BGR格式颜色值
    EndIf    
EndFunc

Func _chkboxState($hlst, $ilParam, ByRef $aDataArray);刷新复选框状态
    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
    $iIndex = DllStructGetData($tInfo, "Index")
    $x = DllStructGetData($tInfo, "X")
    If ($x < 16) And (3 < $x) And (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hlst), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then;使用点击的x坐标来判断是否在复选框上点击
        If $aDataArray[$iIndex][3] = 4096 Then
            $ichked+=1
            $aDataArray[$iIndex][3] = 8192;4096未选中 8192选中
        Else
            $ichked-=1
            $aDataArray[$iIndex][3] = 4096;4096未选中 8192选中
        EndIf
        ;====立刻刷新复选框显示状态 重绘$iIndex项
        GUICtrlSendMsg($hlst, $LVM_REDRAWITEMS, $iIndex, $iIndex)
    EndIf    
EndFunc

Func _SortItems($hlst, $ilParam, ByRef $aDataArray);排序
    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
    $iSub = DllStructGetData($tInfo, "SubItem")
    _ArraySort($aDataArray, $B_DESCENDING[$iSub], 0, 0, $iSub)
    GUICtrlSendMsg($hlst, $LVM_REDRAWITEMS, 0, 20)
    $B_DESCENDING[$iSub] = Not $B_DESCENDING[$iSub]
EndFunc

Func _CtrlSel($hlst, $ilParam, ByRef $aDataArray);按住ctrl键点选item
    If $bCtrlDown Then;ctrl键按下
        $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
        Local $iIndex = DllStructGetData($tInfo, "Item")
        Local $iNewState = DllStructGetData($tInfo, "NewState")
        If $iIndex > -1 And $iNewState = BitOR($LVIS_FOCUSED, $LVIS_SELECTED) Then
            If $aDataArray[$iIndex][3] = 4096 Then
                $ichked+=1
                $aDataArray[$iIndex][3] = 8192;4096未选中 8192选中
            Else
                $ichked-=1
                $aDataArray[$iIndex][3] = 4096;4096未选中 8192选中
            EndIf
            $tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
            DllStructSetData($tInfo, "State", $aDataArray[$iIndex][3]);设置复选框状态
            ;====立刻刷新复选框显示状态 重绘$iIndex项
            GUICtrlSendMsg($hlst, $LVM_REDRAWITEMS, $iIndex, $iIndex)
        EndIf
    EndIf
EndFunc

Func _LVN_GETDISPINFO($hlst, $ilParam, ByRef $aDataArray)
    If Not IsArray($aDataArray) Then Return
    $tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
    $iIndex = Int(DllStructGetData($tInfo, "Item"))
    $iSub = Int(DllStructGetData($tInfo, "SubItem"))

    If BitAND(DllStructGetData($tInfo, "Mask"), $LVIF_IMAGE) And $iSub = 0 Then DllStructSetData($tInfo, "Image", 0);判断是否有LVIF_IMAGE属性,有则设置列图像。不设置_GUICtrlListView_SetImageList则无

    If (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hlst), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then
        ;===============设置复选框信息
        DllStructSetData($tInfo, "Mask", BitOR($LVIF_STATE, DllStructGetData($tInfo, "Mask")))
        DllStructSetData($tInfo, "StateMask", $LVIS_STATEIMAGEMASK)
        DllStructSetData($tInfo, "State", $aDataArray[$iIndex][3])
    EndIf

    DllStructSetData($tText, "Text", $aDataArray[$iIndex][$iSub]);列数据放入$tText结构
    DllStructSetData($tInfo, "Text", DllStructGetPtr($tText));$tText结构的指针来设置列数据
    DllStructSetData($tInfo, "TextMax", StringLen($aDataArray[$iIndex][$iSub]));设置列数据字串长
EndFunc

Func _StartItemEdit($hlst, $ilParam, ByRef $aDataArray)
    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
    $iIndex = DllStructGetData($tInfo, "Index")
    $iSub = DllStructGetData($tInfo, "SubItem")
    $x = DllStructGetData($tInfo, "X")
    If ($iIndex <> -1) And ($iSub >= 0) And ($x > 16) Then;点击的x>16才响应原地编辑
        $hActLst = $hlst
        If _GUICtrlListView_EnsureVisible($hlst, $iIndex) Then GUICtrlSendMsg($hlst, $LVM_REDRAWITEMS, $iIndex, $iIndex + 1);确保列表视图项目可见
        Local $alstPos = ControlGetPos($hGUI, "", $hlst)
        $Item = $iIndex
        $SubItem = $iSub
        ;==========计算编辑框坐标
        Local $aRect = _GUICtrlListView_GetSubItemRect($hlst, $iIndex, $iSub)
        Local $iEdit_X = $aRect[0] + $alstPos[0] + 4
        Local $iEdit_Y = $aRect[1] + $alstPos[1] + 2
        Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($hlst, $iSub) - 1
        Local $iEdit_Height = $aRect[3] - $aRect[1]
        If $iSub = 0 Then
            Local $i1 = 0, $i2 = 0
            If (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hlst), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then $i1 = 17;判断是否有复选框
            If _GUICtrlListView_GetImageList($hlst, 1) Then $i2 = 19;判断是否有分配图像列表到列表视图控件
            $iEdit_X += ($i2 + $i1)
            $iEdit_Width -= ($i2 + $i1)
        EndIf
        Local $iEdit = GUICtrlCreateInput($aDataArray[$iIndex][$iSub], $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_LEFT))
        GUICtrlSetFont($iEdit, 11)
        GUICtrlSetState($iEdit, $GUI_FOCUS)
        $hEdit = GUICtrlGetHandle($iEdit)
        _WinAPI_BringWindowToTop($hEdit)
        _GUICtrlEdit_SetSel($hEdit, 0, -1) ;全选编辑框文字
        Local $iEnter = GUICtrlCreateDummy()
        $hEnter = GUICtrlGetHandle($iEnter)
        GUISetAccelerators($aAccelKeys, $hGUI);在虚拟控件上绑定一个回车快捷按键
    EndIf    
EndFunc

Func _EndItemEdit($hlst, ByRef $aDataArray)
    If ($Item < UBound($aDataArray, 1)) And ($SubItem < UBound($aDataArray, 2)) And ($hActLst == $hlst) Then
        Local $sText = _GUICtrlEdit_GetText($hEdit)
        _GUICtrlListView_SetItemText($hlst, $Item, $sText, $SubItem)
        If IsHWnd($hEdit) Then _WinAPI_DestroyWindow($hEdit)
        If IsHWnd($hEnter) Then _WinAPI_DestroyWindow($hEnter)
        $hEnter = Null
        $hEdit = Null
        If ($Item >= 0) Then $aDataArray[$Item][$SubItem] = $sText
        $Item = -1
        $SubItem = 0
    EndIf
EndFunc
 
Func _GetChkIndex($iChkState)
    Local $aIndex[1] = [-1], $j = 0
    If $ichked = 0 Then Return $aIndex
    If $iChkState = 8192 Then
        ReDim $aIndex[$ichked]
    Else
        ReDim $aIndex[UBound($aShowdata)-$ichked]
    EndIf
    For $i = 0 To UBound($aShowdata) -1
        If $aShowdata[$i][3] == $iChkState Then
            $aIndex[$j] = $i
            $j+=1
        EndIf
    Next
    Return $aIndex
EndFunc

Func __ClickListViewItem($hWnd, $iIndex, $baddX = False)
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)

    Local $tRECT = _GUICtrlListView_GetItemRectEx($hWnd, $iIndex, $LVIR_LABEL)
    Local $tPoint = _WinAPI_PointFromRect($tRECT, True)
    $tPoint = _WinAPI_ClientToScreen($hWnd, $tPoint)
    Local $iX, $iY
    _WinAPI_GetXYFromPoint($tPoint, $iX, $iY)
    If $baddX Then $iX += DllStructGetData($tRECT, "Right")
    Local $iMode = Opt("MouseCoordMode", 1)
    Local $aPos = MouseGetPos()
    MouseClick("left", $iX, $iY, 1, 0)
    MouseMove($aPos[0], $aPos[1], 0)
    Opt("MouseCoordMode", $iMode)
EndFunc
发表于 2015-11-2 22:42:00 | 显示全部楼层
谢谢楼主分享   学习学习
发表于 2015-11-3 02:15:19 | 显示全部楼层
回复 67# 298311657

感謝樓主 我又學到了東西
我想請教的就是
_LVN_GETDISPINFO($hlst, $ilParam, ByRef $aDataArray)


DllStructSetData($tInfo, "TextMax", StringLen($aDataArray[$iIndex][$iSub]));設置列數據字串長
這樣子的用法....

怎麼我的觀念認為這樣是不可以的??......原來是我的認知有問題.....

這個突破 可以讓我更縮短我的 寫法了 感列樓主!!
发表于 2015-11-4 10:54:23 | 显示全部楼层
回复 67# 298311657

樓主 你好  又來打擾了 真不好意思.....  能請教觀念嗎??

  Case $NM_CUSTOMDRAW;自绘消息  处理选中行背景色
   
為何 這個 寫成 Func 後 功能就失效了,雖然不會出現錯誤,但是 都無法上顏色呢??

原因是甚麼呢??
 楼主| 发表于 2015-11-6 00:15:25 | 显示全部楼层
回复 70# kk_lee69

只能这样做:
#cs ______________________
    Au3 版本: 3.3.14.2
    脚本作?? CrossDoor
    电子邮件: [email]382869232@qq.com[/email]
    QQ/TM: 382869232
#ce _______________脚本开始_________________
#PRE_UseX64=n
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <WinAPITheme.au3>
#include <GuiListView.au3>
#include <WinAPISys.au3>
#include <WinAPI.au3>
#include <GuiEdit.au3>
#include <array.au3>
#include <Misc.au3>

Global $B_DESCENDING[3] ; 排序用数组

Global $hActLst
Global $bCtrlDown = False;listview控件ctrl键按下标识
Global $hEdit, $Item = -1, $SubItem = 0
Global $hEnter, $aAccelKeys[1][2] = [["{ENTER}", $hEnter]];虚拟控件的句柄和绑定的快捷键

Local $hUser32 = DllOpen("user32.dll")
Local $ichked = 0;勾选的行数
Local $tText = DllStructCreate("wchar Text[256]");建个结构,用来放listview列数据
Local $GUI, $hImage
Local $iITEM_COUNT = 1000, $aShowdata[$iITEM_COUNT][4], $aShowdata2[$iITEM_COUNT][4], $aShowdata3[$iITEM_COUNT][4];注意数组最大项目数为2^24(16777216),所以$iITEM_COUNT = 4194304为二维数组$aShowdata最大行数
Local $sSomeString = ""
Local $hGUI, $hListView, $hListView2, $hListView3

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
$hGUI = GUICreate("ListView虚表 加载[" & UBound($aShowdata) & "]数据 复选框 原地编辑例子 By_Crossdoor", 600, 605)

$hListView = GUICtrlCreateListView("$hListView| | ", 2, 2, 295, 296, BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_OWNERDATA), $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER + $LVS_EX_CHECKBOXES)
;~ _WinAPI_SetWindowTheme(GUICtrlGetHandle($hListView), "Explorer");设置主题

;设置列宽
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 0, 110)
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 1, 80)
GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 2, 80)
GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0);设定数据总数



$hListView2 = GUICtrlCreateListView("$hListView2| | ", 300, 2, 295, 296, BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_OWNERDATA), $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER + $LVS_EX_CHECKBOXES)
;~ _WinAPI_SetWindowTheme(GUICtrlGetHandle($hListView), "Explorer");设置主题

;设置列宽
GUICtrlSendMsg($hListView2, $LVM_SETCOLUMNWIDTH, 0, 110)
GUICtrlSendMsg($hListView2, $LVM_SETCOLUMNWIDTH, 1, 80)
GUICtrlSendMsg($hListView2, $LVM_SETCOLUMNWIDTH, 2, 80)
GUICtrlSendMsg($hListView2, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0);设定数据总数


$hListView3 = GUICtrlCreateListView("$hListView3| | ", 300, 300, 295, 296, BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_OWNERDATA), $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT + $LVS_EX_DOUBLEBUFFER + $LVS_EX_CHECKBOXES)
;~ _WinAPI_SetWindowTheme(GUICtrlGetHandle($hListView), "Explorer");设置主题

;设置列宽
GUICtrlSendMsg($hListView3, $LVM_SETCOLUMNWIDTH, 0, 110)
GUICtrlSendMsg($hListView3, $LVM_SETCOLUMNWIDTH, 1, 80)
GUICtrlSendMsg($hListView3, $LVM_SETCOLUMNWIDTH, 2, 80)
GUICtrlSendMsg($hListView3, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0);设定数据总数

;===========创建并关联图像列表
$hImage = _GUIImageList_Create()
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 110)
_GUICtrlListView_SetImageList($hListView, $hImage, 1);分配图像列表到列表视图控件$hListView
_GUICtrlListView_SetImageList($hListView2, $hImage, 1);分配图像列表到列表视图控件$hListView2

$Button1 = GUICtrlCreateButton("选中行", 10, 310, 70, 25)
$Button2 = GUICtrlCreateButton("未选行", 80, 310, 70, 25)
$Button3 = GUICtrlCreateButton("修改", 150, 310, 70, 25)
$Button4 = GUICtrlCreateButton("清空", 220, 310, 70, 25)
GUISetState()

;==================在窗体显示后再初始化数据,因为初始化数组数据比较慢
;如果先初始化数组后显示窗口,会卡很久,就造成虚表也很慢的假象
For $i = 0 To $iITEM_COUNT - 1
    ;重绘 刷新 listview 0-13行(让ListView显示数组数据),不用太多行,只需要一屏的行数就就可以
    ;因为下拉滚动的时候listview会收到LVN_GETDISPINFO消息,这个消息我们在WM_NOTIFY内处理过了
    If $i = 18 Then
        GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, $i)
        GUICtrlSendMsg($hListView2, $LVM_REDRAWITEMS, 0, $i)
        GUICtrlSendMsg($hListView3, $LVM_REDRAWITEMS, 0, $i)
    EndIf
    
    $aShowdata[$i][0] = "爷爷" & $i
    $aShowdata[$i][1] = "爸爸" & $i
    $aShowdata[$i][2] = "儿子" & $i
    $aShowdata[$i][3] = 4096;复选框状态4096未选中 8192选中
    
    $aShowdata2[$i][0] = "2爷爷" & $i
    $aShowdata2[$i][1] = "2爸爸" & $i
    $aShowdata2[$i][2] = "2儿子" & $i
    $aShowdata2[$i][3] = 4096;复选框状态4096未选中 8192选中
    
    
    $aShowdata3[$i][0] = "3爷爷" & $i
    $aShowdata3[$i][1] = "3爸爸" & $i
    $aShowdata3[$i][2] = "3儿子" & $i
    $aShowdata3[$i][3] = 4096;复选框状态4096未选中 8192选中
Next

While 1
    $bCtrlDown = _IsPressed("11", $hUser32);取ctrl按键的状态
    Switch GUIGetMsg()
        Case -3
            ExitLoop
        Case $Button1
            $aShowdata[3][3] = 8192
            $aShowdata[7][3] = 8192
            GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 3, 7)
            
;~             $a = _GetChkIndex(8192)
;~             If $a[0] = -1 Then
;~                 MsgBox(32, "提示", "未勾选任何数据")
;~             Else
;~                 _ArrayDisplay($a, "勾选行的索引");数组很大时,_ArrayDisplay会非常耗时
;~             EndIf
        Case $Button2
            $a = _GetChkIndex(4096)
            If $a[0] = -1 Then
                 MsgBox(32, "提示", "数据全都被勾选了。")
            Else
                ;MsgBox(32, "提示", "未勾选的数据有" & UBound($a) & "行")
                _ArrayDisplay($a, "未勾选行的索");数组很大时,_ArrayDisplay会非常耗时
            EndIf
        Case $Button3
            If StringLen($sSomeString) Then
                $sSomeString = ""
            Else
                $sSomeString = Asc(Random(48, 255, 1))
            EndIf
            For $i = 0 To $iITEM_COUNT - 1
                $aShowdata[$i][0] = "爷爷" & $i & "-" & $sSomeString
                $aShowdata[$i][1] = "爸爸" & $i & "-" & $sSomeString
                $aShowdata[$i][2] = "儿子" & $i & "-" & $sSomeString
            Next
            GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
            GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
        Case $Button4
            $aShowdata = 0
            $iITEM_COUNT = 0
            GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, $iITEM_COUNT, 0)
            GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
            GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
    EndSwitch
WEnd
GUIDelete()
DllClose($hUser32)

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    
    Switch $iIDFrom
        Case $hListView
            Switch $iCode
                Case $LVN_COLUMNCLICK ; 点击列头排序
                    _SortItems($iIDFrom, $ilParam, $aShowdata)
                Case $NM_CUSTOMDRAW;自绘消息  处理选中行背景色
                    Local $tCustDraw = DllStructCreate("hwnd hwndFrom;int idFrom;int code;dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;dword clrText;dword clrTextBk;int SubItem; dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align", $ilParam)
                    Local $iDrawStage = DllStructGetData($tCustDraw, "DrawStage")
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
                    If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
                    _SetchkedBkClr($tCustDraw, $aShowdata)
                    Return $CDRF_NEWFONT
                Case $LVN_ITEMCHANGED ; An item has changed
                    _CtrlSel($iIDFrom, $ilParam, $aShowdata)
                Case $LVN_BEGINSCROLL ; 滚动事件开始
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata);如果存在$hEdit控件,则结束编辑                           
                Case $NM_CLICK;单击
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata)
                    _chkboxState($iIDFrom, $ilParam, $aShowdata);刷新复选框状态
                Case $NM_DBLCLK ; 双击
                    _StartItemEdit($iIDFrom, $ilParam, $aShowdata);开始原地编辑
                Case -150, -177 ;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177   请求显示数据
                    _LVN_GETDISPINFO($iIDFrom, $ilParam, $aShowdata)
            EndSwitch
        Case $hListView2
            Switch $iCode
                Case -150, -177 ;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177   请求显示数据
                    _LVN_GETDISPINFO($iIDFrom, $ilParam, $aShowdata2)
                Case $LVN_COLUMNCLICK ; 点击列头排序
                    _SortItems($iIDFrom, $ilParam, $aShowdata2)
                Case $NM_CUSTOMDRAW;自绘消息  处理选中行背景色
                    Local $tCustDraw = DllStructCreate("hwnd hwndFrom;int idFrom;int code;dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;dword clrText;dword clrTextBk;int SubItem; dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align", $ilParam)
                    Local $iDrawStage = DllStructGetData($tCustDraw, "DrawStage")
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
                    If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
                    _SetchkedBkClr($tCustDraw, $aShowdata2, 0x738393)
                    Return $CDRF_NEWFONT
                Case $LVN_ITEMCHANGED ; An item has changed
                    _CtrlSel($iIDFrom, $ilParam, $aShowdata2)
                Case $LVN_BEGINSCROLL ; 滚动事件开始
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata2);如果存在$hEdit控件,则结束编辑
                Case $NM_CLICK;单击
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata2)
                    _chkboxState($iIDFrom, $ilParam, $aShowdata2)
                Case $NM_DBLCLK ; 双击
                    _StartItemEdit($iIDFrom, $ilParam, $aShowdata2)
            EndSwitch
        Case $hListView3
            Switch $iCode
                Case -150, -177 ;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177   请求显示数据
                    _LVN_GETDISPINFO($iIDFrom, $ilParam, $aShowdata3)
                Case $LVN_COLUMNCLICK ; 点击列头排序
                    _SortItems($iIDFrom, $ilParam, $aShowdata3)
                Case $NM_CUSTOMDRAW;自绘消息  处理选中行背景色
                    Local $tCustDraw = DllStructCreate("hwnd hwndFrom;int idFrom;int code;dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;dword clrText;dword clrTextBk;int SubItem; dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align", $ilParam)
                    Local $iDrawStage = DllStructGetData($tCustDraw, "DrawStage")
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
                    If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
                    _SetchkedBkClr($tCustDraw, $aShowdata3, 0xD307AD, 0xE3F7ED)
                    Return $CDRF_NEWFONT
                Case $LVN_ITEMCHANGED ; An item has changed
                    _CtrlSel($iIDFrom, $ilParam, $aShowdata3)
                Case $LVN_BEGINSCROLL ; 滚动事件开始
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata3);如果存在$hEdit控件,则结束编辑
                Case $NM_CLICK;单击
                    If IsHWnd($hEdit) Then _EndItemEdit($iIDFrom, $aShowdata3)
                    _chkboxState($iIDFrom, $ilParam, $aShowdata3)
                Case $NM_DBLCLK ; 双击
                    _StartItemEdit($iIDFrom, $ilParam, $aShowdata3)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $iIDFrom = _WinAPI_LoWord($wParam)
    $iCode = _WinAPI_HiWord($wParam)
    Switch $lParam
        Case $hEdit
            Switch $iCode
                Case $EN_KILLFOCUS;编辑框失去焦点,结束编辑
                    Switch $hActLst
                        Case $hListView
                            _EndItemEdit($hListView, $aShowdata)
                        Case $hListView2
                            _EndItemEdit($hListView2, $aShowdata2)
                        Case $hListView3
                            _EndItemEdit($hListView3, $aShowdata3)
                    EndSwitch
                Case $EN_UPDATE

            EndSwitch
        Case $hEnter;虚拟控件消息触发  收到回车消息才触发
            If IsHWnd($hEdit) Then
                If $SubItem = 0 Then
                    __ClickListViewItem($hActLst, $Item, True);使用点击来结束编辑,省去判断listview的数据数组
                Else
                    __ClickListViewItem($hActLst, $Item)
                EndIf
            EndIf
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _SetchkedBkClr(ByRef $tCustDraw, ByRef $aDataArray, $ihighBkClr = 0xF7D3AD, $idefBkclr = 0xFFFFFF)
    Local $iIndex = DllStructGetData($tCustDraw, "ItemSpec")
    If $aDataArray[$iIndex][3] = 4096 Then
        DllStructSetData($tCustDraw, "clrTextBk", $idefBkclr);BGR格式颜色值 默认背景色
    Else
        DllStructSetData($tCustDraw, "clrTextBk", $ihighBkClr);BGR格式颜色值 高亮背景色
    EndIf
EndFunc

Func _chkboxState($hlst, $ilParam, ByRef $aDataArray);刷新复选框状态
    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
    $iIndex = DllStructGetData($tInfo, "Index")
    $x = DllStructGetData($tInfo, "X")
    If ($x < 16) And (3 < $x) And (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hlst), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then;使用点击的x坐标来判断是否在复选框上点击
        If $aDataArray[$iIndex][3] = 4096 Then
            $ichked+=1
            $aDataArray[$iIndex][3] = 8192;4096未选中 8192选中
        Else
            $ichked-=1
            $aDataArray[$iIndex][3] = 4096;4096未选中 8192选中
        EndIf
        ;====立刻刷新复选框显示状态 重绘$iIndex项
        GUICtrlSendMsg($hlst, $LVM_REDRAWITEMS, $iIndex, $iIndex)
    EndIf    
EndFunc

Func _SortItems($hlst, $ilParam, ByRef $aDataArray);排序
    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
    $iSub = DllStructGetData($tInfo, "SubItem")
    _ArraySort($aDataArray, $B_DESCENDING[$iSub], 0, 0, $iSub)
    GUICtrlSendMsg($hlst, $LVM_REDRAWITEMS, 0, 20)
    $B_DESCENDING[$iSub] = Not $B_DESCENDING[$iSub]
EndFunc

Func _CtrlSel($hlst, $ilParam, ByRef $aDataArray);按住ctrl键点选item
    If $bCtrlDown Then;ctrl键按下
        $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
        Local $iIndex = DllStructGetData($tInfo, "Item")
        Local $iNewState = DllStructGetData($tInfo, "NewState")
        If $iIndex > -1 And $iNewState = BitOR($LVIS_FOCUSED, $LVIS_SELECTED) Then
            If $aDataArray[$iIndex][3] = 4096 Then
                $ichked+=1
                $aDataArray[$iIndex][3] = 8192;4096未选中 8192选中
            Else
                $ichked-=1
                $aDataArray[$iIndex][3] = 4096;4096未选中 8192选中
            EndIf
            $tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
            DllStructSetData($tInfo, "State", $aDataArray[$iIndex][3]);设置复选框状态
            ;====立刻刷新复选框显示状态 重绘$iIndex项
            GUICtrlSendMsg($hlst, $LVM_REDRAWITEMS, $iIndex, $iIndex)
        EndIf
    EndIf
EndFunc

Func _LVN_GETDISPINFO($hlst, $ilParam, ByRef $aDataArray)
    If Not IsArray($aDataArray) Then Return
    $tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
    $iIndex = Int(DllStructGetData($tInfo, "Item"))
    $iSub = Int(DllStructGetData($tInfo, "SubItem"))

    If BitAND(DllStructGetData($tInfo, "Mask"), $LVIF_IMAGE) And $iSub = 0 Then DllStructSetData($tInfo, "Image", 0);判断是否有LVIF_IMAGE属性,有则设置列图像。不设置_GUICtrlListView_SetImageList则无

    If (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hlst), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then
        ;===============设置复选框信息
        DllStructSetData($tInfo, "Mask", BitOR($LVIF_STATE, DllStructGetData($tInfo, "Mask")))
        DllStructSetData($tInfo, "StateMask", $LVIS_STATEIMAGEMASK)
        DllStructSetData($tInfo, "State", $aDataArray[$iIndex][3])
    EndIf

    DllStructSetData($tText, "Text", $aDataArray[$iIndex][$iSub]);列数据放入$tText结构
    DllStructSetData($tInfo, "Text", DllStructGetPtr($tText));$tText结构的指针来设置列数据
    DllStructSetData($tInfo, "TextMax", StringLen($aDataArray[$iIndex][$iSub]));设置列数据字串长
EndFunc

Func _StartItemEdit($hlst, $ilParam, ByRef $aDataArray)
    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
    $iIndex = DllStructGetData($tInfo, "Index")
    $iSub = DllStructGetData($tInfo, "SubItem")
    $x = DllStructGetData($tInfo, "X")
    If ($iIndex <> -1) And ($iSub >= 0) And ($x > 16) Then;点击的x>16才响应原地编辑
        $hActLst = $hlst
        If _GUICtrlListView_EnsureVisible($hlst, $iIndex) Then GUICtrlSendMsg($hlst, $LVM_REDRAWITEMS, $iIndex, $iIndex + 1);确保列表视图项目可见
        Local $alstPos = ControlGetPos($hGUI, "", $hlst)
        $Item = $iIndex
        $SubItem = $iSub
        ;==========计算编辑框坐标
        Local $aRect = _GUICtrlListView_GetSubItemRect($hlst, $iIndex, $iSub)
        Local $iEdit_X = $aRect[0] + $alstPos[0] + 4
        Local $iEdit_Y = $aRect[1] + $alstPos[1] + 3
        Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($hlst, $iSub) - 1
        Local $iEdit_Height = $aRect[3] - $aRect[1]
        If $iSub = 0 Then
            Local $i1 = 0, $i2 = 0
            If (BitAND(_GUICtrlListView_GetExtendedListViewStyle($hlst), $LVS_EX_CHECKBOXES) = $LVS_EX_CHECKBOXES) Then $i1 = 17;判断是否有复选框
            If _GUICtrlListView_GetImageList($hlst, 1) Then $i2 = 19;判断是否有分配图像列表到列表视图控件
            $iEdit_X += ($i2 + $i1)
            $iEdit_Width -= ($i2 + $i1)
        EndIf
        Local $iEdit = GUICtrlCreateInput($aDataArray[$iIndex][$iSub], $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_LEFT))
        GUICtrlSetFont($iEdit, 11)
        GUICtrlSetState($iEdit, $GUI_FOCUS)
        $hEdit = GUICtrlGetHandle($iEdit)
        _WinAPI_BringWindowToTop($hEdit)
        _GUICtrlEdit_SetSel($hEdit, 0, -1) ;全选编辑框文字
        Local $iEnter = GUICtrlCreateDummy()
        $hEnter = GUICtrlGetHandle($iEnter)
        GUISetAccelerators($aAccelKeys, $hGUI);在虚拟控件上绑定一个回车快捷按键
    EndIf    
EndFunc

Func _EndItemEdit($hlst, ByRef $aDataArray)
    If ($Item < UBound($aDataArray, 1)) And ($SubItem < UBound($aDataArray, 2)) And ($hActLst == $hlst) Then
        Local $sText = _GUICtrlEdit_GetText($hEdit)
        _GUICtrlListView_SetItemText($hlst, $Item, $sText, $SubItem)
        If IsHWnd($hEdit) Then _WinAPI_DestroyWindow($hEdit)
        If IsHWnd($hEnter) Then _WinAPI_DestroyWindow($hEnter)
        $hEnter = Null
        $hEdit = Null
        If ($Item >= 0) Then $aDataArray[$Item][$SubItem] = $sText
        $Item = -1
        $SubItem = 0
    EndIf
EndFunc
 
Func _GetChkIndex($iChkState)
    Local $aIndex[1] = [-1], $j = 0
    If $ichked = 0 Then Return $aIndex
    If $iChkState = 8192 Then
        ReDim $aIndex[$ichked]
    Else
        ReDim $aIndex[UBound($aShowdata)-$ichked]
    EndIf
    For $i = 0 To UBound($aShowdata) -1
        If $aShowdata[$i][3] == $iChkState Then
            $aIndex[$j] = $i
            $j+=1
        EndIf
    Next
    Return $aIndex
EndFunc

Func __ClickListViewItem($hWnd, $iIndex, $baddX = False)
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)

    Local $tRECT = _GUICtrlListView_GetItemRectEx($hWnd, $iIndex, $LVIR_LABEL)
    Local $tPoint = _WinAPI_PointFromRect($tRECT, True)
    $tPoint = _WinAPI_ClientToScreen($hWnd, $tPoint)
    Local $iX, $iY
    _WinAPI_GetXYFromPoint($tPoint, $iX, $iY)
    If $baddX Then $iX += DllStructGetData($tRECT, "Right")
    Local $iMode = Opt("MouseCoordMode", 1)
    Local $aPos = MouseGetPos()
    MouseClick("left", $iX, $iY, 1, 0)
    MouseMove($aPos[0], $aPos[1], 0)
    Opt("MouseCoordMode", $iMode)
EndFunc
发表于 2015-11-10 14:15:40 | 显示全部楼层
谢谢分享,正需要者呢
发表于 2015-11-11 09:09:46 | 显示全部楼层
感谢分享源码,新手下载学习。
发表于 2015-11-14 06:26:42 | 显示全部楼层
看看~~~~~~~~~
发表于 2015-11-16 15:50:42 | 显示全部楼层
学习学习
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|小黑屋|手机版|AUTOIT CN ( 鲁ICP备15028933号-3 )谷歌 百度

GMT+8, 2019-1-21 08:24 , Processed in 0.122296 second(s), 13 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表