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

如何在ListView中实现拖动行?并且如何保存拖动后行的位置?

[复制链接]
发表于 2009-3-16 18:35:01 | 显示全部楼层 |阅读模式
我想实现对ListView中的内容能够任意的拖动改变位置,查了很长时间不知道怎么搞,哪位高人请指点一下?谢谢!

[ 本帖最后由 sd007 于 2009-3-21 19:30 编辑 ]
 楼主| 发表于 2009-3-20 19:56:26 | 显示全部楼层
请高人指点一下,谢谢
发表于 2009-3-20 20:45:46 | 显示全部楼层
#include <GuiListView.au3>
#include <WindowsConstants.au3>

$hGui = GuiCreate("Test", 400, 300)

$lvExStyle = bitOr($lvs_ex_fullrowselect, $lvs_ex_gridlines, _
                $lvs_ex_doublebuffer, $ws_ex_clientedge)

Global $iFlag = False
$lv = GuiCtrlCreateListView("Test|Drag", 5, 5, 390, 280, $lvs_report, $lvExStyle)
For $o = 1 to 10
        $Item = "Item " & $o & "|Sub Item " & $o & " - 1" 
        GuiCtrlCreateListViewItem($Item, $lv)
Next

GuiSetState()
GuiRegisterMsg($wm_notify, "_wmNotify")

Do
Until        GuiGetMsg() = -3

Func _WmNotify($hWnd, $iMsg, $wParam, $lParam)
        Local $tNmhdr, $iCode
        $tNmhdr = DllStructCreate($tagNmhdr, $lParam)
        $iCode = DllStructGetData($tNmhdr, "code")
        If $wParam = $lv Then
                Switch $iCode
                Case $lvn_beginDrag
                        $iFlag = True        
                Case $lvn_hotTrack
                        If not $iFlag Then Return False
                        $iFlag = False
                        _DragItems()
                EndSwitch
        EndIf
        $tNmhdr = 0
EndFunc        ;==>_WmNotify()

Func _DragItems()
        Local $selection = _GuiCtrlListView_GetSelectedIndices($lv, true)
        If $selection[0] = 0 then Return False
        Local $selectionText[Ubound($selection) + 1][2]
        For $d = 0 to $selection[0] - 1
                For $x = 0 to 1
                        $selectionText[$d][$x] = _GuiCtrlListView_GetItemText($lv, $selection[$d+1], $x) 
                Next
        Next
        _GuiCtrlListView_DeleteItemsSelected(GuiCtrlGetHandle($lv))
        Local $cursor = GuiGetCursorInfo($hGui)
        Local $lvsPos = ControlGetPos($hGui, "", $lv)
        $lvsPos[0] = $cursor[0] - $lvsPos[0]
        $lvsPos[1] = $cursor[1] - $lvsPos[1]
        $InsertPos = _GuiCtrlListView_HitTest($lv, $lvsPos[0], $lvsPos[1])
        If $InsertPos[0] = -1 then $InsertPos[0] = _GuiCtrlListView_GetItemCount($lv)
        For $d = $selection[0] - 1 to 0 step - 1
                _GuiCtrlListView_InsertItem($lv, $selectionText[$d][0], $InsertPos[0], 0)
                _GuiCtrlListView_AddSubItem($lv, $InsertPos[0], $selectionText[$d][1], 1,1)
        Next
EndFunc        ;==>_DragItems()


[ 本帖最后由 pusofalse 于 2009-3-20 20:51 编辑 ]

评分

参与人数 5威望 +50 金钱 +125 贡献 +49 收起 理由
kn007 + 50 + 90 + 49 Nice Job!
顽固不化 + 10 精品文章
yokoliu + 5 牛人
llztt + 10 要是早有你的代码该多好,呵呵
sanhen + 10 非常经典的代码。感谢兄弟的分享。

查看全部评分

 楼主| 发表于 2009-3-21 19:29:53 | 显示全部楼层
很好用,非常感谢你的代码!
发表于 2009-3-21 20:40:28 | 显示全部楼层
高手。向你学习!
发表于 2009-3-21 22:15:37 | 显示全部楼层
改进建议:修改为更通用性的,譬如Func _DragItems($thelv),以及适用于任何个子ITEM的LISTVIEW。。

再次楼主的做法思路,太棒了,呵呵,终于不用手动按纽一次次的调整LV顺序了
 楼主| 发表于 2009-3-23 16:52:04 | 显示全部楼层
这是我的代码应用,须注意:
1.ListView的第一列是数据库表的字段ID值
2.数据库表中有一个orderid字段,用于排序(从大到小排列)

ListView_DragItems($Form1,$ListView1,数据库表名)

;改进后的_DragItems(),支持多列
Func ListView_DragItems($hForm,$hWnd,$tableName="")
        Local $selection = _GuiCtrlListView_GetSelectedIndices($hWnd, true)
        If $selection[0] = 0 then Return False
        $tmpItemLs=_GUICtrlListView_GetItemTextArray($hWnd, $selection[1]);得到列数$tmpItemLs[0]
        Local $selectionText[$selection[0]][$tmpItemLs[0]+1]
        For $d = 0 to $selection[0] - 1
            $tmp=_GUICtrlListView_GetItemTextArray($hWnd, $selection[$d+1])
                For $x = 0 to $tmpItemLs[0]
                        $selectionText[$d][$x] = _GuiCtrlListView_GetItemText($hWnd, $selection[$d+1], $x) 
                Next
        Next
        _GuiCtrlListView_DeleteItemsSelected($hWnd)
        Local $cursor = GuiGetCursorInfo($hForm)
        Local $lvsPos = ControlGetPos($hForm, "", $hWnd)
        $lvsPos[0] = $cursor[0] - $lvsPos[0]
        $lvsPos[1] = $cursor[1] - $lvsPos[1]
        $InsertPos = _GuiCtrlListView_HitTest($hWnd, $lvsPos[0], $lvsPos[1])
        If $InsertPos[0] = -1 then $InsertPos[0] = _GuiCtrlListView_GetItemCount($hWnd)
        SaveSortToSql(_GuiCtrlListView_GetItemText($hWnd, $InsertPos[0]-1),$selectionText,$tableName);将排序保存到数据库
     For $d = $selection[0] - 1 to 0 step - 1
                _GuiCtrlListView_InsertItem($hWnd, $selectionText[$d][0], $InsertPos[0], 0)
                For $x = 1 to $tmpItemLs[0]
                    _GuiCtrlListView_AddSubItem($hWnd, $InsertPos[0], $selectionText[$d][$x], $x,1)
                Next
        Next
EndFunc

;将排序保存到数据库
Func SaveSortToSql($ItemRsId,$selectionText,$tableName="")
        If $tableName="" Then return
    If $ItemRsId="" Then;当拖动到最上面时
            $orderid=GetRs_2("select orderid from "&$tableName&" order by orderid desc",1);从数据库中查询最大的orderid
                $orderid=$orderid[0][0]+1
        Else
            $orderid=GetRs_2("select orderid from "&$tableName&" where id="&$ItemRsId&"",1);得到要插入在哪个Item后面的orderid
                $orderid=$orderid[0][0]
            ExecSQL("update "&$tableName&" set orderid=orderid+"&ubound($selectionText)&" where orderid>="&$orderid&"");将大于orderid的所有记录的orderid都增加ubound($selectionText)
        EndIf
        For $i = 0 to ubound($selectionText)-1
                ExecSQL("update "&$tableName&" set orderid="&$orderid + (ubound($selectionText)-1-$i)&" where id="&$selectionText[$i][0]&"")
        Next
EndFunc
发表于 2011-12-11 16:26:20 | 显示全部楼层
刚好想用类代码,参考参考,谢谢分享
发表于 2014-3-28 09:39:16 | 显示全部楼层
实用的代码。谢谢分享。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-9-28 11:21 , Processed in 0.089164 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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