1

Тема: AHK: можно ли сделать меню с перетаскиваемыми menuitem'ами?

Встроенной командой Menu, похоже, что нельзя. Но может какими-нибудь dllcall'ами можно на более низком уровне это сделать?
На крайний случай осталась идея делать gui+listview/treeview, там вроде drag'n'drop поддерживается нативно.

2

Re: AHK: можно ли сделать меню с перетаскиваемыми menuitem'ами?

Кажется у нас такой темы ещё не было.
TreeView: Drag and Drop items

+ Пример с TreeView
#singleinstance force

SetTimer, TREEVIEWdragTIMER, 10
SetTimer, TREEVIEWdragTIMER, Off

Gui, Add, TreeView, gMySubroutine h195 0x200 AltSubmit 0x400
Gui, Add, Button, gMOVEdown, MOVEdown
Gui, Add, Button, gMOVEup, MOVEup

P1 := TV_Add("First parent")
P1C1 := TV_Add("Parent 1's first child", P1)  ; Specify P1 to be this item's parent.
P2 := TV_Add("Second parent")
P2C1 := TV_Add("Parent 2's first child", P2)
P2C2 := TV_Add("Parent 2's second child", P2)
P2C2C1 := TV_Add("Child 2's first child", P2C2)
P3 := TV_Add("3rd parent")
P4 := TV_Add("4th parent")
Gui, Show, ,Drag and drop experiment..  ; Show the window and its TreeView.
return

GuiEscape:
GuiClose:  ; Exit the script when the user closes the TreeView's GUI window.
ExitApp
;------------------------------------------------------------------------------
MOVEup:
TREEVIEWmoveup()
return
;------------------------------------------------------------------------------
MOVEdown:
TREEVIEWmovedown()
return
;------------------------------------------------------------------------------
MySubroutine:
If A_GuiEvent=D
{
    MouseGetPos, , OutputVarY
    SetTimer, TREEVIEWdragTIMER, On
}
return
;------------------------------------------------------------------------------
TREEVIEWdragTIMER:
OLDvalue=
;TV_Modify(A_EventInfo , "Select")
GetKeyState, state, LButton, P
If state=U
{
    ;TV_Modify(A_EventInfo , "Select")
    SetTimer, TREEVIEWdragTIMER, Off
    OutputVarY=
    OLDvalue=
    NEWOutputVarY=
    return
}
MouseGetPos, , NEWOutputVarY 
If NEWOutputVarY=%OutputVarY%
    return

OLDvalue:=Sub(OutputVarY, 11)
If NEWOutputVarY<%OLDvalue%
{
    MouseGetPos, , OutputVarY
    TREEVIEWmoveup()
    return
}

OLDvalue:=Add(OutputVarY, 11)
If NEWOutputVarY>%OLDvalue%
{
    MouseGetPos, , OutputVarY
    TREEVIEWmovedown()
    return
}
return

;////////////////////////// FUNCTIONS //////////////////////////
TREEVIEWmoveup()
{
TV_GetText(PREVitem, TV_GetPrev(TV_GetSelection()))
TV_GetText(THISitem, TV_GetSelection())
If PREVitem=
    return

; LOOPS THROUGH ITEM.. STORING THE TEXT OF CHILD ITEMS IN A STRING.. (there's gotta be a better way!!)

Loop
{
    If TV_GetChild(TV_GetSelection())=0   ; CURRENT ITEM HAS CHILD ITEMS..
        break
    TV_GetText(CHILDitem, TV_GetChild(TV_GetSelection()))
    TV_Delete(TV_GetChild(TV_GetSelection())) 
    If THISitemARRAY=
        THISitemARRAY=%CHILDitem%
    Else
        THISitemARRAY=%THISitemARRAY%|%CHILDitem%
}
Loop
{
    If TV_GetChild(TV_GetPrev(TV_GetSelection()))=0 ; CURRENT ITEM HAS CHILD ITEMS..
        break
    TV_GetText(CHILDitem, TV_GetChild(TV_GetPrev(TV_GetSelection())))
    TV_Delete(TV_GetChild(TV_GetPrev(TV_GetSelection())))
    If PREVitemARRAY=
        PREVitemARRAY=%CHILDitem%
    Else
        PREVitemARRAY=%PREVitemARRAY%|%CHILDitem%
}
If THISitemARRAY<>
{
    Loop, Parse, THISitemARRAY, |
        TV_Add(A_LoopField, TV_GetPrev(TV_GetSelection()))

}
If PREVitemARRAY<>
{
    Loop, Parse, PREVitemARRAY, |
        TV_Add(A_LoopField, TV_GetSelection())
}
TV_Modify(TV_GetSelection() , "", PREVitem)
TV_Modify(TV_GetPrev(TV_GetSelection()) , "Select", THISitem)
PREVitemARRAY=
THISitemARRAY=
return
}
;------------------------------------------------------------------------------
TREEVIEWmovedown()
{
TV_GetText(NEXTitem, TV_GetNext(TV_GetSelection()))
TV_GetText(THISitem, TV_GetSelection())
If NEXTitem=
    return

Loop
{
    If TV_GetChild(TV_GetSelection())=0 
        break
    TV_GetText(CHILDitem, TV_GetChild(TV_GetSelection()))
    TV_Delete(TV_GetChild(TV_GetSelection())) 
    If THISitemARRAY=
        THISitemARRAY=%CHILDitem%
    Else
        THISitemARRAY=%THISitemARRAY%|%CHILDitem%
}
Loop
{
    If TV_GetChild(TV_GetNext(TV_GetSelection()))=0 
        break
    TV_GetText(CHILDitem, TV_GetChild(TV_GetNext(TV_GetSelection())))
    TV_Delete(TV_GetChild(TV_GetNext(TV_GetSelection())))
    If NEXTitemARRAY=
        NEXTitemARRAY=%CHILDitem%
    Else
        NEXTitemARRAY=%NEXTitemARRAY%|%CHILDitem%
}
If THISitemARRAY<>
{
    Loop, Parse, THISitemARRAY, |
        TV_Add(A_LoopField, TV_GetNext(TV_GetSelection()))

}
If NEXTitemARRAY<>
{
    Loop, Parse, NEXTitemARRAY, |
        TV_Add(A_LoopField, TV_GetSelection())
}
TV_Modify(TV_GetSelection() , "", NEXTitem)
TV_Modify(TV_GetNext(TV_GetSelection()) , "Select", THISitem)
NEXTitemARRAY=
THISitemARRAY=
return
}
;------------------------------------------------------------------------------
Add(x, y)
{
 return x + y   ; "Return" expects an expression.
}
;------------------------------------------------------------------------------
Sub(x, y)
{
 return x - y   ; "Return" expects an expression.
}

[Class] LV_Rows - Copy, Cut, Paste and Drag ListViews

ListView Drag & Drop

3 (изменено: Drugoy, 2014-11-08 21:30:34)

Re: AHK: можно ли сделать меню с перетаскиваемыми menuitem'ами?

Пример с деревом - с багом
Баг в том, что если курсор при перетаскивании опустить далеко вниз за окно, то потом достаточно повести его совсем чуть-чуть (всё ещё не отпуская кнопку мыши), для перетаскивания вверх, хотя курсор остаётся далеко внизу под окном.
Делать это через позицию курсора как-то не правильно.

Ну и раз уж это дерево, то почему нельзя ветку верхнего уровня сделать под-веткой?

Пример с LV - рабочий, только кода ну уж очень много :-/

4

Re: AHK: можно ли сделать меню с перетаскиваемыми menuitem'ами?

Что вообще задумано? Меню контекстное, меню области уведомлений, главное меню, меню заголовка или собственное нестандартное уникальное меню?

5

Re: AHK: можно ли сделать меню с перетаскиваемыми menuitem'ами?

Хочу улучшить свой скрипт, добавив возможность сортировки итемов в меню простым драг'н'дропом, а по возможности и создание суб-меню при драг-н-дропе итема в итем.