Page 1 of 2
TV_DragAndDrop - Drag & Drop function for TreeView controls (Updated Nov, 13, 2020)
Posted: 20 Oct 2020, 18:45
by Pulover
Usage:
- Call TV_Drag() from the TreeView's G-Label when A_GuiEvent contains "D" or "d". A line will show across the TreeView while holding the button to indicate the destination where the selected node will be dropped with its children.
- If you point the mouse cursor to the half bottom part of the node text it will be dropped as a child of the pointed node. If you point it to the upper part it will drop it as sibling right below the pointed node.
- TV_Drag() returns the target node id (if valid) which you can use to call TV_Drop() and effectively move the selection. Alternatively you can set AutoDrop option on as a shorthand.
- Separating the Drag and Drop calls allows to check if the returned destination is a valid node to drop in as well as setting GuiControl, -Redraw to avoid flickering.
- TV_Drop() may be called directly to move or copy nodes programmatically. You may pass the TreeView control's hwnd to keep icons and set Copy parameter to true if you want to copy nodes instead of moving.
Sources, documentation and examples on GitHub
See also
LV_Rows
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 21 Oct 2020, 02:17
by guest3456
outstanding
Update
Posted: 21 Oct 2020, 16:31
by Pulover
- Updated TV_Drop() to return the ID of the created top node.
Thanks!
Update [Fix]
Posted: 21 Oct 2020, 18:51
by Pulover
- Fixed children being moved in reverse order.
- Fixed items being dropped as first child instead of last.
Update
Posted: 22 Oct 2020, 08:38
by Pulover
- Added DragButton parameter to TV_Drag().
- Added Hwnd and Copy parameters to TV_Drop().
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 23 Oct 2020, 05:12
by Ahk_fan
Thank you for this solution.
Update
Posted: 29 Oct 2020, 07:34
by Pulover
- Added FirstChild parameter in TV_Drop() to allow drop as first/top sibling.
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 29 Oct 2020, 13:38
by burque505
@Pulover, thanks a million for this. I have an observation about today's release: Once an item is demoted by DragAndDrop (on Win7 and Win10), it is quite difficult (impossible?) to promote it again. In the TV_Drag_Demo script, try the following.
1) You have this when the script starts.
- one.PNG (16.55 KiB) Viewed 2324 times
2) Drag the Second Parent to be a child of First Parent.
- two.PNG (18.08 KiB) Viewed 2324 times
Try to promote Second Parent again so that it is, once again, a sibling of First Parent instead of a child (i.e., a level one item). My first thought was to drag First Parent below Second Parent, but that can't be done.
Thanks again for this and all your other generous contributions.
Regards,
burque505
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 29 Oct 2020, 15:59
by Pulover
You're welcome,
@burque505.
In fact it's not only possible, but quite easy to do. Maybe you've missed this part:
If you point it to the upper part it will drop it as sibling right below the pointed node.
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 29 Oct 2020, 16:11
by burque505
@Pulover, thanks a million.
What a relief. I wasn't dragging the cursor far enough over to the left. I see now that the indicator line has to extend all the way to the left of the GUI to promote an item to Level One.
Regards, burque505
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 30 Oct 2020, 07:50
by hasantr
Thank you. As always, this work is great.
Thanks for the
Function. I was using a devious solution like creating one extension in the temp folder for each format.
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 30 Oct 2020, 17:56
by hasantr
Code: Select all
Paths :=
(
"D:\_AppData_\
D:\_AppData_\Desktop\
D:\_AppData_\Desktop\TEST\
D:\_AppData_\Desktop\TEST\TEST1\
D:\_AppData_\Desktop\TEST\TEST1\TEST 1-1\
D:\_AppData_\Desktop\TEST\TEST1\TEST 1-1\TEST 1-1-1\
D:\_AppData_\Desktop\TEST\TEST1\TEST 1-2\
D:\_AppData_\Desktop\TEST\TEST2\
D:\_AppData_\Desktop\TEST\TEST2\TEST 2-1\"
)
How is it practical to add such a list of folders that are not clear whether they are on the disk or not. I don't want them checked on disk. They just need to be added in the Tree view.
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 30 Oct 2020, 18:10
by burque505
@hasantr, take a look at the "TreeView Browser.ahk" file in the Examples folder. You will find a "CreateTreeView(TreeViewDefinitionString)" function by @Learning one in the script. Using your "Paths" variable described above as an argument to the function, you should be able to create your treeview.
Regards,
burque505
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 30 Oct 2020, 18:17
by hasantr
burque505 wrote: ↑30 Oct 2020, 18:10
@hasantr, take a look at the "TreeView Browser.ahk" file in the Examples folder. You will find a "CreateTreeView(TreeViewDefinitionString)" function by @Learning one in the script. Using your "Paths" variable described above as an argument to the function, you should be able to create your treeview.
Regards,
burque505
My attempts have failed.
Actually, I've been trying to do this for a long time. I wanted to ask here if there is a Function I missed.
Maybe I need to sleep now.
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 30 Oct 2020, 18:21
by Pulover
@hasantr, you should try the Save File button and check the format of the saved file. You might want to modify the LoadFile label to convert your format to the one expected by CreateTreeView(). The purpose of TreeView Browser was exactly to browse my files from another computer back when I wrote it.
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 30 Oct 2020, 18:25
by hasantr
Thanks I will do this after I get my sleep. If I can come up with a solution that looks good I'll put it here.
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 31 Oct 2020, 04:47
by hasantr
Pulover wrote: ↑30 Oct 2020, 18:21
@hasantr, you should try the Save File button and check the format of the saved file. You might want to modify the LoadFile label to convert your format to the one expected by CreateTreeView(). The purpose of TreeView Browser was exactly to browse my files from another computer back when I wrote it.
I've created a solution, if not very good. I hope it works for someone in need.
Thanks again.
Code: Select all
Paths :=
(
"C:\Users\hasan\Desktop\
C:\Users\hasan\Desktop\WhatsApp
C:\Users\hasan\Desktop\WhatsApp\Media\WhatsApp Documents\
C:\Users\hasan\Desktop\test\
D:\TestIndex
D:\_AppData_\Desktop
D:\_AppData_\Desktop\AHK TEST\UDFS 7ZDLL İLE
D:\_AppData_\Desktop\AHK TEST\UDFS 7ZDLL İLE\BüyükUdfLer1
D:\_AppData_\Desktop\AHK TEST\UDFS 7ZDLL İLE\UDFLER"
)
Clipboard := PathListToTree(Paths)
PathListToTree(Paths){
Paths := StrSplit(Paths,"`n")
TO := {}
For, K,Dir in Paths
{
if(Dir == "")
Continue
Dir := SubStr(Dir,StrLen(Dir),1) = "\" ? SubStr(Dir,1,StrLen(Dir) - 1) : Dir ;Remove last character if "\"
PATH := Dir
PathBack :=
Loop 125 ; NO MORE "\"
{
SplitPath,PATH,,PATH
if(TO.HasKey(PATH) == true){ ; this has a parent directory
TO[Dir] := TO[PATH] + 1
break
}
if(PathBack == PATH){ ; the loop should end as there are no new subdirectories left. This is the root directory
TO[Dir] := 1
Break
}
PathBack := PATH
}
Loop, % TO[Dir]
Stack .= "`t"
Stack .= Dir . (A_Index != Paths.MaxIndex() ? "`n" : "")
}
return Stack
}
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 01 Nov 2020, 12:02
by hasantr
@Pulover I wanted to use the GetIcon() function, but is there a problem? It takes an infinite number of icons. For example, if I call 5 PDF extensions, it returns 5 separate icon numbers. I couldn't figure out where the problem was caused.
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 01 Nov 2020, 16:46
by Pulover
hasantr wrote: ↑01 Nov 2020, 12:02
@Pulover I wanted to use the GetIcon() function, but is there a problem? It takes an infinite number of icons. For example, if I call 5 PDF extensions, it returns 5 separate icon numbers. I couldn't figure out where the problem was caused.
I don't remember writing that function... probably copied it from somewhere in the forum. But you're right, there is problem with it. Must have been my mistake when I modified it. Here's a fixed version:
Code: Select all
GetIcon(FileName, ImageListID)
{
static IconArray := []
sfi_size := A_PtrSize + 8 + (A_IsUnicode ? 680 : 340)
VarSetCapacity(sfi, sfi_size)
SplitPath, FileName,,, FileExt
if FileExt in EXE,ICO,ANI,CUR
{
ExtID := FileExt
IconNumber = 0
}
else
{
ExtID = 0
Loop 7
{
StringMid, ExtChar, FileExt, A_Index, 1
If not ExtChar
break
ExtID := ExtID | (Asc(ExtChar) << (8 * (A_Index - 1)))
}
IconNumber := IconArray[ExtID]
}
If not IconNumber
{
if not DllCall("Shell32\SHGetFileInfo" . (A_IsUnicode ? "W":"A"), "str", "." FileExt
, "uint", (FileExt ? 0x80 : 0), "ptr", &sfi, "uint", sfi_size, "uint", (FileExt ? 0x111 : 0x101))
IconNumber = 9999999
else
{
hIcon := NumGet(sfi, 0)
IconNumber := DllCall("ImageList_ReplaceIcon", "ptr", ImageListID, "int", -1, "ptr", hIcon) + 1
DllCall("DestroyIcon", "ptr", hIcon)
IconArray[ExtID] := IconNumber
}
}
return IconNumber
}
Re: TV_DragAndDrop - Drag & Drop function for TreeView controls
Posted: 01 Nov 2020, 18:34
by hasantr
Pulover wrote: ↑01 Nov 2020, 16:46
hasantr wrote: ↑01 Nov 2020, 12:02
@Pulover I wanted to use the GetIcon() function, but is there a problem? It takes an infinite number of icons. For example, if I call 5 PDF extensions, it returns 5 separate icon numbers. I couldn't figure out where the problem was caused.
I don't remember writing that function... probably copied it from somewhere in the forum. But you're right, there is problem with it. Must have been my mistake when I modified it. Here's a fixed version:
Code: Select all
GetIcon(FileName, ImageListID)
{
static IconArray := []
sfi_size := A_PtrSize + 8 + (A_IsUnicode ? 680 : 340)
VarSetCapacity(sfi, sfi_size)
SplitPath, FileName,,, FileExt
if FileExt in EXE,ICO,ANI,CUR
{
ExtID := FileExt
IconNumber = 0
}
else
{
ExtID = 0
Loop 7
{
StringMid, ExtChar, FileExt, A_Index, 1
If not ExtChar
break
ExtID := ExtID | (Asc(ExtChar) << (8 * (A_Index - 1)))
}
IconNumber := IconArray[ExtID]
}
If not IconNumber
{
if not DllCall("Shell32\SHGetFileInfo" . (A_IsUnicode ? "W":"A"), "str", "." FileExt
, "uint", (FileExt ? 0x80 : 0), "ptr", &sfi, "uint", sfi_size, "uint", (FileExt ? 0x111 : 0x101))
IconNumber = 9999999
else
{
hIcon := NumGet(sfi, 0)
IconNumber := DllCall("ImageList_ReplaceIcon", "ptr", ImageListID, "int", -1, "ptr", hIcon) + 1
DllCall("DestroyIcon", "ptr", hIcon)
IconArray[ExtID] := IconNumber
}
}
return IconNumber
}
Thanks. I tried Static array. "IconArray[ExtID]" I skipped the fix.