找回密码
 加入
搜索
查看: 5584|回复: 8

[AU3基础] [已解决]发现一个BUG,Listview不能排序!

  [复制链接]
发表于 2015-8-8 20:26:06 | 显示全部楼层 |阅读模式
本帖最后由 ioripalm 于 2015-8-31 09:06 编辑

就用GUICtrlRegisterListViewSort帮助文件参考里面给的示例来说。
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>

Global $nCurCol = -1
Global $nSortDir = 1
Global $bSet = 0
Global $nCol = -1

Example1()

; *******************************************************
; Example 1 - sorting 3 column's different
; *******************************************************
Func Example1()
    Local $lv, $msg

    GUICreate("Test", 300, 200)

    $lv = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180)
    GUICtrlRegisterListViewSort(-1, "LVSort") ; Register the function "SortLV" for the sorting callback

    GUICtrlCreateListViewItem("ABC|666|10.05.2004", $lv)
    GUICtrlSetImage(-1, "shell32.dll", 7)
    GUICtrlCreateListViewItem("DEF|444|11.05.2005", $lv)
    GUICtrlSetImage(-1, "shell32.dll", 12)
    GUICtrlCreateListViewItem("CDE|444|12.05.2004", $lv)
    GUICtrlSetImage(-1, "shell32.dll", 3)

    GUISetState()

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $lv
                $bSet = 0
                $nCurCol = $nCol
                GUICtrlSendMsg($lv, $LVM_SETSELECTEDCOLUMN, GUICtrlGetState($lv), 0)
                DllCall("user32.dll", "int", "InvalidateRect", "hwnd", GUICtrlGetHandle($lv), "int", 0, "int", 1)
        EndSwitch
    WEnd

    GUIDelete()
EndFunc   ;==>Example1

; Our sorting callback funtion
Func LVSort($hWnd, $nItem1, $nItem2, $nColumn)
    Local $val1, $val2, $nResult

    ; Switch the sorting direction
    If $nColumn = $nCurCol Then
        If Not $bSet Then
            $nSortDir = $nSortDir * - 1
            $bSet = 1
        EndIf
    Else
        $nSortDir = 1
    EndIf
    $nCol = $nColumn

    $val1 = GetSubItemText($hWnd, $nItem1, $nColumn)
    $val2 = GetSubItemText($hWnd, $nItem2, $nColumn)

    ; If it is the 3rd colum (column starts with 0) then compare the dates
    If $nColumn = 2 Then
        $val1 = StringRight($val1, 4) & StringMid($val1, 4, 2) & StringLeft($val1, 2)
        $val2 = StringRight($val2, 4) & StringMid($val2, 4, 2) & StringLeft($val2, 2)
    EndIf

    $nResult = 0 ; No change of item1 and item2 positions

    If $val1 < $val2 Then
        $nResult = -1 ; Put item2 before item1
    ElseIf $val1 > $val2 Then
        $nResult = 1 ; Put item2 behind item1
    EndIf

    $nResult = $nResult * $nSortDir

    Return $nResult
EndFunc   ;==>LVSort


; Retrieve the text of a listview item in a specified column
Func GetSubItemText($nCtrlID, $nItemID, $nColumn)
    Local $stLvfi = DllStructCreate("uint;ptr;int;int[2];int")
    Local $nIndex, $stBuffer, $stLvi, $sItemText

    DllStructSetData($stLvfi, 1, $LVFI_PARAM)
    DllStructSetData($stLvfi, 3, $nItemID)

    $stBuffer = DllStructCreate("char[260]")

    $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_FINDITEM, -1, DllStructGetPtr($stLvfi));

    $stLvi = DllStructCreate("uint;int;int;uint;uint;ptr;int;int;int;int")

    DllStructSetData($stLvi, 1, $LVIF_TEXT)
    DllStructSetData($stLvi, 2, $nIndex)
    DllStructSetData($stLvi, 3, $nColumn)
    DllStructSetData($stLvi, 6, DllStructGetPtr($stBuffer))
    DllStructSetData($stLvi, 7, 260)

    GUICtrlSendMsg($nCtrlID, $LVM_GETITEMA, 0, DllStructGetPtr($stLvi));

    $sItemText = DllStructGetData($stBuffer, 1)

    $stLvi = 0
    $stLvfi = 0
    $stBuffer = 0

    Return $sItemText
EndFunc   ;==>GetSubItemText
以上代码可以运行成功,也可以排序成功,Listview里的3行数据是通过GUICtrlCreateListViewItem函数添加的,如果将这3行数据换一种方式添加进去,排序函数就不工作了!
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#Include <GuiListView.au3>

Global $nCurCol = -1
Global $nSortDir = 1
Global $bSet = 0
Global $nCol = -1

Example1()


; *******************************************************
; Example 1 - sorting 3 column's different
; *******************************************************
Func Example1()
    Local $lv, $msg

    GUICreate("Test", 300, 200)

    $lv = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180)
    GUICtrlRegisterListViewSort(-1, "LVSort") ; Register the function "SortLV" for the sorting callback

        Dim $ListViewArray[3][3] = [['ABC',666,'10.05.2004'],['DEF',444,'11.05.2005'],['CDE',444,'12.05.2004']]
        _GUICtrlListView_AddArray($Lv, $ListViewArray)
        
    GUISetState()

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $lv
                $bSet = 0
                $nCurCol = $nCol
                GUICtrlSendMsg($lv, $LVM_SETSELECTEDCOLUMN, GUICtrlGetState($lv), 0)
                DllCall("user32.dll", "int", "InvalidateRect", "hwnd", GUICtrlGetHandle($lv), "int", 0, "int", 1)
        EndSwitch
    WEnd

    GUIDelete()
EndFunc   ;==>Example1

; Our sorting callback funtion
Func LVSort($hWnd, $nItem1, $nItem2, $nColumn)
    Local $val1, $val2, $nResult

    ; Switch the sorting direction
    If $nColumn = $nCurCol Then
        If Not $bSet Then
            $nSortDir = $nSortDir * - 1
            $bSet = 1
        EndIf
    Else
        $nSortDir = 1
    EndIf
    $nCol = $nColumn

    $val1 = GetSubItemText($hWnd, $nItem1, $nColumn)
    $val2 = GetSubItemText($hWnd, $nItem2, $nColumn)

    ; If it is the 3rd colum (column starts with 0) then compare the dates
    If $nColumn = 2 Then
        $val1 = StringRight($val1, 4) & StringMid($val1, 4, 2) & StringLeft($val1, 2)
        $val2 = StringRight($val2, 4) & StringMid($val2, 4, 2) & StringLeft($val2, 2)
    EndIf

    $nResult = 0 ; No change of item1 and item2 positions

    If $val1 < $val2 Then
        $nResult = -1 ; Put item2 before item1
    ElseIf $val1 > $val2 Then
        $nResult = 1 ; Put item2 behind item1
    EndIf

    $nResult = $nResult * $nSortDir

    Return $nResult
EndFunc   ;==>LVSort


; Retrieve the text of a listview item in a specified column
Func GetSubItemText($nCtrlID, $nItemID, $nColumn)
    Local $stLvfi = DllStructCreate("uint;ptr;int;int[2];int")
    Local $nIndex, $stBuffer, $stLvi, $sItemText

    DllStructSetData($stLvfi, 1, $LVFI_PARAM)
    DllStructSetData($stLvfi, 3, $nItemID)

    $stBuffer = DllStructCreate("char[260]")

    $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_FINDITEM, -1, DllStructGetPtr($stLvfi));

    $stLvi = DllStructCreate("uint;int;int;uint;uint;ptr;int;int;int;int")

    DllStructSetData($stLvi, 1, $LVIF_TEXT)
    DllStructSetData($stLvi, 2, $nIndex)
    DllStructSetData($stLvi, 3, $nColumn)
    DllStructSetData($stLvi, 6, DllStructGetPtr($stBuffer))
    DllStructSetData($stLvi, 7, 260)

    GUICtrlSendMsg($nCtrlID, $LVM_GETITEMA, 0, DllStructGetPtr($stLvi));

    $sItemText = DllStructGetData($stBuffer, 1)

    $stLvi = 0
    $stLvfi = 0
    $stBuffer = 0

    Return $sItemText
EndFunc   ;==>GetSubItemText
以上数据是通过_GUICtrlListView_AddArray()函数添加进去的,排序就完全不起作用了,不知道那块出了问题


经过网友chzj589的帮助,测试
_GUICtrlListView_RegisterSortCallBack($ListView1)
_GUICtrlListView_SortItems($ListView1, 0);以ID排序
_GUICtrlListView_SortItems($ListView1, GUICtrlGetState($ListView1))
可以排序,问题已解决!
发表于 2015-8-8 21:20:45 | 显示全部楼层
GUICtrlCreateListViewItem  这个会返回控件ID,这个是在LISTVIEW中创建的控件
_GUICtrlListView_AddArray() 这个添加的只是数据,添加在LISTVIEW中的数据

我理解的就是这样的。

因为今天我做实时更新LISTVIEW中时,也碰到了。才发现这的区别。
发表于 2015-8-8 21:23:34 | 显示全部楼层
回复 1# ioripalm
我看不出哪里有问题

本帖子中包含更多资源

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

×
发表于 2015-8-8 21:53:29 | 显示全部楼层
哦,点击项目后,条目重新排序
但是
    GUICtrlCreateListViewItem("ABC|666|10.05.2004", $lv)
    GUICtrlSetImage(-1, "shell32.dll", 7)
    GUICtrlCreateListViewItem("DEF|444|11.05.2005", $lv)
    GUICtrlSetImage(-1, "shell32.dll", 12)
    GUICtrlCreateListViewItem("CDE|444|12.05.2004", $lv)
    GUICtrlSetImage(-1, "shell32.dll", 3)

        Dim $ListViewArray[3][3] = [['ABC','666','10.05.2004'],['DEF','444','11.05.2005'],['CDE','444','12.05.2004']]
        _GUICtrlListView_AddArray($Lv, $ListViewArray)
一样吗?
所以 
GUICtrlRegisterListViewSort(-1, "LVSort") ; 注册用于排序的回调函数 "LVSort".
不能回调
 楼主| 发表于 2015-8-10 23:23:37 | 显示全部楼层
回复 4# chzj589


    嗯,导入的数据虽然一样,但是方式不对,导入少量数据用GUICtrlCreateListViewItem比较方便,但是遇到大量的数据还是_GUICtrlListView_AddArray速度快(目前看来效率不比用)。

虽然_GUICtrlListView_AddArray是UDF函数,使用同样是UDF的_GUICtrlListView_Create来创建Listview的话,连GUICtrlCreateListViewItem导入的数据都无法排序。

_GUICtrlListView_RegisterSortCallBack这个简单排序,和_GUICtrlListView_AddArray一样时UDF却也不能正常工作。
发表于 2015-8-11 08:34:03 | 显示全部楼层
回复 5# ioripalm

我用数据库MDB导入GUICtrlCreateListView,可以排序
发表于 2015-8-11 23:23:35 | 显示全部楼层
回复 5# ioripalm

_GUICtrlListView_RegisterSortCallBack($ListView1)
_GUICtrlListView_SortItems($ListView1, 0);以ID排序

_GUICtrlListView_SortItems($ListView1, GUICtrlGetState($ListView1))

查看帮助
 楼主| 发表于 2015-8-25 19:51:09 | 显示全部楼层
回复 7# chzj589


    感谢。测试成功,的确可以点击标题排序,而且会自动加上下小箭头。
再请问一个问题,这个注册简单排序回调函数,为什么称之为简单?是不是不能设置排序format的都算是简单排序!
发表于 2015-11-13 01:02:24 | 显示全部楼层
能贴一下,解决后的代码么?学习一下
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-11-15 01:40 , Processed in 0.082081 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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