LV_Drag() for ahk v2——显示拖拽ListView列表项特效

引入

在ahk v1中ListView有事件"D"代表拖拽开始,进而对拖拽事件进行处理。

可参考:Github Pulover- Class_LV_Rows 该v1类库就据此实现了Drag拖拽特效。

但v2中ListView的"D"事件没有被官方实现,必须自己使用"OnNotify()"进行实现,此外 Class_LV_Rows 类库也仅仅提供了v1版本。

本人将其中的"LV_Drag()"方法用v2实现,并给出"D"事件的实现方式。

可以实现很多不错的功能:

  1. 拖动排序
  2. 从一个列表拖动项目到另一个列表
  3. 拖动到列表外删除项目

基础示例

g := Gui()
LV := g.Add("ListView", "x10 y10 w500 h500", ["No", "foo"])
loop 30
    LV.Add(, A_Index, "bar" A_Index)
LV.ModifyCol(1, "AutoHdr"), LV.ModifyCol(2, "AutoHdr")
g.Show()

LVN_BEGINDRAG := -109
LV.OnNotify(LVN_BEGINDRAG, LV_OnDrag) ; 接受拖动事件通知
LV_OnDrag(LV, lParam) {
    ; NMHDR_hwndFrom := NumGet(lParam, 0, 'Ptr')
    ; NMHDR_idFrom := NumGet(lParam, A_PtrSize, 'UInt')
    ; NMHDR_code := NumGet(lParam, 2 * A_PtrSize, 'UInt')
    ; NMLISTVIEW_iItem := NumGet(lParam, 3 * A_PtrSize, 'Int') ; The begin row num (from 1).

    beginRowNum := NumGet(lParam, 3 * A_PtrSize, 'Int') + 1 ; 通知消息中解析出拖动开始的行号
    endRowNum := LV_Drag() ; 显示拖动横条,直到拖动结束返回最终行号,超出范围返回""
    ToolTip(Format("{}-{}", beginRowNum, endRowNum))
}

函数实现

LV_Drag.ah2

/**
 * @Name: LV_Drag
 * @Author: ruchuby
 * @LastEditors: ruchuby
 * @LastEditTime: 2023-03-16
 * @Description: 拖拽事件触发时调用LV_Drag,显示拖动横条并在拖动结束时返回最终行号
 * Update from Pulover [Rodolfo U. Batista]'s Class_LV_Rows: https://github.com/Pulover/Class_LV_Rows/blob/master/Class_LV_Rows.ahk
 */

;example
/*
g := Gui()
LV := g.Add("ListView", "x10 y10 w500 h500", ["No", "foo"])
loop 30
    LV.Add(, A_Index, "bar" A_Index)
LV.ModifyCol(1, "AutoHdr"), LV.ModifyCol(2, "AutoHdr")
g.Show()

LVN_BEGINDRAG := -109
LV.OnNotify(LVN_BEGINDRAG, LV_OnDrag) ; 接受拖动事件通知
LV_OnDrag(LV, lParam) {
    ; NMHDR_hwndFrom := NumGet(lParam, 0, 'Ptr')
    ; NMHDR_idFrom := NumGet(lParam, A_PtrSize, 'UInt')
    ; NMHDR_code := NumGet(lParam, 2 * A_PtrSize, 'UInt')
    ; NMLISTVIEW_iItem := NumGet(lParam, 3 * A_PtrSize, 'Int') ; The begin row num (from 1).

    beginRowNum := NumGet(lParam, 3 * A_PtrSize, 'Int') + 1 ; 通知消息中解析出拖动开始的行号
    endRowNum := LV_Drag() ; 显示拖动横条,直到拖动结束返回最终行号,超出范围返回""
    ToolTip(Format("{}-{}", beginRowNum, endRowNum))
}
*/

;=======================================================================================
;    Method:             LV_Drag()
;    Description:        Drag-and-Drop row showing a destination bar.
;    Parameters:
;        AutoScroll:     If true or omitted the ListView will automatically scroll
;                            up or down when the cursor is above or below the control.
;        ScrollDelay:    Delay in miliseconds for AutoScroll. Default is 100ms.
;        LineThick:      Thickness of the destination bar in pixels. Default is 2px.
;        Color:          Color of destination bar. Default is "Black".
;    Return:             The destination row number.
;=======================================================================================
LV_Drag(AutoScroll := true, ScrollDelay := 100, LineThick := 2, Color := "Black")
{
    Static LVIR_LABEL := 0x0002
    Static LVM_GETITEMCOUNT := 0x1004
    Static LVM_SCROLL := 0x1014
    Static LVM_GETTOPINDEX := 0x1027
    Static LVM_GETCOUNTPERPAGE := 0x1028
    Static LVM_GETSUBITEMRECT := 0x1038
    Static LV_currColHeight := 0
    Static MarkLineGui := Gui()


    SM_CXVSCROLL := SysGet(2)
    old_CoordModeMouse := A_CoordModeMouse
    CoordMode("Mouse", "Client")
    MouseGetPos(, , &LV_Win, &LV_LView, 2)
    WinGetClientPos(&Win_X, &Win_Y, &Win_W, &Win_H, "ahk_id " LV_Win)
    ControlGetPos(&LV_lx, &LV_ly, &LV_lw, &LV_lh, LV_LView)
    LV_lw := LV_lw * 96 // A_ScreenDPI
    LV_XYstruct := Buffer(16, 0)

    While (GetKeyState("LButton", "P"))
    {
        MouseGetPos(&LV_mx, &LV_my, , &CurrCtrl, 2)
        If (AutoScroll)
        {
            LV_mx -= LV_lx, LV_my -= LV_ly
            If (LV_my < 0)
            {
                SendMessage(LVM_SCROLL, 0, -LV_currColHeight, , LV_LView)
                Sleep(ScrollDelay)
            }
            If (LV_my > LV_lh)
            {
                SendMessage(LVM_SCROLL, 0, LV_currColHeight, , LV_LView)
                Sleep(ScrollDelay)
            }
        }

        If (CurrCtrl != LV_LView)
        {
            LV_currRow := ""
            MarkLineGui.Hide()
            continue
        }

        LV_TotalNumOfRows := SendMessage(LVM_GETITEMCOUNT, 0, 0, , LV_LView)
        LV_NumOfRows := SendMessage(LVM_GETCOUNTPERPAGE, 0, 0, , LV_LView)
        LV_topIndex := SendMessage(LVM_GETTOPINDEX, 0, 0, , LV_LView)
        Line_W := (LV_TotalNumOfRows > LV_NumOfRows) ? LV_lw - SM_CXVSCROLL : LV_lw

        Loop LV_NumOfRows + 1
        {
            LV_which := LV_topIndex + A_Index - 1
            NumPut("UInt", LVIR_LABEL, LV_XYstruct, 0)
            NumPut("UInt", A_Index - 1, LV_XYstruct, 4)
            SendMessage(LVM_GETSUBITEMRECT, LV_which, LV_XYstruct.Ptr, , LV_LView)
            LV_RowY := NumGet(LV_XYstruct, 4, "UInt")
                , LV_RowY2 := NumGet(LV_XYstruct, 12, "UInt")
                , LV_currColHeight := LV_RowY2 - LV_RowY
            If (LV_my <= LV_RowY + LV_currColHeight)
            {
                LV_currRow := LV_which + 1
                    , LV_currRow0 := LV_which
                    , Line_Y := Win_Y + LV_ly + LV_RowY
                    , Line_X := Win_X + LV_lx
                If (LV_currRow > (LV_TotalNumOfRows + 1))
                {
                    MarkLineGui.Hide()
                    LV_currRow := ""
                }
                Break
            }
        }

        If (LV_currRow)
        {
            MarkLineGui.BackColor := Color
            MarkLineGui.Opt("+LastFound +AlwaysOnTop +Toolwindow -Caption")
            MarkLineGui.Show(Format("w{} h{} y{} x{} NoActivate", Line_W, LineThick, Line_Y, Line_X))
        }
    }

    MarkLineGui.Hide()
    CoordMode("Mouse", old_CoordModeMouse)
    return LV_currRow
}

给TA捐赠
共{{data.count}}人
人已捐赠
AHKV2类和函数库

Class_LV_Logger for ahk v2——高颜值、可定制化GUI日志组件

2023-3-15 19:00:33

AHKV1

Loop, Files, F:批量计划autohtkeyAHK脚本库*.ahk,R

2020-3-9 2:46:44

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索