Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Explorer Context Menus (with sub-menus)


  • Please log in to reply
7 replies to this topic
TheArkyTekt
  • Members
  • 9 posts
  • Last active: Feb 06 2017 12:29 PM
  • Joined: 22 Apr 2013

NOTE: This most recent update messes with the AutoHotKey Context Menu.  I've made it collapse into a sub-menu.  When you perform the REMOVE function to put things back, you won't see the AHK context menus until you restart.  Not sure why, but that's what happens.

 

There is lots of registry editing to be done here.  I've included some VBS files for easily automating the process of merging the multiple REG files.

 

The AutoHotKey part comes in when you select multiple items, and what explorer.exe tries to do.  In a nutshell, you get one instance per item selected of your chosen command.  And for some reason, the #SingleInstance Force/Ignore directive doesn't work so well when the AHK script is compiled.  Thanks to some users on this forum, I've been able to combine their scripts to make a somewhat easy method for cleaning up your context menus.  I use the AHK scirpt to pass certain parameters to the programs, and to gather the list of selected files in the explorer window, making it easier to pass all selected files to your command line.

 

Credits:

- emmanuel d - ForceSingleInstance.ahk
- Rapte_Of_Suzaku - GetWindowFileList.ahk
 

Keep in mind that many of the entries that add / remove / reset registry values are unique to the apps that I use, but I'm sure many people will find those apps useful anyways!  Just be sure to look at the reg files in the following folders:

 

CustomReg

ToggleCMH

 

... and edit them according to your needs.  Please edit BOTH the "clean" and "reset" files.  Resetting an entry that shouldn't exist in your registry could be problematic ;-)

 

If anyone finds this useful I'd sure like to hear about it.

 

Cheers!

 

Sendspace Link: http://www.sendspace.com/file/n5qx73

 

1) Create C:\_APPS_\

2) Place sendspace file there

3) Extract "here"

4) play and have fun

 

NOTE: You can edit the REG files with ";" to comment out lines to custominze.  If you're really brave you can also add your own context menus.  Please note I didn't bother trying the script as an AHK file.  I just compile and use with the reg entries.


Edited by TheArkyTekt, 12 January 2014 - 01:41 AM.


Skrell
  • Members
  • 384 posts
  • Last active: Jul 07 2016 05:03 PM
  • Joined: 23 Aug 2011

After reading your description, i'm still not sure what your script does.  Can you please post pics?



TheArkyTekt
  • Members
  • 9 posts
  • Last active: Feb 06 2017 12:29 PM
  • Joined: 22 Apr 2013

I'll post a pic, but please be aware the context menu editing is done in the registry only.

 

The script comes in when trying to handle custom menus and the associated commands.  Particularly when selecting multiple items (that gets a bit more tricky).  A fluent C++ programmer has no use for this, but those of us who are lesser can use this script to handle the output of a context menu command when multiple items are selected, and the benefit is that you won't get a separate instance for every item selected ... you only get one instance when using this script (compiled).

 

In addition, when selecting multiple items, my script puts all the files / folders selected into this format:

 

"item" "item" "item" ....

 

... which is necessary for most programs when using the command line.

 

Here's a pic:

 

352e8547478969b4f8b38a38077f06649db5945c

 

And the other menu:

 

75f827a01af2a50c673a75ac734df744eb02745c

 

Once again, my script does not create custom context menus, it simply handles the output when selecting a custom menu entry.

 

I have included my .reg files for examples, as well as the .reg example i found on Wilders Security forum.  With these examples you can construct your own custom menus.

 

Hope this helps.



Skrell
  • Members
  • 384 posts
  • Last active: Jul 07 2016 05:03 PM
  • Joined: 23 Aug 2011

Pics aren't working.  I sort of get what you're saying.  So basically you use the reg files to make custom entries in the context menu, then upon selecting the entry your autohotkey script kicks and and does something (can you give an example?) to the files selected when the entry was clicked?



TheArkyTekt
  • Members
  • 9 posts
  • Last active: Feb 06 2017 12:29 PM
  • Joined: 22 Apr 2013

This is the main script.  The items selected are passed to the script.  In the script I count them, split them up however the destination application needs it (mostly it's "file" "file" "file") ... and then I just execute the command lines desired.  So far it's working great for me.

;
; AutoHotkey Version: 1.x
; Language:       English
; Platform:       Windows 8 Pro
; Author:         TheArkyTekt <[email protected]>
;
; Script Function:
;    Template script (you can customize this template by editing "ShellNew\Template.ahk" in your Windows folder)
;

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#Include %A_ScriptDir%\INCLUDE\

#Include ForceSingleInstance.ahk
#Include GetWindowFileList.ahk
#Include TheArkyTekt_Library.ahk

#SingleInstance off
ForceSingleInstance()

; Get Parameters - not needed when using "PathStr" variable
;Loop, %0%
;{
;    If ( StrLen(ParamList) = 0 ) {
;        ParamList := %A_Index%
;    }
;    Else {
;        ParamList := ParamList . " " . %A_Index%
;    }
;}

; Variables
Chr59 := Chr(59)
RootPath := Explorer_GetPath() ; Root path from explorer.exe selection
PathStr := Explorer_GetSelected() ; path/file names separated by semicolon (;)

; Get number of items selected
TotTok := 0
Loop, Parse, PathStr, %Chr59%
{
    TotTok := TotTok + 1
}

; *** INSERT COMMAND LINE OPERATIONS HERE ***

IfExist, C:\Program Files\7-Zip\7zFM.exe
{
    7zipGUI = C:\Program Files\7-Zip\7zFM.exe
    7zipGUI2 = C:\Program Files\7-Zip\7zG.exe
}
    
IfExist, C:\Program Files (x86)\7-Zip\7zFM.exe
{
    7zipGUI = C:\Program Files (x86)\7-Zip\7zFM.exe
    7zipGUI2 = C:\Program Files (x86)\7-Zip\7zG.exe
}

IfExist, C:\Program Files\WinRAR\WinRAR.exe
{
    WinRarGUI = C:\Program Files\WinRAR\WinRAR.exe
}

IfExist, C:\Program Files (x86)\WinRAR\WinRAR.exe
{
    WinRarGUI = C:\Program Files (x86)\WinRAR\WinRAR.exe
}
    
StartFunc:
SetWorkingDir, %RootPath%

FindStr := Chr(59) ; semicolon (;) separator
RepStr := Chr(34) . " " . Chr(34) ; used for replacing (;) with (" ")
StringReplace, PathStr, PathStr, %FindStr%, %RepStr%, All ; change separation from ; to " "
PathStr := qt(PathStr) ; put "" around string

If ( ParamList = "7-Zip Open" ) {
    Run, "%7zipGUI%" "%RootPath%"
}
    
If ( ParamList = "7-Zip Compress" ) {
    ArchiveTitle := ArchTitle(RootPath,PathStr,TotTok)
    StringReplace, PathStr2, PathStr, %RootPath%\, , All
    Run, "%7zipGUI2%" a "%ArchiveTitle%.7z" %PathStr2%
}
    
If ( ParamList = "7-Zip DecompressFolder" ) {
    ArchiveTitle := FileFromPath(noqt(PathStr))
    FolderTitle := FileTitle(PathStr)
    ExtrPath := RootPath . "\" . FolderTitle . "\"
    Run, "%7zipGUI2%" x "%ArchiveTitle%" -o"%ExtrPath%"
}
    
If ( ParamList = "7-Zip DecompressHere" ) {
    ArchiveTitle := FileFromPath(noqt(PathStr))
    Run, "%7zipGUI2%" x "%ArchiveTitle%"
}

    
If ( ParamList = "WinRAR Open" ) {
    Run, "%WinRarGUI%" "%RootPath%"
}

If ( ParamList = "WinRAR CompressRAR" ) {
    ArchiveTitle := ArchTitle(RootPath,PathStr,TotTok)
    StringReplace, PathStr2, PathStr, %RootPath%\, , All
    Run, "%WinRarGUI%" a "%ArchiveTitle%" %PathStr2%
}

If ( ParamList = "WinRAR CompressZIP" ) {
    ArchiveTitle := ArchTitle(RootPath,PathStr,TotTok)
    StringReplace, PathStr2, PathStr, %RootPath%\, , All
    Run, "%WinRarGUI%" a -afzip "%ArchiveTitle%.zip" %PathStr2%
}

If ( ParamList = "WinRAR DecompressFolder" ) {
    ArchiveTitle := FileFromPath(noqt(PathStr))
    FolderTitle := FileTitle(PathStr)
    ExtrPath := FolderTitle
    Run, "%WinRarGUI%" X "%ArchiveTitle%" * "%ExtrPath%\"
}

If ( ParamList = "WinRAR DecompressHere" ) {
    Archive := noqt(PathStr)
    FolderTitle := FileTitle(PathStr)
    ExtrPath := FolderTitle
    Run, "%WinRarGUI%" X "%Archive%" *
}

If ( ParamList = "CopyPath" ) {
    StringReplace, PathStr, PathStr, % Chr(32) . Chr(34), `r, All
    StringReplace, PathStr, PathStr, % Chr(34), , All
    Clipboard := PathStr
}

If ( ParamList = "CopyPathQT" ) {
    Clipboard := PathStr
}

; *** END COMMAND LINE OPERATIONS ***

; *** CUSTOM FUNCTIONS ***


ArchTitle(Str1,Str2,TotTok) {
    ; If only 1 item selected then return that item name.
    ; Else return root path of active window
    
    ; Str1 = RootPat
    ; Str2 = PathStr
    
    Str2 := noqt(Str2)
    Chr46 := Chr(46)
    
    If ( TotTok = 1 ) {
        FileGetAttrib, Attrib, %Str2%
        If ( InStr(Attrib,"D") > 0 ) {
            StrType := "Folder"
        }
        Else {
            StrType := "File"
        }
    }

    If ( TotTok = 1 ) {
        If ( StrType = "Folder" ) {
            Result := FileFromPath(Str2)
        }
        Else {
            Result := FileTitle(Str2)
        }
    }
    Else {
        Result := FileFromPath(Str1)
    }
    return %Result%
}

;ExitApp

Edited by TheArkyTekt, 12 January 2014 - 01:33 AM.


TheArkyTekt
  • Members
  • 9 posts
  • Last active: Feb 06 2017 12:29 PM
  • Joined: 22 Apr 2013

My INCLUDE:

; This is a library created by TheArkyTekt
;
; Posted on AutoHotKey Forum

qt(InStr)
{
    Result := Chr(34) . InStr . Chr(34)
    return %Result%
}

noqt(Str) {
    StringRight, StrR, Str, 1
    StringLeft, StrL, Str, 1
    If ( StrR = Chr(34) ) && ( StrL = Chr(34) ) {
        Result := SubStr( Str, 2, -1)
    }
    Else {
        Result := Str
    }
    return %Result%
}

FileTitle(PathStr) {
    FileName := FileFromPath(PathStr)
    StringGetPos, LastDot, FileName, ., R
    StringLeft, Result, FileName, %LastDot%
    return %Result%
}

FileFromPath(PathStr) {
    PathStr := noqt(PathStr)
    StringGetPos, LastSlash, PathStr, \, R
    PathLen := StrLen(PathStr)
    SubStrLen := PathLen - LastSlash - 1
    StringRight, Result, PathStr, %SubStrLen%
    return %Result%
}

PathToFile(PathStr) {
    PathStr := noqt(PathStr)
    StringGetPos, LastSlash, PathStr, \, R
    SubStrLen := LastSlash + 1
    StringLeft, Result, PathStr, %SubStrLen%
    return %Result%
}

INCLUDE from emmanuel d

;posted by: emmanuel d
;
; This function has been converted to a library.
;
; This script saved me countless headaches. Thanks emmanuel d!

;#SingleInstance off ; We handle instances ourselves
;ForceSingleInstance() ; force single instance ourselve

;Gui, show ,w100 h100,thegui ; show a gui to see if it activates when we open a second instance
;Return

ForceSingleInstance() {
Process, Exist,%A_ScriptName% ; this allways gets the pid from the 1 instance in the ErrorLevel
FirstInstancePID:=ErrorLevel ; store the pid of the instance
if (FirstInstancePID=DllCall("GetCurrentProcessId")) ; if the first instance is this script
return ; Return
else {
winshow,ahk_pid %FirstInstancePID% ahk_class AutoHotkeyGUI ; show the window if hidden
winactivate,ahk_pid %FirstInstancePID% ahk_class AutoHotkeyGUI ; Activate the first instance
exitapp ; we have a return for the first instance so exit the app
}
}
;GuiEscape:
;guiclose:
; Gui, hide
;return

INCLUDE from Rapte_Of_Suzaku

;posted by: Rapte_Of_Suzaku
;
; Modified by TheArkyTekt
;
; My modifications simply include outputting the list of files/paths separated by semicolons:
;
; path/file ; path/file ; path/file
;
; This made it easier for me to convert the string to:
;
; "path/file" "path/file" "path/file"
;
; I use this to pass multiple arguments to other programs/scripts.
;
; Thanks again Rapte_Of_Suzaku!

/*
Library for getting info from a specific explorer window (if window handle not specified, the currently active
window will be used). Requires AHK_L or similar. Works with the desktop. Does not currently work with save
dialogs and such.


Explorer_GetSelected(hwnd="") - paths of target window's selected items
Explorer_GetAll(hwnd="") - paths of all items in the target window's folder
Explorer_GetPath(hwnd="") - path of target window's folder

example:
F1::
path := Explorer_GetPath()
all := Explorer_GetAll()
sel := Explorer_GetSelected()
MsgBox % path
MsgBox % all
MsgBox % sel
return

Joshua A. Kinnison
2011-04-27, 16:12
*/

Explorer_GetPath(hwnd="")
{
if !(window := Explorer_GetWindow(hwnd))
return ErrorLevel := "ERROR"
if (window="desktop")
return A_Desktop
path := window.LocationURL
path := RegExReplace(path, "ftp://.*@","ftp://")
StringReplace, path, path, file:///
StringReplace, path, path, /, \, All

; thanks to polyethene
Loop
If RegExMatch(path, "i)(?<=%)[\da-f]{1,2}", hex)
StringReplace, path, path, `%%hex%, % Chr("0x" . hex), All
Else Break
return path
}
Explorer_GetAll(hwnd="")
{
return Explorer_Get(hwnd)
}
Explorer_GetSelected(hwnd="")
{
return Explorer_Get(hwnd,true)
}

Explorer_GetWindow(hwnd="")
{
; thanks to jethrow for some pointers here
WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A")
WinGetClass class, ahk_id %hwnd%

if (process!="explorer.exe")
return
if (class ~= "(Cabinet|Explore)WClass")
{
for window in ComObjCreate("Shell.Application").Windows
if (window.hwnd==hwnd)
return window
}
else if (class ~= "Progman|WorkerW")
return "desktop" ; desktop found
}

Explorer_Get(hwnd="",selection=false)
{
if !(window := Explorer_GetWindow(hwnd))
return ErrorLevel := "ERROR"
if (window="desktop")
{
ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman
if !hwWindow ; #D mode
ControlGet, hwWindow, HWND,, SysListView321, A
ControlGet, files, List, % ( selection ? "Selected":"") "Col1",,ahk_id %hwWindow%
base := SubStr(A_Desktop,0,1)=="\" ? SubStr(A_Desktop,1,-1) : A_Desktop
Loop, Parse, files, `n, `r
{
path := base "\" A_LoopField
IfExist %path% ; ignore special icons like Computer (at least for now)
{
;ret .= path "`n"
if ( StrLen(ret) = 0 ) {
ret := path
}
else {
ret := ret . ";" . path
}
}
}
}
else
{
if selection
collection := window.document.SelectedItems
else
collection := window.document.Folder.Items
for item in collection
;ret .= item.path "`n"

if ( StrLen(ret) = 0 ) {
ret := item.path
}
else {
ret := ret . ";" . item.path
}
}
;return Trim(ret,"`n")
return %ret%
}

Edited by TheArkyTekt, 12 January 2014 - 01:44 AM.


TheArkyTekt
  • Members
  • 9 posts
  • Last active: Feb 06 2017 12:29 PM
  • Joined: 22 Apr 2013

Updated my posts to include all the script code, and updated my first post to include my latest changes, but please be aware it all makes MUCH more sense in the context of the REG files.  Seeing what they do helps too.



Yaron
  • Members
  • 3 posts
  • Last active: Apr 02 2014 12:25 AM
  • Joined: 02 Apr 2014

Hello,

Thank you for the script.

 

May I ask you to have a look at the following post?

http://www.autohotke...ve-filenamexpi/

 

I'd be grateful for your help.