Hi all,
I was thinking along the following lines. Out of the entire filesystem and folder structure of my hard drive, about 30 folders are important. I have 1 START folder that contains a shortcut to several files and also to these 30 folders. The list can change, though.
So when I need to copy or paste files to a certain folder, I now press Win-e for the File Explorer, then launch the START folder, then right-click the target folder shortcut and Paste.
I think that can be faster/easier and I don't need all the File Explorer windows. The idea is to have a popup userform with a listbox containing the 30 folders. Basically, we need to loop through the START folder and keep (1) all shortcuts, that (2) point to a valid folder. Then I can click on a folder and the selected files can be moved to the target folder.
The path of the START folder can he hardcoded in the script, but a loop would be good to loop through its contents.
Does anyone have something along these lines ? I can do the rest of the scripting based on an example for example. I could add the Desktop location / Downloads / USB key location to the list, and so on.
Thank you in advance !
Improved SendTo dialog Topic is solved
Re: Improved SendTo dialog Topic is solved
Try something like this;
Code: Select all
#NoEnv
#SingleInstance Force
; Create a GUI with checkboxes to save the path of the last copied files and
; copy/move selected items to other directories shown in a Menu:
; Add in this list the path of the directories
folder_paths =
(
%A_MyDocuments%
%A_Desktop%
D:\my folder
)
; Create the Menu
Loop, Parse, folder_paths, `n
{
Menu copy_files, Add, %A_LoopField%, copy_files
Menu move_files, Add, %A_LoopField%, move_files
}
; save the path of the last copied files
OnClipboardChange("files_copied")
return
; Create the GUI
files_copied(type){
global
If (type == 1) ; the Clipboard contains text or files copied
{
If (DllCall("IsClipboardFormatAvailable", "uint", 15)) ; the Clipboard contains files
{
ToolTip, file(s) copied
Gui, destroy
Gui, Color, ControlColor, Black
Gui, Font, CDefault, Lucida Console
Gui, Add, Button, x30 y5 w100 h26 gCopy, Copy
Gui, Add, Button, x230 y5 w100 h26 gMove, Move
Gui, Add, CheckBox, x20 y50 vCh200 gCheckAll cYellow, Select All
Gui, Add, CheckBox, x20 y75 vCh201 gUnCheckAll cYellow, De-Select All
Loop, Parse, Clipboard, `n, `r
{
y_pos := 100 + (A_Index * 25)
Gui, Add, CheckBox, x20 y%y_pos% vCh%A_Index% cYellow, %A_LoopField%
I := A_Index ; number of copied files
}
Gui_height := 125+I*25
Gui, Show, x5 y5 w400 h%Gui_height%, Files copied ; comment out this line if you want to only show the Gui after pressing F1
Sleep 1000
ToolTip
}
}
}
; Press F1 to show the Gui if it's hidden
F1:: Gui, Show
; or If the command in the above function is commented out
; F1:: Gui, Show, x100 y5 w400 h%Gui_height%, Files copied
CheckAll:
Loop, %I%
GuiControl,, Ch%A_Index%, 1
GuiControl,, Ch200, 1
GuiControl,, Ch201, 0
return
UnCheckAll:
Loop, %I%
GuiControl,, Ch%A_Index%, 0
GuiControl,, Ch200, 0
GuiControl,, Ch201, 1
return
Copy:
Menu copy_files, show
return
Move:
Menu move_files, show
return
copy_files:
Gui, submit, nohide
Run %A_ThisMenuItem%\
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, file,, Ch%A_Index%, Text
FileCopy, %file%, %A_ThisMenuItem%\, 1 ; overwrite existing files
}
}
return
move_files:
MsgBox, 262180, Move Files, Are you sure you want to move the selected files to`n`n"%A_ThisMenuItem%"?
IfMsgBox No
return
Run %A_ThisMenuItem%\
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, file,, Ch%A_Index%, Text
FileMove, %file%, %A_ThisMenuItem%\, 1 ; overwrite existing files
}
else
{
GuiControlGet, file,, Ch%A_Index%, Text
New_Clipboard .= file . "`n" ; concatenate the outputs
}
}
If (New_Clipboard := "")
Gui, destroy
else
ClipboardSetFiles(New_Clipboard, DropEffect := "Copy")
return
GuiClose:
Gui, Hide
return
; Press Esc to terminate the script
Esc:: ExitApp
; https://autohotkey.com/boards/viewtopic.php?p=63914#p63914
ClipboardSetFiles(FilesToSet, DropEffect := "Copy") {
; FilesToSet - list of fully qualified file pathes separated by "`n" or "`r`n"
; DropEffect - preferred drop effect, either "Copy", "Move" or "" (empty string)
Static TCS := A_IsUnicode ? 2 : 1 ; size of a TCHAR
Static PreferredDropEffect := DllCall("RegisterClipboardFormat", "Str", "Preferred DropEffect")
Static DropEffects := {1: 1, 2: 2, Copy: 1, Move: 2}
; Count files and total string length
TotalLength := 0
FileArray := []
Loop, Parse, FilesToSet, `n, `r
{
If (Length := StrLen(A_LoopField))
FileArray.Push({Path: A_LoopField, Len: Length + 1})
TotalLength += Length
}
FileCount := FileArray.Length()
If !(FileCount && TotalLength)
Return False
; Add files to the clipboard
If DllCall("OpenClipboard", "Ptr", A_ScriptHwnd) && DllCall("EmptyClipboard") {
; HDROP format
; 0x42 = GMEM_MOVEABLE (0x02) | GMEM_ZEROINIT (0x40)
hDrop := DllCall("GlobalAlloc", "UInt", 0x42, "UInt", 20 + (TotalLength + FileCount + 1) * TCS, "UPtr")
pDrop := DllCall("GlobalLock", "Ptr" , hDrop)
Offset := 20
NumPut(Offset, pDrop + 0, "UInt") ; DROPFILES.pFiles = offset of file list
NumPut(!!A_IsUnicode, pDrop + 16, "UInt") ; DROPFILES.fWide = 0 --> ANSI, fWide = 1 --> Unicode
For Each, File In FileArray
Offset += StrPut(File.Path, pDrop + Offset, File.Len) * TCS
DllCall("GlobalUnlock", "Ptr", hDrop)
DllCall("SetClipboardData","UInt", 0x0F, "UPtr", hDrop) ; 0x0F = CF_HDROP
; Preferred DropEffect format
If (DropEffect := DropEffects[DropEffect]) {
; Write Preferred DropEffect structure to clipboard to switch between copy/cut operations
; 0x42 = GMEM_MOVEABLE (0x02) | GMEM_ZEROINIT (0x40)
hMem := DllCall("GlobalAlloc", "UInt", 0x42, "UInt", 4, "UPtr")
pMem := DllCall("GlobalLock", "Ptr", hMem)
NumPut(DropEffect, pMem + 0, "UChar")
DllCall("GlobalUnlock", "Ptr", hMem)
DllCall("SetClipboardData", "UInt", PreferredDropEffect, "Ptr", hMem)
}
DllCall("CloseClipboard")
Return True
}
Return False
}
Re: Improved SendTo dialog
Many many thanks !
I will review this today and post my feedback.
I will review this today and post my feedback.
Re: Improved SendTo dialog
Amazing !
I will extend the logic and post updates here.
Thank you very much.
I will extend the logic and post updates here.
Thank you very much.
Re: Improved SendTo dialog
I added the option to provide paths of directories that contain shortcuts. The targeted directories of the shortcuts are used in the script too.
Code: Select all
; Add in this list the path of the directories
folder_paths =
(
%A_Desktop%
%A_MyDocuments%
)
; Add in this list the path of the directories that contain shortcuts
; The targeted directories are used in the script too
folder_paths_to_loop =
(
D:\OneDrive\............\Shortcuts & backups\START
)
; Create the Menu
Loop, Parse, folder_paths, `n
{
Menu copy_files, Add, %A_LoopField%, copy_files
Menu move_files, Add, %A_LoopField%, move_files
}
Loop, Parse, folder_paths_to_loop, `n
{
Loop, Files, %A_LoopField%\*, F
{
extensions := "lnk,"
if A_LoopFileExt in %extensions%
{
FileGetShortcut, %A_LoopFileFullPath%, shortcutTargetPath
If( InStr( FileExist(shortcutTargetPath), "D") )
{
Menu copy_files, Add, %shortcutTargetPath%, copy_files
Menu move_files, Add, %shortcutTargetPath%, move_files
}
}
}
}
Last edited by Wigi on 25 Apr 2020, 16:03, edited 1 time in total.
Re: Improved SendTo dialog
I marked the topic as solved but I will continue to make the script even more functional. Thanks.
Re: Improved SendTo dialog
If you only want to copy selected files, you could also create a shortcut of your favorites folders in the sendto folder.
To open the sendto folder use the command:
To open the sendto folder use the command:
Code: Select all
Run shell:sendto
Re: Improved SendTo dialog
- Version where I have reformatted the file paths
- Also the directories are loaded in the menu at runtime, rather than when the script is refreshed. It could be that in the meantime locations are added so I want to have them included.
- Sanity checks were added, such that at least 1 file should be selected to do the copy or cut.
- If the user copies a file to the same folder, I add ' - Copy' as a suffix in the filename.
For now, the user needs to do a copy or cut so the clipboard is filled with files. Then hit F1 to show the userform and proceed.
- Also the directories are loaded in the menu at runtime, rather than when the script is refreshed. It could be that in the meantime locations are added so I want to have them included.
- Sanity checks were added, such that at least 1 file should be selected to do the copy or cut.
- If the user copies a file to the same folder, I add ' - Copy' as a suffix in the filename.
For now, the user needs to do a copy or cut so the clipboard is filled with files. Then hit F1 to show the userform and proceed.
Code: Select all
#NoEnv
#SingleInstance Force
; Create a GUI with checkboxes to save the path of the last copied files and
; copy/move selected items to other directories shown in a Menu:
; Add in this list the path of the directories
folder_paths =
(
Desktop `t[%A_Desktop%]
My Documents `t[%A_MyDocuments%]
)
; Add in this list the path of the directories that contain shortcuts.
; The targeted directories of the shortcuts are used in the script too.
folder_paths_to_loop =
(
D:\OneDrive\O....ups\COPY_CUT
)
; save the path of the last copied files
OnClipboardChange("files_copied")
return
; Create the GUI
files_copied(type){
global
If (type == 1) ; the Clipboard contains text or files copied
{
If (DllCall("IsClipboardFormatAvailable", "uint", 15)) ; the Clipboard contains files
{
ToolTip, file(s) copied/cut
Gui, destroy
Gui, Color, ControlColor, Black
Gui, Font, CDefault, Lucida Console
Gui, Add, Button, x30 y5 w100 h26 gMove, Move
Gui, Add, Button, x230 y5 w100 h26 gCopy, Copy
Gui, Add, CheckBox, x20 y50 vCh200 gCheckAll cYellow, Select All
Gui, Add, CheckBox, x20 y75 vCh201 gUnCheckAll cYellow, De-Select All
Loop, Parse, Clipboard, `n, `r
{
y_pos := 100 + (A_Index * 25)
; Gui, Add, CheckBox, x20 y%y_pos% vCh%A_Index% cYellow, %A_LoopField%
SplitPath, A_LoopField, filename, path
Gui, Add, CheckBox, x20 y%y_pos% vCh%A_Index% cYellow, %filename% `t[%path%]
I := A_Index ; number of copied files
}
Gui_height := 125+I*25
; ; ; Gui, Show, x5 y5 w600 h%Gui_height%, SendTo ; comment out this line if you want to only show the Gui after pressing F1
GoSub CheckAll
Sleep 1000
ToolTip
}
}
}
; Press F1 to show the Gui if it's hidden
; ; ; F1:: Gui, Show
; or If the command in the above function is commented out
F1::
Menu copy_files, UseErrorLevel
Menu move_files, UseErrorLevel
Menu copy_files, DeleteAll
Menu move_files, DeleteAll
Menu copy_files, UseErrorLevel, OFF
Menu move_files, UseErrorLevel, OFF
; Create the Menu
Loop, Parse, folder_paths, `n
{
Menu copy_files, Add, %A_LoopField%, copy_files
Menu move_files, Add, %A_LoopField%, move_files
}
Loop, Parse, folder_paths_to_loop, `n
{
Loop, Files, %A_LoopField%\*, F
{
extensions := "lnk,"
if A_LoopFileExt in %extensions%
{
FileGetShortcut, %A_LoopFileFullPath%, shortcutTargetPath
If( InStr( FileExist(shortcutTargetPath), "D") )
{
SplitPath, A_LoopFileLongPath, , , , OutNameNoExt
Menu copy_files, Add, %OutNameNoExt% `t[%shortcutTargetPath%], copy_files
Menu move_files, Add, %OutNameNoExt% `t[%shortcutTargetPath%], move_files
}
}
}
}
Gui, Show, x100 y5 w600 h%Gui_height%, SendTo
CheckAll:
Loop, %I%
GuiControl,, Ch%A_Index%, 1
GuiControl,, Ch200, 1
GuiControl,, Ch201, 0
return
UnCheckAll:
Loop, %I%
GuiControl,, Ch%A_Index%, 0
GuiControl,, Ch200, 0
GuiControl,, Ch201, 1
return
Copy:
Menu copy_files, show
return
Move:
Menu move_files, show
return
copy_files:
Gui, submit, nohide
; make sure at least 1 file is selected
n := 0
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) { ; if the control is checked
n := 1
Break
}
}
if (n = 0)
{
Msgbox Please select at least 1 file.
return
}
vTarget_Path := RegexReplace( A_ThisMenuItem, ".*\[(.+?)\].*", "$1")
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, file,, Ch%A_Index%, Text
filepath := RegexReplace( file, ".*\[(.+?)\].*", "$1")
filename := StrSplit(file, "[", " `t")[1]
; if we copy files to the same folder, add a Copy suffix
If (filepath = vTarget_Path) {
SplitPath, filename, , , OutExtension, OutNameNoExt
FileCopy, %filepath%\%filename%, %vTarget_Path%\%OutNameNoExt% - Copy.%OutExtension%, 1 ; overwrite existing files
}
Else
FileCopy, %filepath%\%filename%, %vTarget_Path%\, 1 ; overwrite existing files
}
}
Run %vTarget_Path%\
Gui, destroy
return
move_files:
; make sure at least 1 file is selected
n := 0
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) { ; if the control is checked
n := 1
Break
}
}
if (n = 0)
{
Msgbox Please select at least 1 file.
return
}
vTarget_Path := RegexReplace( A_ThisMenuItem, ".*\[(.+?)\].*", "$1")
MsgBox, 262180, Move files, Are you sure you want to move the selected file(s) to:`n`n`t%vTarget_Path%
IfMsgBox No
return
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, file,, Ch%A_Index%, Text
filepath := RegexReplace( file, ".*\[(.+?)\].*", "$1")
filename := StrSplit(file, "[", " `t")[1]
If (filepath != vTarget_Path)
FileMove, %filepath%\%filename%, %vTarget_Path%\, 1 ; overwrite existing files
}
else
{
GuiControlGet, file,, Ch%A_Index%, Text
New_Clipboard .= file . "`n" ; concatenate the outputs
}
}
Run %vTarget_Path%\
Gui, destroy
If (New_Clipboard := "")
Gui, destroy
else
ClipboardSetFiles(New_Clipboard, DropEffect := "Copy")
return
GuiClose:
Gui, Hide
return
; Press Esc to terminate the script
Esc:: ExitApp
; https://autohotkey.com/boards/viewtopic.php?p=63914#p63914
ClipboardSetFiles(FilesToSet, DropEffect := "Copy") {
; FilesToSet - list of fully qualified file pathes separated by "`n" or "`r`n"
; DropEffect - preferred drop effect, either "Copy", "Move" or "" (empty string)
Static TCS := A_IsUnicode ? 2 : 1 ; size of a TCHAR
Static PreferredDropEffect := DllCall("RegisterClipboardFormat", "Str", "Preferred DropEffect")
Static DropEffects := {1: 1, 2: 2, Copy: 1, Move: 2}
; Count files and total string length
TotalLength := 0
FileArray := []
Loop, Parse, FilesToSet, `n, `r
{
If (Length := StrLen(A_LoopField))
FileArray.Push({Path: A_LoopField, Len: Length + 1})
TotalLength += Length
}
FileCount := FileArray.Length()
If !(FileCount && TotalLength)
Return False
; Add files to the clipboard
If DllCall("OpenClipboard", "Ptr", A_ScriptHwnd) && DllCall("EmptyClipboard") {
; HDROP format
; 0x42 = GMEM_MOVEABLE (0x02) | GMEM_ZEROINIT (0x40)
hDrop := DllCall("GlobalAlloc", "UInt", 0x42, "UInt", 20 + (TotalLength + FileCount + 1) * TCS, "UPtr")
pDrop := DllCall("GlobalLock", "Ptr" , hDrop)
Offset := 20
NumPut(Offset, pDrop + 0, "UInt") ; DROPFILES.pFiles = offset of file list
NumPut(!!A_IsUnicode, pDrop + 16, "UInt") ; DROPFILES.fWide = 0 --> ANSI, fWide = 1 --> Unicode
For Each, File In FileArray
Offset += StrPut(File.Path, pDrop + Offset, File.Len) * TCS
DllCall("GlobalUnlock", "Ptr", hDrop)
DllCall("SetClipboardData","UInt", 0x0F, "UPtr", hDrop) ; 0x0F = CF_HDROP
; Preferred DropEffect format
If (DropEffect := DropEffects[DropEffect]) {
; Write Preferred DropEffect structure to clipboard to switch between copy/cut operations
; 0x42 = GMEM_MOVEABLE (0x02) | GMEM_ZEROINIT (0x40)
hMem := DllCall("GlobalAlloc", "UInt", 0x42, "UInt", 4, "UPtr")
pMem := DllCall("GlobalLock", "Ptr", hMem)
NumPut(DropEffect, pMem + 0, "UChar")
DllCall("GlobalUnlock", "Ptr", hMem)
DllCall("SetClipboardData", "UInt", PreferredDropEffect, "Ptr", hMem)
}
DllCall("CloseClipboard")
Return True
}
Return False
}
Re: Improved SendTo dialog
Hi all,
While the previous solution is very good, I still want to have as few actions as possible. So I changed the code to the following:
- user selects 1 or more files in either Windows Explorer, either the Desktop. Selecting 0 files is allowed too, then you treat all files.
- user presses the Menu key (AppsKey) in either Windows Explorer, either the Desktop
- the userform is shown, listing the files/folders that were selected
- same as before, copy or move a selection of files
Additionally, the code can treat environment variables to shorten paths. I use %HO% to point to the folder: "D:\OneDrive\OneDrive - Aexis NV"
So this is honoured to, both in contracting long OneDrive paths to %HO% as well as translating again %HO% to OneDrive at the time of copying/moving files/folders.
Ctrl-c and Ctrl-x are not captured anymore in the sense that clipboard changes are not monitored by the script below.
I will keep this version of the code but it is still not fully optimized I think. In the end, I just want to:
- select 1 or more files in either Windows Explorer, either the Desktop
- hit the Menu key
- hit the button "Copy" or "Move" and select the target location. No other logic is needed. GEV: I do admire your first code a lot, though !
In essence, a simple ListView of target paths will do. A left-mouse click can be "Move files", a right-mouse click "Copy files". Or something like that. Maybe multi-select will be allowed to copy to multiple target folders. I will probably not show the source files anymore in the userform to conserve space.
To be continued
While the previous solution is very good, I still want to have as few actions as possible. So I changed the code to the following:
- user selects 1 or more files in either Windows Explorer, either the Desktop. Selecting 0 files is allowed too, then you treat all files.
- user presses the Menu key (AppsKey) in either Windows Explorer, either the Desktop
- the userform is shown, listing the files/folders that were selected
- same as before, copy or move a selection of files
Additionally, the code can treat environment variables to shorten paths. I use %HO% to point to the folder: "D:\OneDrive\OneDrive - Aexis NV"
So this is honoured to, both in contracting long OneDrive paths to %HO% as well as translating again %HO% to OneDrive at the time of copying/moving files/folders.
Ctrl-c and Ctrl-x are not captured anymore in the sense that clipboard changes are not monitored by the script below.
I will keep this version of the code but it is still not fully optimized I think. In the end, I just want to:
- select 1 or more files in either Windows Explorer, either the Desktop
- hit the Menu key
- hit the button "Copy" or "Move" and select the target location. No other logic is needed. GEV: I do admire your first code a lot, though !
In essence, a simple ListView of target paths will do. A left-mouse click can be "Move files", a right-mouse click "Copy files". Or something like that. Maybe multi-select will be allowed to copy to multiple target folders. I will probably not show the source files anymore in the userform to conserve space.
To be continued
Code: Select all
#SingleInstance Force
; Create a GUI with checkboxes to save the path of the last copied files and
; copy/move selected items to other directories shown in a Menu:
; Add in this list the path of the directories
folder_paths =
(
Desktop `t[%A_Desktop%]
)
; My Documents `t[%A_MyDocuments%]
; Add in this list the path of the directories that contain shortcuts.
; The targeted directories of the shortcuts are used in the script too.
folder_paths_to_loop =
(
%HO%\........\Shortcuts & backups\COPY_CUT
)
; Press the Menu key to show the Gui if it's hidden
; ; ; AppsKey:: Gui, Show
; or If the command in the above function is commented out
AppsKey::
Menu copy_files, UseErrorLevel
Menu move_files, UseErrorLevel
Menu copy_files, DeleteAll
Menu move_files, DeleteAll
Menu copy_files, UseErrorLevel, OFF
Menu move_files, UseErrorLevel, OFF
; Create the GUI
Gui, destroy
Gui, Color, ControlColor, Black
Gui, Font, CDefault, Lucida Console
Gui, Add, Button, x30 y5 w100 h26 gMove, Move
Gui, Add, Button, x230 y5 w100 h26 gCopy, Copy
Gui, Add, CheckBox, x20 y50 vCh200 gCheckAll cYellow, Select All
Gui, Add, CheckBox, x20 y75 vCh201 gUnCheckAll cYellow, De-Select All
; retrieve the selection of the user: either files/folders, either the path in the File Explorer
v =
v := GetSelectedFileFolderNames_UnderCursor()
if !v
{
v := GetSelectedFileFolderNames_FolderYouSee()
if !v
return
}
Loop, Parse, v, `n
{
y_pos := 100 + (A_Index * 25)
; Gui, Add, CheckBox, x20 y%y_pos% vCh%A_Index% cYellow, %A_LoopField%
SplitPath, A_LoopField, filename, path
path := InsertEnvVars(path)
Gui, Add, CheckBox, x20 y%y_pos% vCh%A_Index% cYellow, %filename% `t[%path%]
I := A_Index ; number of copied files
}
Gui_height := 125+I*25
GoSub CheckAll
; Sleep 1000
; Create the Menu
Loop, Parse, folder_paths, `n
{
Menu copy_files, Add, %A_LoopField%, copy_files
Menu move_files, Add, %A_LoopField%, move_files
}
Loop, Parse, folder_paths_to_loop, `n
{
Loop, Files, % ReplaceEnvVars(A_LoopField) . "\*", F
{
extensions := "lnk,"
if A_LoopFileExt in %extensions%
{
FileGetShortcut, %A_LoopFileFullPath%, shortcutTargetPath
If( InStr( FileExist(shortcutTargetPath), "D") )
{
SplitPath, A_LoopFileLongPath, , , , OutNameNoExt
vFolder_Short := InsertEnvVars(shortcutTargetPath)
Menu copy_files, Add, %OutNameNoExt% `t[%vFolder_Short%], copy_files
Menu move_files, Add, %OutNameNoExt% `t[%vFolder_Short%], move_files
}
}
}
}
Gui, Show, x100 y5 w600 h%Gui_height%, SendTo
CheckAll:
Loop, %I%
GuiControl,, Ch%A_Index%, 1
GuiControl,, Ch200, 1
GuiControl,, Ch201, 0
return
UnCheckAll:
Loop, %I%
GuiControl,, Ch%A_Index%, 0
GuiControl,, Ch200, 0
GuiControl,, Ch201, 1
return
Copy:
Menu copy_files, show
return
Move:
Menu move_files, show
return
copy_files:
Gui, submit, nohide
; make sure at least 1 file is selected
n := 0
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) { ; if the control is checked
n := 1
Break
}
}
if (n = 0)
{
Msgbox Please select at least 1 file.
return
}
vTarget_Path := RegexReplace( A_ThisMenuItem, ".*\[(.+?)\].*", "$1")
vTarget_Path := ReplaceEnvVars(vTarget_Path)
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, file,, Ch%A_Index%, Text
filepath := RegexReplace( file, ".*\[(.+?)\].*", "$1")
filepath := ReplaceEnvVars(filepath)
filename := StrSplit(file, "[", " `t")[1]
; if we copy files to the same folder, add a Copy suffix
If (filepath = vTarget_Path)
{
SplitPath, filename, , , OutExtension, OutNameNoExt
FileCopy, %filepath%\%filename%, %vTarget_Path%\%OutNameNoExt% - Copy.%OutExtension%, 1 ; overwrite existing files
}
Else
{
vFullName = %filepath%\%filename%
If( InStr( FileExist(vFullName), "D") )
FileCopyDir, %vFullName%, %vTarget_Path%\%filename%, 1 ; overwrite existing files
Else
FileCopy, %vFullName%, %vTarget_Path%, 1 ; overwrite existing files
}
}
}
; Run %vTarget_Path%\
Gui, destroy
return
move_files:
; make sure at least 1 file is selected
n := 0
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) { ; if the control is checked
n := 1
Break
}
}
if (n = 0)
{
Msgbox Please select at least 1 file.
return
}
vTarget_Path := RegexReplace( A_ThisMenuItem, ".*\[(.+?)\].*", "$1")
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, file,, Ch%A_Index%, Text
filepath := RegexReplace( file, ".*\[(.+?)\].*", "$1")
filepath := ReplaceEnvVars(filepath)
filename := StrSplit(file, "[", " `t")[1]
If (filepath != vTarget_Path)
{
vFullName = %filepath%\%filename%
If( InStr( FileExist(vFullName), "D") )
FileMoveDir, %filepath%\%filename%, %vTarget_Path%\%filename%, 1 ; overwrite existing files
Else
FileMove, %filepath%\%filename%, %vTarget_Path%, 1 ; overwrite existing files
}
}
}
; Run %vTarget_Path%\
Gui, destroy
GuiClose:
Gui, Hide
return
; Press Esc to terminate the script
Esc:: ExitApp
ExpandEnvVars(sEV)
{
VarSetCapacity(dest, 2000)
DllCall("ExpandEnvironmentStrings", "str", sEV, "str", dest, int, 1999, "Cdecl int")
return dest
}
return
ReplaceEnvVars(sLocation)
{
if ( InStr( sLocation, "%HO%", false ) > 0 )
sLocation := StrReplace(sLocation, "%HO%", ExpandEnvVars("%HO%"))
return sLocation
}
return
InsertEnvVars(sLocation)
{
if ( InStr( sLocation, ExpandEnvVars("%HO%"), false ) > 0 )
sLocation := StrReplace(sLocation, ExpandEnvVars("%HO%"), "%HO%")
return sLocation
}
return
GetSelectedFileFolderNames_UnderCursor()
{
ToReturn =
hwnd := hwnd ? hwnd : WinExist("A")
WinGetClass class, ahk_id %hwnd%
if (class="CabinetWClass" or class="ExploreWClass")
{
for window in ComObjCreate("Shell.Application").Windows
if (window.hwnd==hwnd)
{
sel := window.Document.SelectedItems
for item in sel
{
v := % item.path
ToReturn .= v "`n"
}
}
}
else
{
files:={}
sel:=""
if (class="Progman" or class="WorkerW")
FolderPath = %A_Desktop%
else if WinActive("ahk_class CabinetWClass")
; http://ahkscript.org/boards/viewtopic.php?p=28751#p28751
for window in ComObjCreate("Shell.Application").Windows
try FolderPath := window.Document.Folder.Self.Path
ControlGet, win, HWND,, SysListView321, A
ControlGet, sel, List, Selected Col1,,ahk_id %win%
Loop, parse, sel, `n, `r
files.push(A_LoopField)
for each, file in files
{
FileGetAttrib, FileAttrib, %FolderPath%\%file%
If InStr(FileAttrib, "D") ; a DIRECTORY
{
Loop, %FolderPath%\%file%, 2,0 ; only folders
{
StringReplace, FileFullPath, A_LoopFileFullPath, :\\ ,:\
; MsgBox, DIRECTORY: "%FileFullPath%"
v = %FileFullPath%
ToReturn .= v "`n"
}
}
else
{
Loop, %FolderPath%\%file%.*
{
; MsgBox, FILE: "%A_LoopFileFullPath%"
v := % A_LoopFileFullPath
ToReturn .= v "`n"
}
}
}
}
ToReturn := Trim(ToReturn,"`n")
return ToReturn
}
GetSelectedFileFolderNames_FolderYouSee()
{
ToReturn =
; WinGetClass, class, A
hwnd := hwnd ? hwnd : WinExist("A")
WinGetClass class, ahk_id %hwnd%
if (class="CabinetWClass" or class="ExploreWClass")
{
ControlGetText, currentpath, ToolbarWindow323, ahk_class %class%
StringTrimLeft, currentpath, currentpath, 9
if( SubStr( currentpath, 0, 1) == "\")
currentpath := SubStr(currentpath, 1, StrLen( currentpath ) - 1 )
ToReturn .= currentpath "`n"
ToReturn := Trim(ToReturn,"`n")
Return ToReturn
}
else if (class="Progman" or class="WorkerW")
{
currentpath = %A_Desktop%
ToReturn .= currentpath "`n"
ToReturn := Trim(ToReturn,"`n")
Return ToReturn
}
Return
}
Re: Improved SendTo dialog
You can compile such a script
and add it to the explorer context menu.
_register Copy_Move_Files_To.reg
Replace
D:\\Scripts\\EXPLORER\\Kontextmenue\\Copy_Move_Files\\Copy_Move_Files_To.exe
with the path of your compiled script.
_unregister Copy_Move_Files_To.ahk
or define a shortcut in your main script to run the script
or create a shortcut of the script on your desktop and assign a custom combination in its properties.
Code: Select all
#NoEnv
#SingleInstance Ignore
If !WinActive("ahk_exe explorer.exe")
ExitApp
WinGetActiveTitle, WinTitle
target_folders =
(
%A_Desktop%
%A_MyDocuments%
D:\my folder\subfolder1
)
Loop, Parse, target_folders, `n
If !FileExist(A_LoopField)
FileCreateDir, %A_LoopField%
Gui, destroy
Gui, Color, ControlColor, Black
Gui, Font, CDefault, Lucida Console
Gui, Add, Button, x30 y5 w100 h26 gCopy, Copy
Gui, Add, Button, x230 y5 w100 h26 gMove, Move
Gui, Add, CheckBox, x20 y50 vCh200 gCheckAll cYellow, Select All
Gui, Add, CheckBox, x20 y75 vCh201 gUnCheckAll cYellow, De-Select All
Loop, Parse, target_folders, `n, `r
{
y_pos := 100 + (A_Index * 25)
Gui, Add, CheckBox, x20 y%y_pos% vCh%A_Index% cYellow, %A_LoopField%
I := A_Index ; number of target_folders
}
Gui_height := 125+I*25
Gui, Show, x5 y5 w400 h%Gui_height%, SendTo
return
CheckAll:
Loop, %I%
GuiControl,, Ch%A_Index%, 1
GuiControl,, Ch200, 1
GuiControl,, Ch201, 0
return
UnCheckAll:
Loop, %I%
GuiControl,, Ch%A_Index%, 0
GuiControl,, Ch200, 0
GuiControl,, Ch201, 1
return
Copy:
Gui, submit
Activate(WinTitle " ahk_exe explorer.exe")
Selection := Explorer_GetSelection()
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, folder,, Ch%A_Index%, Text
{
If !WinExist(folder " ahk_exe explorer.exe")
Run %folder%
Loop, Parse, Selection, `n
{
If InStr(FileExist(A_LoopField), "D")
{
SplitPath, A_LoopField, SourceFolderName
FileCopyDir, %A_LoopField%, %folder%\%SourceFolderName%, 1
}
else
FileCopy, %A_LoopField%, %folder%\, 1
}
}
; Sleep, 500
}
}
ExitApp
return
Move:
Gui, submit
Activate(WinTitle " ahk_exe explorer.exe")
Selection := Explorer_GetSelection()
Loop %I%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, folder,, Ch%A_Index%, Text
MsgBox, 262180, Move Files, Are you sure you want to move the selected files to`n`n"%folder%"?
IfMsgBox No
ExitApp
If !WinExist(folder " ahk_exe explorer.exe")
Run %folder%
Loop, Parse, Selection, `n
{
If InStr(FileExist(A_LoopField), "D")
{
SplitPath, A_LoopField, SourceFolderName
FileMoveDir, %A_LoopField%, %folder%\%SourceFolderName%, 1
}
else
FileMove, %A_LoopField%, %folder%\, 1
}
ExitApp ; you can move the selected items in only one directory
}
}
return
GuiClose:
ExitApp
return
Activate(title){
WinActivate %title%
WinWaitActive %title%, , 2
If ErrorLevel
{
MsgBox '%title%' not found.`n`nExiting script...
ExitApp
}
}
; https://www.autohotkey.com/boards/viewtopic.php?f=76&t=60403&p=255273#p255256
Explorer_GetSelection(){
WinGetClass, winClass, % "ahk_id" . hWnd := WinExist("A") ; %
if !(winClass ~="Progman|WorkerW|(Cabinet|Explore)WClass")
Return
shellWindows := ComObjCreate("Shell.Application").Windows
if (winClass ~= "Progman|WorkerW")
shellFolderView := shellWindows.FindWindowSW(0, 0, SWC_DESKTOP := 8, 0, SWFO_NEEDDISPATCH := 1).Document
else {
for window in shellWindows
try if (hWnd = window.HWND) && (shellFolderView := window.Document)
break
}
for item in shellFolderView.SelectedItems
result .= (result = "" ? "" : "`n") . item.Path
if !result
result := shellFolderView.Folder.Self.Path
Return result
}
_register Copy_Move_Files_To.reg
Code: Select all
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\AllFilesystemObjects\shell\Copy_Move selected files to ...]
@="Copy_Move selected files to ..."
"Icon"="C:\\WINDOWS\\System32\\SHELL32.dll,68"
"Position"="Top"
[HKEY_CLASSES_ROOT\AllFilesystemObjects\shell\Copy_Move selected files to ...\command]
@="\"D:\\Scripts\\EXPLORER\\Kontextmenue\\Copy_Move_Files\\Copy_Move_Files_To.exe\" \"%1\""
[HKEY_CLASSES_ROOT\Directory\Background\Shell\Copy_Move all files to ...]
"MUIVerb"="Copy_Move all files to ..."
"Icon"="C:\\WINDOWS\\System32\\SHELL32.dll,68"
"Position"="Top"
[HKEY_CLASSES_ROOT\Directory\Background\Shell\Copy_Move all files to ...\command]
@="\"D:\\Scripts\\EXPLORER\\Kontextmenue\\Copy_Move_Files\\Copy_Move_Files_To.exe\" \"%W\""
D:\\Scripts\\EXPLORER\\Kontextmenue\\Copy_Move_Files\\Copy_Move_Files_To.exe
with the path of your compiled script.
_unregister Copy_Move_Files_To.ahk
Code: Select all
RegDelete, HKEY_CLASSES_ROOT, AllFilesystemObjects\shell\Copy_Move selected files to ...
RegDelete, HKEY_CLASSES_ROOT, Directory\Background\Shell\Copy_Move all files to ...
or create a shortcut of the script on your desktop and assign a custom combination in its properties.
Re: Improved SendTo dialog
Incredible ! That's a very neat idea
I will test this soon, I first need to compile the AHK script.
On my work laptop I cannot do it, so need to use a different PC.
I will test this soon, I first need to compile the AHK script.
On my work laptop I cannot do it, so need to use a different PC.
Re: Improved SendTo dialog
Hi,
After some time, coming back with my final approach and script.
Select the files / folders to be copied, press F6.
A ListView will appear with all folders as the target of shortcuts that are stored in a certain dedicated folder.
Then in the ListView, right-click a line and the files/folders will be moved to the selected folder. Double-click a line and the files/folders will be copied to the selected folder.
Here's the code, only in the beginning you should make some changes. %HO% is an environment variable on my PC and points to D:\OneDrive\..., it's the root directory where many of my folders and files reside.
Thanks again GEV !
After some time, coming back with my final approach and script.
Select the files / folders to be copied, press F6.
A ListView will appear with all folders as the target of shortcuts that are stored in a certain dedicated folder.
Then in the ListView, right-click a line and the files/folders will be moved to the selected folder. Double-click a line and the files/folders will be copied to the selected folder.
Here's the code, only in the beginning you should make some changes. %HO% is an environment variable on my PC and points to D:\OneDrive\..., it's the root directory where many of my folders and files reside.
Thanks again GEV !
Code: Select all
#SingleInstance Force
F6::
{
; Create the ListView with 3 columns: Nr, Long Name, Short name
Gui, Destroy
Gui, Add, ListView, vMyListView w600 gMyListView AltSubmit -Multi, Nr|Long|Short
Gui, +Resize +ToolWindow +Border
; Add in this list the path of the directories
folder_paths =
(
Desktop`t%A_Desktop%
)
; Add in this list the path of the directories that contain shortcuts.
; The targeted directories of the shortcuts are used in the script too.
folder_paths_to_loop =
(
%HO%\Wim\COPY_CUT
)
; PART 1: retrieve the selection of files
; retrieve the selection of the user: either files/folders, either the path in the File Explorer
v =
v := GetSelectedFileFolderNames_UnderCursor()
if !v
{
v := GetSelectedFileFolderNames_FolderYouSee()
if !v
return
}
Loop, Parse, v, `n
{
SplitPath, A_LoopField, filename, path
path := InsertEnvVars(path)
Gui, Add, CheckBox, Checked Hidden x20 vCh%A_Index%, %filename% `t[%path%]
J := A_Index ; number of selected files
}
; PART 2: list all target paths
i = 0
Loop, Parse, folder_paths, `n
{
i++
MyArray := StrSplit( A_LoopField, "`t" )
LV_Add(, i, MyArray[1], MyArray[2] )
}
Loop, Parse, folder_paths_to_loop, `n
{
Loop, Files, % ReplaceEnvVars(A_LoopField) . "\*", F
{
extensions := "lnk,"
if A_LoopFileExt in %extensions%
{
FileGetShortcut, %A_LoopFileFullPath%, shortcutTargetPath
If( InStr( FileExist(shortcutTargetPath), "D") )
{
SplitPath, A_LoopFileLongPath, , , , OutNameNoExt
vFolder_Short := InsertEnvVars(shortcutTargetPath)
i++
LV_Add(, i, OutNameNoExt, vFolder_Short )
}
}
}
}
LV_ModifyCol() ; Auto-size each column to fit its contents
LV_ModifyCol(1, "Integer") ; For sorting purposes, indicate that column 1 is an integer
hoogte := 20 * i
Gui, Show, h%hoogte%, Copy | Move to...
return
GUISize:
width:=A_GuiWidth-15
height:=A_GuiHeight-15
guicontrol, move, MyListView, w%width% h%height%
return
MyListView:
Gui, submit, nohide
LV_GetText(shortcut, A_EventInfo, 3)
; RIGHTCLICK MEANS MOVE THE SELECTED FILES / FOLDERS
if A_GuiEvent = RightClick
{
; make sure at least 1 file is selected
n := 0
Loop %J%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) { ; if the control is checked
n := 1
Break
}
}
if (n = 0)
{
Msgbox Please select at least 1 file.
return
}
vTarget_Path := RegexReplace( shortcut, ".*\[(.+?)\].*", "$1")
Loop %J%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, file,, Ch%A_Index%, Text
filepath := RegexReplace( file, ".*\[(.+?)\].*", "$1")
filepath := ReplaceEnvVars(filepath)
filename := StrSplit(file, "[", " `t")[1]
If (filepath != vTarget_Path)
{
vFullName = %filepath%\%filename%
If( InStr( FileExist(vFullName), "D") )
FileMoveDir, %filepath%\%filename%, %vTarget_Path%\%filename%, 1 ; overwrite existing files
Else
FileMove, %filepath%\%filename%, %vTarget_Path%, 1 ; overwrite existing files
}
}
}
Gui, Destroy
return
}
; DOUBLECLICK MEANS COPY THE SELECTED FILES / FOLDERS
else if A_GuiEvent = DoubleClick
{
; make sure at least 1 file is selected
n := 0
Loop %J%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) { ; if the control is checked
n := 1
Break
}
}
if (n = 0)
{
Msgbox Please select at least 1 file.
return
}
vTarget_Path := RegexReplace( shortcut, ".*\[(.+?)\].*", "$1")
vTarget_Path := ReplaceEnvVars(vTarget_Path)
Loop %J%
{
GuiControlGet, checked,, Ch%A_Index%, Value
If (checked = 1) ; if the control is checked
{
GuiControlGet, file,, Ch%A_Index%, Text
filepath := RegexReplace( file, ".*\[(.+?)\].*", "$1")
filepath := ReplaceEnvVars(filepath)
filename := StrSplit(file, "[", " `t")[1]
; if we copy files to the same folder, add a Copy suffix
If (filepath = vTarget_Path)
{
SplitPath, filename, , , OutExtension, OutNameNoExt
FileCopy, %filepath%\%filename%, %vTarget_Path%\%OutNameNoExt% - Copy.%OutExtension%, 1 ; overwrite existing files
}
Else
{
vFullName = %filepath%\%filename%
If( InStr( FileExist(vFullName), "D") )
FileCopyDir, %vFullName%, %vTarget_Path%\%filename%, 1 ; overwrite existing files
Else
FileCopy, %vFullName%, %vTarget_Path%, 1 ; overwrite existing files
}
}
}
Gui, Destroy
return
}
return
}
ExpandEnvVars(sEV)
{
VarSetCapacity(dest, 2000)
DllCall("ExpandEnvironmentStrings", "str", sEV, "str", dest, int, 1999, "Cdecl int")
return dest
}
return
ReplaceEnvVars(sLocation)
{
if ( InStr( sLocation, "%HO%", false ) > 0 )
sLocation := StrReplace(sLocation, "%HO%", ExpandEnvVars("%HO%"))
return sLocation
}
return
InsertEnvVars(sLocation)
{
if ( InStr( sLocation, ExpandEnvVars("%HO%"), false ) > 0 )
sLocation := StrReplace(sLocation, ExpandEnvVars("%HO%"), "%HO%")
return sLocation
}
return
GetSelectedFileFolderNames_UnderCursor()
{
ToReturn =
hwnd := hwnd ? hwnd : WinExist("A")
WinGetClass class, ahk_id %hwnd%
if (class="CabinetWClass" or class="ExploreWClass")
{
for window in ComObjCreate("Shell.Application").Windows
if (window.hwnd==hwnd)
{
sel := window.Document.SelectedItems
for item in sel
{
v := % item.path
ToReturn .= v "`n"
}
}
}
else
{
files:={}
sel:=""
if (class="Progman" or class="WorkerW")
FolderPath = %A_Desktop%
else if WinActive("ahk_class CabinetWClass")
; http://ahkscript.org/boards/viewtopic.php?p=28751#p28751
for window in ComObjCreate("Shell.Application").Windows
try FolderPath := window.Document.Folder.Self.Path
ControlGet, win, HWND,, SysListView321, A
ControlGet, sel, List, Selected Col1,,ahk_id %win%
Loop, parse, sel, `n, `r
files.push(A_LoopField)
for each, file in files
{
FileGetAttrib, FileAttrib, %FolderPath%\%file%
If InStr(FileAttrib, "D") ; a DIRECTORY
{
Loop, %FolderPath%\%file%, 2,0 ; only folders
{
StringReplace, FileFullPath, A_LoopFileFullPath, :\\ ,:\
v = %FileFullPath%
ToReturn .= v "`n"
}
}
else
{
Loop, %FolderPath%\%file%.*
{
v := % A_LoopFileFullPath
ToReturn .= v "`n"
}
}
}
}
ToReturn := Trim(ToReturn,"`n")
return ToReturn
}
GetSelectedFileFolderNames_FolderYouSee()
{
ToReturn =
; WinGetClass, class, A
hwnd := hwnd ? hwnd : WinExist("A")
WinGetClass class, ahk_id %hwnd%
if (class="CabinetWClass" or class="ExploreWClass")
{
ControlGetText, currentpath, ToolbarWindow323, ahk_class %class%
StringTrimLeft, currentpath, currentpath, 9
if( SubStr( currentpath, 0, 1) == "\")
currentpath := SubStr(currentpath, 1, StrLen( currentpath ) - 1 )
ToReturn .= currentpath "`n"
ToReturn := Trim(ToReturn,"`n")
Return ToReturn
}
else if (class="Progman" or class="WorkerW")
{
currentpath = %A_Desktop%
ToReturn .= currentpath "`n"
ToReturn := Trim(ToReturn,"`n")
Return ToReturn
}
Return
}
Who is online
Users browsing this forum: Assquatch23, Descolada, Google [Bot] and 348 guests