You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在AutoIt的ListView中检查项是否存在,避免重复添加拖拽文件?

AutoIT拖拽文件到ListView避免重复添加的解决方案

问题背景

现有AutoIT程序支持将Windows文件拖拽到由GUICtrlCreateListView()创建的列表中,但存在重复添加文件的问题。同时ControlListView()函数仅支持32位系统,在64位环境下无法正常工作,需要替代方案。

原始代码如下:

GuiCreate('Drag and Drop', 530, 320, @DesktopWidth / 2 - 192, @DesktopHeight / 2 - 235, -1, $WS_EX_ACCEPTFILES)

GUICtrlCreateLabel('File:', 20, 30)

Local $dropControl = GUICtrlCreateInput('', 80, 30, 400, 24, -1, $WS_EX_STATICEDGE)
Local $dropList = GUICtrlCreateListView('File', 80, 80, 400, 200)   ;, -1, $WS_EX_STATICEDGE)

GUICtrlSetState ($dropControl, $GUI_DROPACCEPTED)
GUICtrlSetTip ($dropControl, 'Drag File here …')

GUISetOnEvent($GUI_EVENT_DROPPED, 'doDrop')

Func doDrop()
    $dropFiles = GUICtrlRead(@GUI_DropId)
    Local $files = StringSplit($dropFiles, '|')
    For $i=1 to $files[0]
        $file = $files[$i]
        ;   How do I test wheter the item already exists?
        Local $item = GUICtrlCreateListViewItem($file, $dropList)
        GUICtrlSetData($item, $file)
    Next
    GUICtrlSetData($dropControl, '')
EndFunc

解决方案

方案1:遍历ListView现有项检查重复(无需额外缓存)

通过GUICtrlRead()结合循环遍历ListView的所有项,对比当前文件路径(忽略Windows路径大小写),判断是否已存在。

修改后的完整代码:

GuiCreate('Drag and Drop', 530, 320, @DesktopWidth / 2 - 192, @DesktopHeight / 2 - 235, -1, $WS_EX_ACCEPTFILES)

GUICtrlCreateLabel('File:', 20, 30)

Local $dropControl = GUICtrlCreateInput('', 80, 30, 400, 24, -1, $WS_EX_STATICEDGE)
Local $dropList = GUICtrlCreateListView('File', 80, 80, 400, 200)

GUICtrlSetState ($dropControl, $GUI_DROPACCEPTED)
GUICtrlSetTip ($dropControl, 'Drag File here …')

GUISetOnEvent($GUI_EVENT_DROPPED, 'doDrop')
GUISetOnEvent($GUI_EVENT_CLOSE, '_Exit')

Func doDrop()
    $dropFiles = GUICtrlRead(@GUI_DropId)
    Local $files = StringSplit($dropFiles, '|')
    For $i=1 to $files[0]
        $file = $files[$i]
        ; 检查文件是否已在列表中
        If Not _IsFileInListView($dropList, $file) Then
            Local $item = GUICtrlCreateListViewItem($file, $dropList)
            GUICtrlSetData($item, $file)
        EndIf
    Next
    GUICtrlSetData($dropControl, '')
EndFunc

; 自定义检查函数:判断文件是否已存在于ListView
Func _IsFileInListView($hListView, $sFilePath)
    Local $iIndex = 0
    While True
        Local $sItemText = GUICtrlRead($hListView, $GUI_INDEX, $iIndex)
        ; 遍历到空项说明已检查完所有项
        If $sItemText = "" Then ExitLoop
        ; 忽略大小写对比路径(Windows路径不区分大小写)
        If StringCompare($sItemText, $sFilePath, 1) = 0 Then
            Return True
        EndIf
        $iIndex += 1
    WEnd
    Return False
EndFunc

Func _Exit()
    Exit
EndFunc

GUISetState(@SW_SHOW)
While 1
    Sleep(100)
WEnd

方案2:维护数组缓存已添加文件(效率更高)

当ListView项较多时,遍历会影响性能,可维护一个全局数组记录已添加的文件路径,每次添加前先检查数组:

修改后的核心代码:

; 全局数组,用于缓存已添加的文件,[0]为元素数量
Global $aAddedFiles[1] = [0]

Func doDrop()
    $dropFiles = GUICtrlRead(@GUI_DropId)
    Local $files = StringSplit($dropFiles, '|')
    For $i=1 to $files[0]
        $file = $files[$i]
        ; 检查数组中是否已存在该文件
        Local $bExists = False
        For $j=1 to $aAddedFiles[0]
            If StringCompare($aAddedFiles[$j], $file, 1) = 0 Then
                $bExists = True
                Break
            EndIf
        Next
        If Not $bExists Then
            ; 添加到ListView
            Local $item = GUICtrlCreateListViewItem($file, $dropList)
            GUICtrlSetData($item, $file)
            ; 更新缓存数组
            $aAddedFiles[0] += 1
            ReDim $aAddedFiles[$aAddedFiles[0]+1]
            $aAddedFiles[$aAddedFiles[0]] = $file
        EndIf
    Next
    GUICtrlSetData($dropControl, '')
EndFunc

说明

  • 两种方案均无需依赖ControlListView(),完全兼容64位系统
  • 使用StringCompare(..., 1)忽略大小写,符合Windows文件系统的路径规则
  • 方案2适合列表项较多的场景,避免重复遍历ListView带来的性能损耗

内容的提问来源于stack exchange,提问作者Manngo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:17:22