#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>
#include <ButtonConstants.au3>
Opt('GUIOnEventMode', 1)
#cs
autoit.com yamakawa
测试环境 win10 x64
autoit3 3.3.14.2
#ce
;版本判断
Local $verArray = StringSplit(@AutoItVersion, ".")
If $verArray[3] < 14 Then MsgBox(4096, "来自Autoit.com -Yamakawa的提示", "本段代码测试于 Autoit 3.3.14.2!" & @CRLF & @CRLF & @CRLF & "当前版本低于3.3.14.2 如果出现问题,请自行修改!")
;低于3.3.14.2则弹出提示。不兼容可能是版本问题
;常量定义区
Global Const $ODT_LISTVIEW = 102
Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4
Global Const $ODS_SELECTED = 0x0001
;全局变量定义
Global $hGUI, $lListView, $hlListView, $rListView, $hrListView,$idAddSingleSel, $idDelSingleSel
Global $btn_test
Global $dataArray[10000][2]
For $i = 0 To 10000 - 1
$dataArray[$i][0] = "Item " & $i + 1
$dataArray[$i][1] = "SubItem " & $i + 1
Next
$hGUI = GUICreate("Test GUI", 650, 300)
GUISetOnEvent(-3, '_Exit')
;===第一个列表
$lListView = GUICtrlCreateListView("", 10, 10, 280, 180, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED, $LVS_OWNERDATA)) ;两个自绘属性都加上!
$hlListView = GUICtrlGetHandle(-1)
_GUICtrlListView_InsertColumn($hlListView, 1, "Item", 120)
_GUICtrlListView_InsertColumn($hlListView, 2, "SubItem", 120)
_GUICtrlListView_SetExtendedListViewStyle($hlListView, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))
_GUICtrlListView_SetColumnWidth($hlListView, 0, 120)
_GUICtrlListView_SetColumnWidth($hlListView, 1, 120)
_GUICtrlListView_SetItemCount($lListView, UBound($dataArray))
;第二个列表
$rListView = GUICtrlCreateListView("", 310, 10, 280, 180)
$hrListView = GUICtrlGetHandle(-1)
_GUICtrlListView_SetExtendedListViewStyle($hrListView, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))
_GUICtrlListView_InsertColumn($hrListView, 0, "隐藏列", 0)
_GUICtrlListView_InsertColumn($hrListView, 1, "列1", 120)
_GUICtrlListView_InsertColumn($hrListView, 2, "列2", 120)
; Subclass ListView to receive keyboard/mouse messages
$pListViewFunc = DllCallbackGetPtr(DllCallbackRegister("ListViewFunc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr"))
_WinAPI_SetWindowSubclass($hlListView, $pListViewFunc, 0, 0) ; $iSubclassId = 0, $pData = 0
; Add/del single selection
$idAddSingleSel = GUICtrlCreateDummy()
GUICtrlSetOnEvent(-1, '_AddSingleSel')
$idDelSingleSel = GUICtrlCreateDummy()
GUICtrlSetOnEvent(-1, '_DelSingleSel')
GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()
While 1
Switch GUIGetMsg()
Case -3
Exit
EndSwitch
WEnd
Func ListViewFunc($hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData)
If $iMsg = $WM_LBUTTONDOWN Then
Switch $wParam
Case 0x0001
If _GUICtrlListView_GetSelectedCount($hlListView) Then
Local $aHit = _GUICtrlListView_HitTest(GUICtrlGetHandle($lListView), BitAND($lParam, 0xFFFF), BitShift($lParam, 16))
If Not (@error Or $aHit[0] = -1) Then
If _GUICtrlListView_GetItemSelected($hlListView, $aHit[0]) Then
GUICtrlSendToDummy($idDelSingleSel, $aHit[0])
Else
GUICtrlSendToDummy($idAddSingleSel, $aHit[0])
EndIf
EndIf
Return 0
EndIf
Case 0x0009
Return 0
EndSwitch
ElseIf $iMsg = $WM_KILLFOCUS Then
ConsoleWrite("WM_KILLFOCUS" & @CRLF)
Else
Local $result = DllCall("comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)
If Not @error Then
Return $result[0]
Else
Return
EndIf
EndIf
Local $result = DllCall("comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)
If Not @error Then
Return $result[0]
Else
Return
EndIf
#forceref $iSubclassId, $pData
EndFunc ;==>ListViewFunc
Func _AddSingleSel()
Local $iItem = GUICtrlRead($idAddSingleSel)
_GUICtrlListView_SetItemSelected($hlListView, $iItem, True)
_GUICtrlListView_SetItemFocused($hlListView, $iItem)
EndFunc ;==>_AddSingleSel
Func _DelSingleSel()
Local $iItem = GUICtrlRead($idDelSingleSel)
_GUICtrlListView_SetItemSelected($hlListView, $iItem, False)
_GUICtrlListView_SetItemFocused($hlListView, $iItem)
EndFunc ;==>_DelSingleSel
Func _Exit()
_WinAPI_RemoveWindowSubclass($hlListView, $pListViewFunc, 0)
GUIDelete()
Exit
EndFunc ;==>_Exit
Func _WinAPI_SetWindowSubclass($hWnd, $pSubclassProc, $idSubClass, $pData = 0)
Local $aRet = DllCall('comctl32.dll', 'bool', 'SetWindowSubclass', 'hwnd', $hWnd, 'ptr', $pSubclassProc, 'uint_ptr', $idSubClass, _
'dword_ptr', $pData)
If @error Then Return SetError(@error, @extended, 0)
; If Not $aRet[0] Then Return SetError(1000, 0, 0)
Return $aRet[0]
EndFunc ;==>_WinAPI_SetWindowSubclass
Func _WinAPI_RemoveWindowSubclass($hWnd, $pSubclassProc, $idSubClass)
Local $aRet = DllCall('comctl32.dll', 'bool', 'RemoveWindowSubclass', 'hwnd', $hWnd, 'ptr', $pSubclassProc, 'uint_ptr', $idSubClass)
If @error Then Return SetError(@error, @extended, False)
Return $aRet[0]
EndFunc ;==>_WinAPI_RemoveWindowSubclass
Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
Local $tagDRAWITEMSTRUCT, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected, $oldColor
$tagDRAWITEMSTRUCT = DllStructCreate( _
"uint cType;" & _
"uint cID;" & _
"uint itmID;" & _
"uint itmAction;" & _
"uint itmState;" & _
"hwnd hItm;" & _
"handle hDC;" & _
"long itmRect[4];" & _
"ulong_ptr itmData" _
, $lParam)
$cID = $tagDRAWITEMSTRUCT.cID
$itmID = $tagDRAWITEMSTRUCT.itmID
$hItm = $tagDRAWITEMSTRUCT.hItm
$hDC = $tagDRAWITEMSTRUCT.hDC
If $tagDRAWITEMSTRUCT.cType <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
If $tagDRAWITEMSTRUCT.itmAction <> $ODA_DRAWENTIRE Then Return $GUI_RUNDEFMSG
;>=========
;~ Local $tRect = DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect") ;====这个学习了。。
Local $tRect = DllStructCreate($tagRect, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect")) ;====这样也可以。好处是可以修改
Local $iBrushColor = BitAND($tagDRAWITEMSTRUCT.itmState, $ODS_SELECTED) = $ODS_SELECTED ? 0xff7bcc : 0xffffff ;上色
Local $aBrush = _WinAPI_CreateSolidBrush($iBrushColor)
Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush)
_WinAPI_FillRect($hDC, $tRect, $aBrush)
_WinAPI_SelectObject($hDC, $aBrushOld)
_WinAPI_DeleteObject($aBrush)
;<=====画背景
;>====设置选中项文字颜色
$txtcolor = BitAND($tagDRAWITEMSTRUCT.itmState, $ODS_SELECTED) = $ODS_SELECTED ? 0xffffff : 0x000000
_WinAPI_SetTextColor($hDC, $txtcolor)
;<=====
;回填数据
For $i = 0 To _GUICtrlListView_GetColumnCount($hItm) - 1
Local $iItmRect = DllStructCreate($tagRect)
If $i Then $iItmRect.top = $i
DllCall('user32.dll', 'int', 'SendMessage', 'hwnd', $hItm, 'uint', $LVM_GETSUBITEMRECT, 'wparam', $itmID, 'lparam', DllStructGetPtr($iItmRect))
$iItmRect.left += $i ? 5 : 10
_WinAPI_DrawText($hDC, $dataArray[$itmID][$i], $iItmRect, $DT_LEFT)
Next
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_DRAWITEM
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 $rListView
If $iCode <> $NM_DBLCLK Then Return $GUI_RUNDEFMSG
$tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
Local $index = DllStructGetData($tInfo, "Index")
If _GUICtrlListView_DeleteItem($iIDFrom, $index) Then
If _GUICtrlListView_GetItemCount($iIDFrom) > _GUICtrlListView_GetCounterPage($iIDFrom) Then
_GUICtrlListView_SetItemSelected($hrListView, $index - 1)
Else
_GUICtrlListView_SetItemSelected($hrListView, $index)
EndIf
EndIf
Return $GUI_RUNDEFMSG
Case $lListView
Switch $iCode
Case $NM_DBLCLK
$tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
Local $index = DllStructGetData($tInfo, "Index")
If $index = -1 Then Return $GUI_RUNDEFMSG
Local $newIndex = _GUICtrlListView_FindText($hrListView, String($lListView & "," & $index))
If $newIndex <> -1 Then
_GUICtrlListView_DeleteItem($hrListView, $newIndex)
Else
$newIndex = _GUICtrlListView_AddItem($hrListView, String($lListView & "," & $index))
For $i = 0 To UBound($dataArray, 2) - 1
_GUICtrlListView_AddSubItem($hrListView, $newIndex, $dataArray[$index][$i], $i + 1)
Next
_GUICtrlListView_EnsureVisible($hrListView, $newIndex)
_GUICtrlListView_SetItemSelected($hrListView, $newIndex)
EndIf
Return 0
EndSwitch
Return $GUI_RUNDEFMSG
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY