chzj589
发表于 2015-10-25 15:28:29
回复 44# 298311657
如果不需要复选框,代码如何修改?
chzj589
发表于 2015-10-25 16:06:50
回复 44# 298311657
我修改后,双击子项目框,把原来的数据删除了
#cs ______________________
Au3 版本: 3.3.14.2
脚本作?? CrossDoor
电子邮件: 382869232@qq.com
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>
Opt("GUIOnEventMode", 1)
Global $B_DESCENDING ; 排序用数组
Global $bCtrlDown = False;listview控件ctrl键按下标识
Global $hEdit, $Item = -1, $SubItem = 0
Local $hUser32 = DllOpen("user32.dll")
Local $ichked = 0;勾选的行数
Local $tText = DllStructCreate("wchar Text");建个结构,用来放listview列数据
Local $GUI, $hImage, $hListView
Local $iITEM_COUNT = 20, $aShowdata[$iITEM_COUNT];注意数组最大项目数为2^24(16777216),所以$iITEM_COUNT = 4194304为二维数组$aShowdata最大行数
Local $sSomeString = ""
GUI()
While 1
Sleep(100)
WEnd
Func GUI()
;GUIRegisterMsg($WM_KEYDOWN, "WM_KEYDOWN")
;GUIRegisterMsg($WM_KEYUP, "WM_KEYUP")
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
$hGUI = GUICreate("ListView虚表 加载[" & $iITEM_COUNT & "]数据 复选框 原地编辑例子 By_Crossdoor", 600, 350)
GUISetOnEvent($GUI_EVENT_CLOSE, "GForm1Close")
;$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)
$hListView = GUICtrlCreateListView("", 2, 2, 594, 296, $LVS_REPORT, $WS_EX_CLIENTEDGE)
GUICtrlSetBkColor($hListview, 0xC0C0C1); 背景色
GUICtrlSetFont($hListview, 10, 400, 0, "微软雅黑")
;GUICtrlSetColor($hEdit, 0xFFFF00)
;设置列宽
_GUICtrlListView_SetColumn($hListView, 0, "Item1", 70, 2);设置列属性
_GUICtrlListView_SetColumn($hListView, 1, "nSubItem1", 100, 2)
_GUICtrlListView_SetColumn($hListView, 2, "nSubItem2", 100, 2)
_GUICtrlListView_SetColumn($hListView, 3, "nSubItem3", 100, 2)
_GUICtrlListView_SetColumn($hListView, 4, "nSubItem4", 100, 2)
;GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 0, 150)
;GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 1, 150)
;GUICtrlSendMsg($hListView, $LVM_SETCOLUMNWIDTH, 2, 150)
;GUICtrlSendMsg($hListView, $LVM_SETITEMCOUNT, 10, 0);设定数据总数
; 设置颜色
_GUICtrlListView_SetBkColor($hListview, $CLR_MONEYGREEN)
$hImage = _GUIImageList_Create(1, 18);30为每行的间距(即网格高度)
_GUICtrlListView_SetImageList($hListview, $hImage, 1)
_GUICtrlListView_SetExtendedListViewStyle($hListview, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_INFOTIP))
;Local $num = _GUICtrlListView_GetItemCount($hListview)
;_GUICtrlListView_Scroll($hListview, 0, $num * 18);估计默认行高为18
;_GUICtrlListView_SetItemSelected($hListview, $num - 1);索引从0开始,所以减1
;$hImage = _GUIImageList_Create(1, $iHeight)
;_GUICtrlListView_SetImageList($hListview, $hImage, 1)
;设置列宽
;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 5
_GUICtrlListView_InsertColumn($hListView, $i, '项目 ' & $i, 90)
Next
For $i = 0 To 9
_GUICtrlListView_AddItem($hListView, "" & $i, $i)
_GUICtrlListView_AddSubItem($hListView, $i, 'SubItem ' & 0, 1)
_GUICtrlListView_AddSubItem($hListView, $i, 'SubItem ' & 1, 2)
_GUICtrlListView_AddSubItem($hListView, $i, 'SubItem ' & 2, 3)
_GUICtrlListView_AddSubItem($hListView, $i, 'SubItem ' & 3, 4)
_GUICtrlListView_AddSubItem($hListView, $i, 'SubItem ' & 4, 5)
Next
;==================在窗体显示后再初始化数据,因为初始化数组数据比较慢
;如果先初始化数组后显示窗口,会卡很久,就造成虚表也很慢的假象
#cs
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] = "爷爷" & $i
$aShowdata[$i] = "爸爸" & $i
$aShowdata[$i] = "儿子" & $i
;$aShowdata[$i] = 4096;复选框状??4096未选中 8192选中
Next
#ce
EndFunc ;==>GUI
#cs
While 1
$bCtrlDown = _IsPressed("11", $hUser32);取ctrl按键的状态
Switch GUIGetMsg()
Case -3
ExitLoop
Case $Button1
$a = _GetChkIndex(8192)
If $a = -1 Then
MsgBox(32, "提示", "未勾选任何数据")
Else
_ArrayDisplay($a, "勾选行的索引");数组很大时,_ArrayDisplay会非常耗时
EndIf
Case $Button2
$a = _GetChkIndex(4096)
If $a = -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] = "爷爷" & $i & "-" & $sSomeString
$aShowdata[$i] = "爸爸" & $i & "-" & $sSomeString
$aShowdata[$i] = "儿子" & $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)
#ce
Func GForm1Close()
Exit
EndFunc ;==>GForm1Close
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
#forceref $hWnd, $iMsg, $iwParam
Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo, $s
$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
#cs
Case $LVN_COLUMNCLICK ; 点击列头排序
$tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
$iSub = DllStructGetData($tInfo, "SubItem")
_ArraySort($aShowdata, $B_DESCENDING[$iSub], 2, 0, $iSub)
GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
$B_DESCENDING[$iSub] = Not $B_DESCENDING[$iSub]
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] = 4096 Then
$ichked += 1
$aShowdata[$iIndex] = 8192;4096未选中 8192选中
Else
$ichked -= 1
$aShowdata[$iIndex] = 4096;4096未选中 8192选中
EndIf
$tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
DllStructSetData($tInfo, "State", $aShowdata[$iIndex]);设置复选框状态
;====立刻刷新复选框显示状态 重绘$iIndex-1??iIndex+20的项
GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, $iIndex - 1, $iIndex + 20)
EndIf
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])
EndIf
;DllStructSetData($tText, "Text", $aShowdata[$iIndex][$iSub]);列数据放入$tText结构
DllStructSetData($tInfo, "Text", DllStructGetPtr($tText));$tText结构的指针来设置列数据
;DllStructSetData($tInfo, "TextMax", StringLen($aShowdata[$iIndex][$iSub]));设置列数据字串长
Case $NM_CLICK;单击
$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] = 4096 Then
$ichked += 1
$aShowdata[$iIndex] = 8192;4096未选中 8192选中
Else
$ichked -= 1
$aShowdata[$iIndex] = 4096;4096未选中 8192选中
EndIf
$tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
DllStructSetData($tInfo, "State", $aShowdata[$iIndex]);设置复选框状态
;====立刻刷新复选框显示状态 重绘$iIndex-1??iIndex+20的项
GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, $iIndex - 1, $iIndex + 20)
EndIf
Case $NM_CUSTOMDRAW;自绘消息处理选中行背景色
Local $tCustDraw = DllStructCreate('hwnd hwndFrom;int idFrom;int code;dword DrawStage;hwnd hdc;long rect;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;int Align', $ilParam)
Local $iDrawStage, $iIndex
$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] = 4096 Then
DllStructSetData($tCustDraw, 'clrTextBk', 0xFFFFFF);BGR格式颜色值
Else
DllStructSetData($tCustDraw, 'clrTextBk', 0xF7D3AD);BGR格式颜色值
EndIf
Return $CDRF_NEWFONT
#ce
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才响应原地编辑
$Item = $iIndex
$SubItem = $iSub
;==========计算编辑框坐??
Local $aRect = _GUICtrlListView_GetSubItemRect($hListView, $iIndex, $iSub)
Local $iEdit_X = $aRect + 4
Local $iEdit_Y = $aRect + 3
Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($hListView, $iSub) + 3
Local $iEdit_Height = $aRect - $aRect + 3
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
$hEdit = GUICtrlCreateInput($aShowdata[$iIndex][$iSub], $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_LEFT))
;GUICtrlSetFont($hEdit, 12)
GUICtrlSetFont($hEdit, 10, 400, 0, "微软雅黑")
GUICtrlSetColor($hEdit, 0xFFFF00)
GUICtrlSetBkColor($hEdit, 0x009900);0x009900); 背景色
GUICtrlSetState($hEdit, $GUI_FOCUS)
$hEdit = GUICtrlGetHandle($hEdit)
;Send("{RIGHT}") ;方向右键
;~ _GUICtrlEdit_SetSel($hEdit, 0, -1) ;全选编辑框文字
;HotKeySet("{ENTER}", "_EndItemEdit");设置热键响应回车
EndIf
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, $iwParam, $ilParam)
Local $iCode = BitShift($iwParam, 16)
Local $nMsgID = BitAND($iwParam, 0x0000FFFF)
$iIDFrom = _WinAPI_LoWord($iwParam)
$iCode = _WinAPI_HiWord($iwParam)
Switch $ilParam
Case $hEdit
Switch $iCode
Case $EN_KILLFOCUS
_EndItemEdit()
Case $EN_UPDATE
EndSwitch
EndSwitch
If $nMsgID = 1 And $hEdit <> '' Then
_EndItemEdit()
EndIf
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)
_WinAPI_DestroyWindow($hEdit)
;If ($Item >= 0) Then
;$aShowdata[$Item][$SubItem] = $sText
;GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
;GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
;EndIf
;$Item = -1
;$SubItem = 0
;HotKeySet("{ENTER}");取消回车热键
;EndIf
EndFunc ;==>_EndItemEdit
Func _GetChkIndex($iChkState)
Local $aIndex = [-1], $j = 0
If $ichked = 0 Then Return $aIndex
If $iChkState = 8192 Then
ReDim $aIndex[$ichked]
Else
ReDim $aIndex
EndIf
For $i = 0 To UBound($aShowdata) - 1
If $aShowdata[$i] == $iChkState Then
$aIndex[$j] = $i
$j += 1
EndIf
Next
Return $aIndex
EndFunc ;==>_GetChkIndex
kk_lee69
发表于 2015-10-25 20:55:54
回复 41# 298311657
樓主: 不好意思 又來麻煩妳了.......
當 LISTVIEW 拉動卷軸的時候 $hEdit 並不會跟著移動.....
就會造成一個很怪異的情況如附件圖有辦法解決嗎??
kk_lee69
发表于 2015-10-25 20:59:57
回复 46# chzj589
chzj589 兄
1.拿掉創建 LISTVIEW 時候的 $LVS_EX_CHECKBOXES 的風格
2.拿掉 左點擊 裡面的那段判斷 就可以啦
298311657
发表于 2015-10-25 22:26:02
本帖最后由 298311657 于 2015-10-25 22:46 编辑
回复 48# kk_lee69
这个问题,你可以在滚动事件开始时关闭输入来解决
参考如下代码段
Case $LVN_BEGINSCROLL ; 滚动事件开始
If IsHWnd($hEdit) Then _EndItemEdit();如果存在$hEdit控件,则结束编辑
Func _EndItemEdit()
If ($Item < UBound($aShowdata, 1)) And ($SubItem < UBound($aShowdata, 2)) Then
Local $sText = _GUICtrlEdit_GetText($hEdit)
_GUICtrlListView_SetItemText($hListView, $Item, $sText, $SubItem)
_WinAPI_DestroyWindow($hEdit)
$hEdit = Null
If ($Item >= 0) Then
$aShowdata[$Item][$SubItem] = $sText
GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
EndIf
$Item = -1
$SubItem = 0
HotKeySet("{ENTER}");取消回车热键
EndIf
EndFunc ;==>_EndItemEdit
298311657
发表于 2015-10-25 22:34:47
本帖最后由 298311657 于 2015-10-25 22:41 编辑
回复 47# chzj589
你修改的代码并没有使用虚表,而且你的数据全部是直接写在listview控件上,并没有使用数组来存放数据,所以你不能从数组中获取数据填充到输入框进行编辑。你应该直接从控件上取listview项目或子项文本
参考一下这段代码:
Local $sItem = _GUICtrlListView_GetItemText($hListView, $iIndex, $iSub);取listview$iIndex行 $iSub列的文本
$hEdit = GUICtrlCreateInput($sItem, $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_LEFT))
chzj589
发表于 2015-10-26 07:01:40
回复 51# 298311657
谢谢!这样就可以了。
chzj589
发表于 2015-10-26 09:00:11
回复 49# kk_lee69
谢谢!感谢关注!!!!
kk_lee69
发表于 2015-10-30 23:52:55
回复 1# 298311657
樓主 有個問題要跟您請教一下,目前我實際應用上遇到了一個困難 不知道該如何解決
大陸的輸入法 不常以 ENTER 為輸入的按鍵嗎??
因為在範例中 註冊了以 ENTER 當作熱鍵
實際應用上 打數字 英文都沒問題,但是 當切換輸入法的時候時,我的輸入法打完後需要按ENTER 輸入 我剛剛打的字,但是此時卻觸發了熱鍵 所以 $hEdit 就被刪除了,此時 輸入法還沒將剛剛打的字 輸入到編輯框 ,因此無法輸入.......
這種情況 我該如何解決呢?? 取消 ENTER 熱鍵又好像 變的不是那麼方便~~~
kk_lee69
发表于 2015-10-31 00:52:25
回复 53# chzj589
chzj589 兄
有沒有遇過 原地編輯 LISTVIEW
按 ENTER 保存
卻遇到與輸入法的ENTER 健衝突
處理方式是怎樣的呢??
chzj589
发表于 2015-10-31 10:47:33
回复 55# kk_lee69
没碰到过,我用的输入法是<陈桥五笔>
298311657
发表于 2015-10-31 16:14:29
本帖最后由 298311657 于 2015-10-31 16:20 编辑
回复 54# kk_lee69
我使用的是手心输入法,是按空格输入。你说的问题可以这样解决
先定义变量:
Global $hEnter, $aAccelKeys = [["{ENTER}", $hEnter]];虚拟控件的句柄和绑定的快捷键
然后这样处理listview双击原地编辑:
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才响应原地编辑
$Item = $iIndex
$SubItem = $iSub
;==========计算编辑框坐??
Local $aRect = _GUICtrlListView_GetSubItemRect($hListView, $iIndex, $iSub)
Local $iEdit_X = $aRect + 4
Local $iEdit_Y = $aRect + 3
Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($hListView, $iSub) + 3
Local $iEdit_Height = $aRect - $aRect + 3
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
Local $iEdit = GUICtrlCreateInput($aShowdata[$iIndex][$iSub], $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_LEFT))
GUICtrlSetFont($iEdit, 12)
GUICtrlSetState($iEdit, $GUI_FOCUS)
$hEdit = GUICtrlGetHandle($iEdit)
Send("{RIGHT}") ;方向右键
;~ _GUICtrlEdit_SetSel($hEdit, 0, -1) ;全选编辑框文字
;~ HotKeySet("{ENTER}", "_EndItemEdit");设置热键响应回车
Local $iEnter = GUICtrlCreateDummy()
$hEnter = GUICtrlGetHandle($iEnter)
GUISetAccelerators($aAccelKeys, $hWnd);在虚拟控件上绑定一个回车快捷按键
EndIf
接着在WM_COMMAND响应虚拟控件消息:
Case $hEnter;虚拟控件消息触发收到回车消息才触发
If IsHWnd($hEdit) Then
_EndItemEdit()
EndIf
下面是完整的代码:
#cs ______________________
Au3 版本: 3.3.14.2
脚本作?? CrossDoor
电子邮件: 382869232@qq.com
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 ; 排序用数组
Global $bCtrlDown = False;listview控件ctrl键按下标识
Global $hEdit, $Item = -1, $SubItem = 0
Global $hEnter, $aAccelKeys = [["{ENTER}", $hEnter]];虚拟控件的句柄和绑定的快捷键
Local $hUser32 = DllOpen("user32.dll")
Local $ichked = 0;勾选的行数
Local $tText = DllStructCreate("wchar Text");建个结构,用来放listview列数据
Local $GUI, $hImage
Local $iITEM_COUNT = 94304, $aShowdata[$iITEM_COUNT];注意数组最大项目数为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] = "爷爷" & $i
$aShowdata[$i] = "爸爸" & $i
$aShowdata[$i] = "儿子" & $i
$aShowdata[$i] = 4096;复选框状态4096未选中 8192选中
Next
While 1
$bCtrlDown = _IsPressed("11", $hUser32);取ctrl按键的状态
Switch GUIGetMsg()
Case -3
ExitLoop
Case $Button1
$aShowdata = 8192
$aShowdata = 8192
GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 3, 7)
;~ $a = _GetChkIndex(8192)
;~ If $a = -1 Then
;~ MsgBox(32, "提示", "未勾选任何数据")
;~ Else
;~ _ArrayDisplay($a, "勾选行的索引");数组很大时,_ArrayDisplay会非常耗时
;~ EndIf
Case $Button2
$a = _GetChkIndex(4096)
If $a = -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] = "爷爷" & $i & "-" & $sSomeString
$aShowdata[$i] = "爸爸" & $i & "-" & $sSomeString
$aShowdata[$i] = "儿子" & $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;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;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] = 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] = 4096 Then
$ichked+=1
$aShowdata[$iIndex] = 8192;4096未选中 8192选中
Else
$ichked-=1
$aShowdata[$iIndex] = 4096;4096未选中 8192选中
EndIf
$tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
DllStructSetData($tInfo, "State", $aShowdata[$iIndex]);设置复选框状态
;====立刻刷新复选框显示状态 重绘$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;单击
$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] = 4096 Then
$ichked+=1
$aShowdata[$iIndex] = 8192;4096未选中 8192选中
Else
$ichked-=1
$aShowdata[$iIndex] = 4096;4096未选中 8192选中
EndIf
$tInfo = DllStructCreate($tagNMLVDISPINFO, $ilParam)
DllStructSetData($tInfo, "State", $aShowdata[$iIndex]);设置复选框状态
;====立刻刷新复选框显示状态 重绘$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才响应原地编辑
$Item = $iIndex
$SubItem = $iSub
;==========计算编辑框坐标
Local $aRect = _GUICtrlListView_GetSubItemRect($hListView, $iIndex, $iSub)
Local $iEdit_X = $aRect + 4
Local $iEdit_Y = $aRect + 3
Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($hListView, $iSub) + 3
Local $iEdit_Height = $aRect - $aRect + 3
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
Local $iEdit = GUICtrlCreateInput($aShowdata[$iIndex][$iSub], $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_LEFT))
GUICtrlSetFont($iEdit, 12)
GUICtrlSetState($iEdit, $GUI_FOCUS)
$hEdit = GUICtrlGetHandle($iEdit)
Send("{RIGHT}") ;方向右键
_GUICtrlEdit_SetSel($hEdit, 0, -1) ;全选编辑框文字
Local $iEnter = GUICtrlCreateDummy()
$hEnter = GUICtrlGetHandle($iEnter)
GUISetAccelerators($aAccelKeys, $hWnd);在虚拟控件上绑定一个回车快捷按键
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])
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
_EndItemEdit()
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)
_WinAPI_DestroyWindow($hEdit)
$hEdit = Null
If ($Item >= 0) Then
$aShowdata[$Item][$SubItem] = $sText
GUICtrlSendMsg($hListView, $LVM_ENSUREVISIBLE, 1, 0)
GUICtrlSendMsg($hListView, $LVM_REDRAWITEMS, 0, 20)
EndIf
$Item = -1
$SubItem = 0
EndIf
EndFunc ;==>_EndItemEdit
Func _GetChkIndex($iChkState)
Local $aIndex = [-1], $j = 0
If $ichked = 0 Then Return $aIndex
If $iChkState = 8192 Then
ReDim $aIndex[$ichked]
Else
ReDim $aIndex
EndIf
For $i = 0 To UBound($aShowdata) -1
If $aShowdata[$i] == $iChkState Then
$aIndex[$j] = $i
$j+=1
EndIf
Next
Return $aIndex
EndFunc
kk_lee69
发表于 2015-10-31 20:39:28
本帖最后由 kk_lee69 于 2015-10-31 22:44 编辑
回复 57# 298311657
OK 感謝樓主!!
這樣又學到了一招 太感謝了!!
還有個 問題 想問問樓主的看法 看看是否有辦法解決
這個應該屬於 繁體系統的問題,繁體系統下 有個輸入法叫做 新注音輸入法
相對於這個的是 傳統的注音輸入法
傳統的注音輸入法 是 一個字一個字打的 每打一個字就會 輸入到編輯框中,但是新注音不是
他會在編輯框的位置,先讓你打字打完全部的字以後,需要按下ENTER 才能將文字輸入
ENTER 的問題 根據上面的方法 可以解決,不過這個輸入法 造成了另外一個問題 殘影的問題
使用傳統的輸入法 一個字一個字輸入 不會有問題,就是這個輸入法會造成 下面的問題
但是這個輸入法在台灣幾乎是 必用的輸入法,所以還是得想辦法解決,只能來求助樓主了
因為 按下滑鼠左鍵後 就會正常,而且 如果我是一個字一個字輸入,前一個字以前的顯示都會是正常的,就是當下打個那個字不正常
我懷疑是 編輯框重繪的問題,因為輸入完畢後 按一下滑鼠的左鍵 顯示就會正常.....
有辦法 在按下ENTER 的時間點 重繪 編輯框嗎??
可以確認的是 按下ENTER 會觸發 WM_COMMAND 的$hEdit 的 $EN_CHANGE我想在這裡 設下 重繪編輯框的語法
chzj589
发表于 2015-10-31 22:13:14
回复 58# kk_lee69
你把
Local $iITEM_COUNT = 94304, $aShowdata[$iITEM_COUNT]
改为
Local $iITEM_COUNT = 15, $aShowdata[$iITEM_COUNT]的话,
列表框都不能显示数字,鼠标划过后才能显示,跟你现在的情况是否一样?
kk_lee69
发表于 2015-10-31 22:28:35
回复 59# chzj589
這個範例是我改過的 上面只秀三筆資料
這個有用傳統的輸入法測試 不會有此現象....
是新注音輸入法的問題,但是 這又是一個常用的輸入法
而且 新注音輸入法新舊版都有這個問題....
不得不解決此問題
页:
1
2
3
[4]
5
6
7
8
9
10
11
12
13