diff --git a/F4MiniMenu.ahk b/F4MiniMenu.ahk index 9796b20..403a509 100644 --- a/F4MiniMenu.ahk +++ b/F4MiniMenu.ahk @@ -1,9 +1,9 @@ /* Script : F4MiniMenu.ahk for Total Commander - AutoHotkey 1.1+ (Ansi and Unicode) -Version : 0.96.2 +Version : 0.97 Author : hi5 -Last update : 27 May 2019 +Last update : 30 June 2019 Purpose : Minimalistic clone of the F4 Menu program for Total Commander (open selected files in editor(s)) Source : https://github.com/hi5/F4MiniMenu @@ -13,7 +13,7 @@ Note : ; % used to resolve syntax highlighting feature bug of N++ ; ;@Ahk2Exe-SetDescription F4MiniMenu: Open files from TC -;@Ahk2Exe-SetVersion 0.96.2.0 +;@Ahk2Exe-SetVersion 0.97.0.0 ;@Ahk2Exe-SetCopyright MIT License - Copyright (c) https://github.com/hi5 ; @@ -44,7 +44,7 @@ If (TmpFileList = "") TmpFileList .= "\$$f4mtmplist$$.m3u" -F4Version:="v0.96.2" +F4Version:="v0.97" ; shared with F4TCIE #Include %A_ScriptDir%\inc\LoadSettings1.ahk @@ -94,7 +94,7 @@ Menu, tray, Add, Scan Document Templates, DocumentTemplatesScan Try Menu, tray, Icon, Scan Document Templates, shell32.dll, 172 Menu, tray, Add, -Menu, tray, Add, Exit, SaveSettings +Menu, tray, Add, Exit, ExitSettings Try Menu, tray, Icon, Exit, shell32.dll, 132 @@ -124,13 +124,13 @@ FileCopy, %F4ConfigFile%, %F4ConfigFile%.bak, 1 If (MatchList.settings.TCStart = 2) and !WinExist("ahk_class TTOTAL_CMD") { If FileExist(MatchList.settings.TCPath) - Run % MatchList.settings.TCPath ; % + Run % MatchList.settings.TCPath,,,TCOutputVarPID ; % } If (MatchList.settings.TCStart = 3) { If FileExist(MatchList.settings.TCPath) - Run % MatchList.settings.TCPath ; % + Run % MatchList.settings.TCPath,,,TCOutputVarPID ; % } ; shared with F4MM @@ -146,19 +146,26 @@ Gosub, GetAllExtensions HotKeyState:="On" Gosub, SetHotkeys -; Save Matchlist Object to XML -OnExit, SaveSettings +; Clear tmp file(s) +OnExit, ExitSettings ; End of Auto-execute section -If (Matchlist.settings.F4MMClose = 1) +If (Matchlist.settings.F4MMCloseAll = 1) { WinWaitClose, ahk_class TTOTAL_CMD ExitApp } +Else If (Matchlist.settings.F4MMClosePID = 1) + { + Sleep 5000 + WinWaitClose, ahk_pid %TCOutputVarPID% + ExitApp + } Return Process: ProcessFiles(MatchList) +MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp") Return ; Function executed by background hotkey (open directly) @@ -166,7 +173,11 @@ ProcessFiles(MatchList, SelectedEditor = "-1") { Done:=[] Stop:=0 - Files:=GetFiles() ; Get list of selected files in TC, one per line + If (MatchList.Temp.Files = "") + Files:=GetFiles() ; Get list of selected files in TC, one per line + else + Files:=MatchList.Temp.Files + MatchList.Temp.Files:="" ; Check if we possibly have selected file(s) from an archive If RegExMatch(Files,"iUm)" ArchiveExtentions ) { @@ -176,7 +187,7 @@ ProcessFiles(MatchList, SelectedEditor = "-1") Check:=Files IfNotExist, %check% ; additional check, if the file is from an archive it won't exist { ; therefore we resort to the internal TC Edit command - added for v0.51 - SendMessage 1075, 904, 0, , ahk_class TTOTAL_CMD + SendMessage 1075, 904, 0, , ahk_class TTOTAL_CMD ; Edit (Notepad) Return } } @@ -199,7 +210,7 @@ ProcessFiles(MatchList, SelectedEditor = "-1") Break open:=A_LoopField SplitPath, A_LoopField, , , OutExtension - + for k, v in MatchList { Index:=A_Index @@ -259,11 +270,25 @@ ProcessFiles(MatchList, SelectedEditor = "-1") } } } + PostMessage 1075, 524, 0, , ahk_class TTOTAL_CMD ; Unselect all (files+folders) + } + +; Get a list of extensions from selected files we can use to build filtered menu +GetExt(Files) + { + Global MatchList + Loop, parse, files, `n, `r + { + SplitPath, A_LoopField,,, OutExtension + Ext .= OutExtension "|" + } + MatchList.Temp["SelectedExtensions"]:=Trim(Ext,"|") } ; Get a list of selected files using internal TC commands (see totalcmd.inc for references) GetFiles() { + Global MatchList If WinActive("ahk_class TLister") { WinGetActiveTitle, Files @@ -285,7 +310,8 @@ GetFiles() Files:=Clipboard Clipboard:=ClipboardSave ClipboardSave:="" - PostMessage 1075, 524, 0, , ahk_class TTOTAL_CMD ; Unselect all (files+folders) +; PostMessage 1075, 524, 0, , ahk_class TTOTAL_CMD ; Unselect all (files+folders) + MatchList.Temp["Files"]:=Files Return Files } @@ -400,7 +426,7 @@ GetInput(byref parameters, byref file, byref startdir, byref execute, program) ; %f41 placeholder to alter position of filenames on the command line. ; if InStr(parameters,"%f41") - { + { parameters:=StrReplace(parameters, "%f41", file) file:="" } @@ -417,9 +443,9 @@ GetInput(byref parameters, byref file, byref startdir, byref execute, program) { Gui, AskInput:Add, Text, xp y5 , Command line parameters: Gui, AskInput:Add, Edit, xp yp+20 w400 h20 , %parameters% - } + } if (AskParameters <> 1) and (parameters <> "") - { + { Gui, AskInput:Add, Text, xp y58 , Command line parameters: Gui, AskInput:Add, Edit, xp yp+20 w400 h20 ReadOnly , %parameters% } @@ -559,26 +585,35 @@ If (InStr(BGHKey,"ESC")) Hotkey, % hk_prefix . BGHKey, Process, %HotKeyState% ; % ; MsgBox % "OpenItDirectly: " hk_prefix . BGHKey ; debug +If (MatchList.settings.FilteredHotkey <> "ERROR") and (MatchList.settings.FilteredHotkey <> "") + { + hk_prefix:="$" + TMHKey:=MatchList.settings.FilteredHotkey + StringReplace, TMHKey, TMHKey, &`;amp`;, & , All + StringReplace, TMHKey, TMHKey, &`;, &, All + If (InStr(TMHKey,"ESC")) + hk_prefix:="~" + + Hotkey, % hk_prefix . TMHKey, FilteredMenu, %HotKeyState% ; % + } + Hotkey, IfWinActive Return SaveSettings: -Gosub, SaveSetup -ExitApp +MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp") +%F4Save%("MatchList", F4ConfigFile) +FileDelete, % TmpFileList Return -SaveSetup: -If (A_ExitReason <> "Exit") ; to prevent saving it twice - { - if (MatchListStart <> MatchList) ; only save changes no need to save settings otherwise - %F4Save%("MatchList", F4ConfigFile) - } +ExitSettings: FileDelete, % TmpFileList -If (Error = 1) +If (Error = 1) ; we can't read settings so create a new clean version { FileDelete, %F4ConfigFile% Gosub, CreateNewConfig } +ExitApp Return @@ -612,11 +647,14 @@ FileAppend, F4 Esc & F4 + 30 3 - 0 c:\totalcmd\TotalCmd.exe 1 + 0 + 0 + z c:\WINDOWS\notepad.exe @@ -635,18 +673,21 @@ FileAppend, [settings] BackgroundHotkey=F4 ForegroundHotkey=Esc & F4 +FilteredHotkey= MaxFiles=30 MenuPos=3 TCPath=c:\totalcmd\TotalCmd.exe TCStart=1 -F4MMClose=0 +F4MMCloseAll=0 +F4MMClosePID=0 +FullMenu=z [1] delay=0 exe=c:\WINDOWS\notepad.exe ext=txt,xml method=Normal windowmode=1 -), F4MiniMenu.ini +), F4MiniMenu.ini, UTF-16 } Return @@ -655,21 +696,26 @@ Return DocumentTemplatesScan: If (FileExist(A_ScriptDir "\DocumentTemplates\") = "D") { + templatesExtBeforeScan:=MatchList.Settings["templatesExt"] Loop, %A_ScriptDir%\DocumentTemplates\template.* { SplitPath, A_LoopFileName, , , TemplatesOutExtension templatesExt .= TemplatesOutExtension "," } - MatchList.Settings["templatesExt"]:=Trim(templatesExt,",") - TemplatesOutExtension:="" - templatesExt:="" - %F4Save%("MatchList", F4ConfigFile) + ; only update when its has been changed + If (templatesExtBeforeScan <> Trim(templatesExt,",")) + { + MatchList.Settings["templatesExt"]:=Trim(templatesExt,",") + %F4Save%("MatchList", F4ConfigFile) + } + templatesExt:="",TemplatesOutExtension:="",templatesExtBeforeScan:="" } Return ; Includes #include %A_ScriptDir%\inc\Menu.ahk +#include %A_ScriptDir%\inc\FilteredMenu.ahk #include %A_ScriptDir%\inc\Settings.ahk #include %A_ScriptDir%\inc\Editors.ahk #include %A_ScriptDir%\inc\HelperFunctions.ahk ; shared with F4TCIE diff --git a/F4TCIE.ahk b/F4TCIE.ahk index 6edaee1..4ca93aa 100644 --- a/F4TCIE.ahk +++ b/F4TCIE.ahk @@ -26,6 +26,12 @@ Templates : Create a DocumentTemplates\ folder and place files for each templa #NoTrayIcon #NoEnv +; +;@Ahk2Exe-SetDescription F4MiniMenu: Open files from TC +;@Ahk2Exe-SetVersion 0.97.0.0 +;@Ahk2Exe-SetCopyright MIT License - Copyright (c) https://github.com/hi5 +; + SetWorkingDir, %A_ScriptDir% File=%1% ; cmd line parameter "%1" it receives from TC diff --git a/changelog.md b/changelog.md index d564c4f..2dd7aea 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ ## Changelog +* 20190622 - v0.97 + a) New option for filtered foreground menu: only show programs that match selected extensions. See Settings for setup. https://github.com/hi5/F4MiniMenu/issues/21 + b) Fix: correctly use %commander_path% in Editor listview IL_Add routine (if v.Icon isn't set) + c) Fix: Editor - Set as Default should now work correctly + d) Fix: Editor - cancel should now work more reliably by using .clone() + e) Only save settings when actually changing them e.g. no longer at each start/exit of the script * 20190607 - v0.96.2 - Fix: adding Try to all Menu, tray, icons to avoid startup error for compiled scripts and autohotkey.exe is not installed. https://www.ghisler.ch/board/viewtopic.php?p=356022#p356022 * 20190606 - v0.96.1 - Fix: adding close F4MiniMenu setting to INI version (iob.ahk) https://www.ghisler.ch/board/viewtopic.php?p=355998#p355998 * 20190527 - v0.96 @@ -18,7 +24,7 @@ d) Now use %TEMP%\$$f4mtmplist$$.m3u instead of ScriptFolder - [requested by Ovg](http://ghisler.ch/board/viewtopic.php?p=319773&sid=2e2472aec32f6906e699d095b4998ea3#319773) e) Fixed hotkeys - #12 https://github.com/hi5/F4MiniMenu/issues/12 f) You can now specify an Icon and Menu name when you configure an Editor. #17 https://github.com/hi5/F4MiniMenu/issues/17 - g) %Commander_Path% now accepted in Editor and Icon paths. + g) %Commander_Path% now accepted in Editor and Icon paths. h) Removed F4MiniMenui.ahk - to use INI simply rename/copy the (compiled) script to end with "i". * 20161023 - v0.93 OpenFile: add WinWait before WinActivate, merge request @nameanyone #10 https://github.com/hi5/F4MiniMenu/issues/10 * 20160618 - v0.92 Fix error checking on startup in case script is compiled - HT Ovg @@ -36,7 +42,7 @@ * 20130607 - v0.51 Check if selected file(s) are archived, if so bypass F4MiniMenu all together and use internal TC Edit command to open file, this will only use the file under the cursor, not all selected files. * 20130330 - v0.5 a) Process entire file list first and open per program; b) Introduced [Filelist](#filelist) method; - c) Removed "Open Mode". + c) Removed "Open Mode". * 20121117 - v0.4 Configuration GUIs, tray menu. First editor now considered default editor. * 20121111 - v0.3 Added menu for "foreground" feature - open all selected files with specific editor (its behaviour may change in future). * 20121108 - v0.2 Added 0 (zero) entry in XML as default editor. diff --git a/inc/Editors.ahk b/inc/Editors.ahk index 5c2ede5..c70cf7a 100644 --- a/inc/Editors.ahk +++ b/inc/Editors.ahk @@ -5,7 +5,7 @@ Include for F4MiniMenu.ahk */ -; This label is used when "Add new Editor" is selected in the foreground menu, +; This label is used when "Add new Editor" is selected in the foreground menu, ; we only need to set a variable and the proceed with the regular editor Gui ConfigEditorsNew: @@ -17,7 +17,7 @@ ConfigEditors: ; Variables ; Backup Object so we can use this for CANCEL -Backup:=MatchList +Backup:=MatchList.Clone() GetList:="Exe|Parameters|StartDir|WindowMode|Ext|Method|Delay|Open|Editor|Icon|Name" @@ -64,23 +64,23 @@ Sleep 100 NewEditor: If (New = 1) ; we choose "Add new Editor in foreground menu" - { - Gosub, Add - ; get list of selected files so we can set the Extensions automatically - SelectedExtensions:="" - Files:=GetFiles() - Loop, parse, Files, `n, `r + { + Gosub, Add + ; get list of selected files so we can set the Extensions automatically + SelectedExtensions:="" + Files:=GetFiles() + Loop, parse, Files, `n, `r { SplitPath, A_LoopField, , , OutExtension If OutExtension not in %SelectedExtensions% SelectedExtensions .= OutExtension "," } - SelectedExtensions:=Rtrim(SelectedExtensions,",") - GuiControl,Modify: , Ext, %SelectedExtensions% - SelectedExtensions:="" - Files:="" - } - + SelectedExtensions:=Rtrim(SelectedExtensions,",") + GuiControl,Modify: , Ext, %SelectedExtensions% + SelectedExtensions:="" + Files:="" + } + New:=0 Return @@ -95,7 +95,7 @@ Loop, % LV_GetCount() ; % { Row:=A_Index Loop, parse, GetList, | - LV_GetText(%A_LoopField%, Row, A_Index) + LV_GetText(%A_LoopField%, Row, A_Index) MatchList[Row,"Exe"]:=Exe MatchList[Row,"Parameters"]:=Parameters MatchList[Row,"StartDir"]:=StartDir @@ -116,8 +116,10 @@ Gosub, GetAllExtensions Return Cancel: +MatchList:=[] MatchList:=Backup Backup:="" +Gosub, BuildMenu Gosub, BrowseGuiClose Return @@ -128,17 +130,17 @@ Gui, Browse:Submit, NoHide SelItem := LV_GetNext() If (SelItem = 0) SelItem = 1 -LV_GetText(Ask, SelItem, 1) +LV_GetText(Ask, SelItem, 1) MsgBox, 52, Remove editor, Do you want to remove:`n%Ask%? IfMsgBox, Yes { - LV_Delete(SelItem) + LV_Delete(SelItem) MatchList.Remove(Editor) } Gosub, BuildMenu Return -; We can use the same Gui to ADD or MODIFY an editor we only need +; We can use the same Gui to ADD or MODIFY an editor we only need ; to set a variable and the proceed with the regular Modify Gui Add: @@ -153,43 +155,43 @@ Loop, parse, GetList, | If New { Delay:=0 - Method:="Normal" + Method:="Normal" WindowMode:=1 } - -; We want to modify existing entry, get info from listview and set variables for use in Gui + +; We want to modify existing entry, get info from listview and set variables for use in Gui If !New { Gui, Browse:Default Gui, Browse:Submit, NoHide SelItem := LV_GetNext() If (SelItem = 0) - SelItem = 1 + SelItem = 1 Loop, parse, GetList, | { LV_GetText(%A_LoopField%, SelItem, A_Index) } - } + } Gui, Modify:+Owner Gui, Modify:font, % dpi("s8") Gui, Modify:Add, Text, % dpi("x10 y10 w77 h18"), &Exe -Gui, Modify:Add, Edit, % dpi("x89 y8 w290 h20 vExe"), %Exe% +Gui, Modify:Add, Edit, % dpi("x89 y8 w290 h20 vExe"), %Exe% Gui, Modify:Add, Button, % dpi("x386 y8 w30 h20 gSelectExe"), >> Gui, Modify:Add, Checkbox, % dpi("x426 y8 w200 h20 vDefault"), Set as &Default - + Gui, Modify:Add, Text, % dpi("x10 yp+32 w77 h18"), &Icon Gui, Modify:Add, Edit, % dpi("x89 yp-2 w170 h20 vIcon"), %Icon% Gui, Modify:Add, Button, % dpi("x266 yp w30 h20 gSelectIcon"), >> Gui, Modify:Add, Text, % dpi("xp+41 yp+2 w60 h18"), Menu &Name Gui, Modify:Add, Edit, % dpi("xp+70 yp-2 w150 h20 vName"), %Name% - + Gui, Modify:Add, Text, % dpi("x10 yp+32 w77 h16"), Para&meters -Gui, Modify:Add, Edit, % dpi("x89 yp-2 w438 h20 vParameters"), %Parameters% - +Gui, Modify:Add, Edit, % dpi("x89 yp-2 w438 h20 vParameters"), %Parameters% + Gui, Modify:Add, Text, % dpi("x10 yp+32 w77 h16"), &Start Dir -Gui, Modify:Add, Edit, % dpi("x89 yp-2 w323 h20 vStartDir"), %StartDir% +Gui, Modify:Add, Edit, % dpi("x89 yp-2 w323 h20 vStartDir"), %StartDir% Gui, Modify:Add, Button, % dpi("xp+328 yp h20 w110 gCopyPath"), Copy path from Exe. Gui, Modify:Add, Text, % dpi("x10 yp+32 w78 h28"), &Method @@ -217,7 +219,7 @@ Gui, Modify:Add, DropDownList, % dpi("x89 yp-3 w438 h21 R3 Choose" WindowMode " ;GuiControl, Disable, Mode Gui, Modify:Add, Text, % dpi("x10 yp+32 w77 h16"), Ex&tensions -Gui, Modify:Add, Edit, % dpi("x89 yp-2 w438 h76 vExt"), %Ext% +Gui, Modify:Add, Edit, % dpi("x89 yp-2 w438 h76 vExt"), %Ext% Gui, Modify:Add, Link, % dpi("x10 yp+100 w310 h16"), F4MiniMenu %F4Version% --- More info at Github.com/hi5/F4MiniMenu @@ -231,9 +233,9 @@ Return SelectIcon: FileSelectFile, Icon, 3, , Select Icon, Icon (*.ico) if (Icon = "") - Return + Return GuiControl, Modify: ,Icon,%Icon% - + Return SelectExe: @@ -252,7 +254,7 @@ If WinActive("Editor configuration") GuiControl, Modify: ,Delay,0 GuiControl, Modify: ,Open,0 } -Else If WinActive("Settings") +Else If WinActive("Settings") { GuiControl, ,TCPath, %Exe% } @@ -269,7 +271,7 @@ ModifyButtonOK: Gui, Modify:Default Gui, Submit, NoHide If (Editor = "") ; we have a new editor - Editor:=MatchList.MaxIndex() + 1 + Editor:=MatchList.MaxIndex() + 1 MatchList[Editor,"Exe"]:=Exe MatchList[Editor,"Icon"]:=Icon @@ -296,14 +298,24 @@ MatchList[Editor,"Delay"]:=Delay MatchList[Editor,"Open"]:=Open MatchList[Editor,"Editor"]:=Editor +If Default + { + DefaultMatchEditor:=[] + DefaultMatchEditor:=MatchList[Editor] + DefaultMatchEditor["Editor"]:="" + MatchList.Remove(Editor) + MatchList.InsertAt(1,DefaultMatchEditor) + DefaultMatchEditor:="" + } + Gui, Modify:Destroy Gui, Browse:Default -If (Editor = Matchlist.MaxIndex()) +If (Editor = Matchlist.MaxIndex()) or (Default) Gosub, UpdateListview Else LV_Modify(SelItem, "",Exe,Parameters,StartDir,WindowMode,Ext,Method,Delay,Open,Editor,Icon,Name) -New:=0 +New:=0,Default:=0 Gosub, BuildMenu Return @@ -320,7 +332,7 @@ Return UpdateListview: Gui, Browse:Default -; Icon wizardry comes directly from AutoHotkey Listview documentation +; Icon wizardry comes directly from AutoHotkey Listview documentation ; It works with both Ansi & Unicode versions ; Calculate buffer size required for SHFILEINFO structure. sfi_size := A_PtrSize + 8 + (A_IsUnicode ? 680 : 340) @@ -335,61 +347,66 @@ LV_Delete() Count=0 ; Loop % MatchList.MaxIndex() ; Exe|Parameters|StartDir|WindowMode|Ext|Method|Delay|Editor|Icon|Name ; % for k, v in MatchList - { - If (k = "settings") - continue - FileName := v.Exe ; Must save it to a writable variable for use below. - If (v.Icon <> "") - FileName := StrReplace(v.Icon,"%Commander_Path%",Commander_Path) - + { + If (k = "settings") or (k = "temp") + Continue + FileName := v.Exe ; Must save it to a writable variable for use below. + If (FileName = "") + Continue + If (v.Icon <> "") + FileName := StrReplace(v.Icon,"%Commander_Path%",Commander_Path) + + If InStr(FileName,"%Commander_Path%") + FileName := StrReplace(FileName,"%Commander_Path%",Commander_Path) + ; Build a unique extension ID to avoid characters that are illegal in variable names, ; such as dashes. This unique ID method also performs better because finding an item ; in the array does not require search-loop. SplitPath, FileName,,, FileExt ; Get the file's extension. if FileExt in EXE,ICO,ANI,CUR - { + { ExtID := FileExt ; Special ID as a placeholder. IconNumber = 0 ; Flag it as not found so that these types can each have a unique icon. - } + } else ; Some other extension/file-type, so calculate its unique ID. - { - ExtID = 0 ; Initialize to handle extensions that are shorter than others. - Loop 7 ; Limit the extension to 7 characters so that it fits in a 64-bit value. - { + { + ExtID = 0 ; Initialize to handle extensions that are shorter than others. + Loop 7 ; Limit the extension to 7 characters so that it fits in a 64-bit value. + { StringMid, ExtChar, FileExt, A_Index, 1 if not ExtChar ; No more characters. - break + break ; Derive a Unique ID by assigning a different bit position to each character: ExtID := ExtID | (Asc(ExtChar) << (8 * (A_Index - 1))) - } - ; Check if this file extension already has an icon in the ImageLists. If it does, - ; several calls can be avoided and loading performance is greatly improved, - ; especially for a folder containing hundreds of files: - IconNumber := IconArray%ExtID% - } + } + ; Check if this file extension already has an icon in the ImageLists. If it does, + ; several calls can be avoided and loading performance is greatly improved, + ; especially for a folder containing hundreds of files: + IconNumber := IconArray%ExtID% + } if not IconNumber ; There is not yet any icon for this extension, so load it. - { - ; Get the high-quality small-icon associated with this file extension: - if not DllCall("Shell32\SHGetFileInfo" . (A_IsUnicode ? "W":"A"), "str", FileName - , "uint", 0, "ptr", &sfi, "uint", sfi_size, "uint", 0x101) ; 0x101 is SHGFI_ICON+SHGFI_SMALLICON - IconNumber = 9999999 ; Set it out of bounds to display a blank icon. - else ; Icon successfully loaded. - { - ; Extract the hIcon member from the structure: - hIcon := NumGet(sfi, 0) - ; Add the HICON directly to the small-icon and large-icon lists. - ; Below uses +1 to convert the returned index from zero-based to one-based: - IconNumber := DllCall("ImageList_ReplaceIcon", "ptr", ImageListID1, "int", -1, "ptr", hIcon) + 1 - DllCall("ImageList_ReplaceIcon", "ptr", ImageListID2, "int", -1, "ptr", hIcon) - ; Now that it's been copied into the ImageLists, the original should be destroyed: - DllCall("DestroyIcon", "ptr", hIcon) - ; Cache the icon to save memory and improve loading performance: - IconArray%ExtID% := IconNumber - } - } + { + ; Get the high-quality small-icon associated with this file extension: + if not DllCall("Shell32\SHGetFileInfo" . (A_IsUnicode ? "W":"A"), "str", FileName + , "uint", 0, "ptr", &sfi, "uint", sfi_size, "uint", 0x101) ; 0x101 is SHGFI_ICON+SHGFI_SMALLICON + IconNumber = 9999999 ; Set it out of bounds to display a blank icon. + else ; Icon successfully loaded. + { + ; Extract the hIcon member from the structure: + hIcon := NumGet(sfi, 0) + ; Add the HICON directly to the small-icon and large-icon lists. + ; Below uses +1 to convert the returned index from zero-based to one-based: + IconNumber := DllCall("ImageList_ReplaceIcon", "ptr", ImageListID1, "int", -1, "ptr", hIcon) + 1 + DllCall("ImageList_ReplaceIcon", "ptr", ImageListID2, "int", -1, "ptr", hIcon) + ; Now that it's been copied into the ImageLists, the original should be destroyed: + DllCall("DestroyIcon", "ptr", hIcon) + ; Cache the icon to save memory and improve loading performance: + IconArray%ExtID% := IconNumber + } + } ; Create the new row in the ListView and assign it the icon number determined above: - LV_Add("Icon" IconNumber, v.Exe, v.Parameters, v.StartDir, v.WindowMode, v.ext, v.Method, v.Delay, v.Open, A_Index, v.Icon, v.Name) + LV_Add("Icon" IconNumber, v.Exe, v.Parameters, v.StartDir, v.WindowMode, v.ext, v.Method, v.Delay, v.Open, A_Index, v.Icon, v.Name) } dpifactor:=dpi() LV_ModifyCol(1, dpifactor*250), LV_ModifyCol(2, dpifactor*70), LV_ModifyCol(3, dpifactor*70) @@ -411,7 +428,7 @@ return MoveUp: LvHandle.Move(1) ; Move selected rows up. return - + MoveDown: LvHandle.Move() ; Move selected rows down. return diff --git a/inc/FilteredMenu.ahk b/inc/FilteredMenu.ahk new file mode 100644 index 0000000..439978e --- /dev/null +++ b/inc/FilteredMenu.ahk @@ -0,0 +1,74 @@ +/* + +Foreground menu - show matching programs only based on .ext - uses lib\GetPos.ahk +Shares code with menu.ahk (building menu, AddMenuEntry + AddMenuProgramOptions labels, menuhandler) +Include for F4MiniMenu.ahk + +*/ + +FilteredMenu: +GetExt(GetFiles()) +If debug + { + debug_ext:=MatchList.Temp.SelectedExtensions + debug_files:=MatchList.Temp.Files + } +CoordMode, Menu, Client +Gosub, BuildFilteredMenu +Coord:=GetPos(MatchList.settings.MenuPos,MatchList.MaxIndex()) +Menu, %MenuName%, Show, % Coord["x"], % Coord["y"] +MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp") +Return + +; Build menu based on defined editors + +BuildFilteredMenu: +Menu, MyFilteredMenu, Add, +Menu, MyFilteredMenu, DeleteAll + +MenuName:="MyFilteredMenu" + +MatchListReference:=[] ; Object and counter below used to keep track of the orginal position in MatchList so +MenuCounter:=0 ; we select the correct editor in the filtered menu as we use A_ThisMenuItemPos in menuhandler + +for k, v in MatchList + { + If (k = "settings") or (k = "temp") + Continue ; skip settings + if RegExMatch(MatchList.Temp.SelectedExtensions,StrReplace(RegExExtensions(v.ext),",","|")) or (k = 1) + { + MenuCounter++ + ExeName:=v.exe + SplitPath, ExeName, ShortName + If (v.name <> "") + ShortName:=v.name + + If InStr(ShortName,"&") + ShortName:=MenuPadding ShortName + else + ShortName:=MenuPadding "&" ShortName + + MatchListReference[MenuCounter]:=A_Index + + If (k = 1) ; because we add a separator line we need to keep track of this + MenuCounter++ + + Gosub, AddMenuEntry + } + } + +Menu, MyFilteredMenu, Add, +Menu, MyFilteredMenu, Add, % MatchList.settings.FullMenu ? "&" MatchList.settings.FullMenu " Full menu" : " Full menu", :MyMenu +Try + Menu, MyFilteredMenu, Icon, % MatchList.settings.FullMenu ? "&" MatchList.settings.FullMenu " Full menu" : " Full menu", res\f4.ico + +Gosub, AddMenuProgramOptions + + + +If (MenuCounter = 2) ; we haven't found any matches, so just show full menu + MenuName:="MyMenu" + +MenuCounter:="" + +Return diff --git a/inc/Menu.ahk b/inc/Menu.ahk index 3dd44a2..10a13b2 100644 --- a/inc/Menu.ahk +++ b/inc/Menu.ahk @@ -1,6 +1,7 @@ /* Foreground menu - uses lib\GetPos.ahk +FilteredMenu.ahk makes use of various labels in Menu.ahk Include for F4MiniMenu.ahk */ @@ -9,6 +10,7 @@ ShowMenu: CoordMode, Menu, Client Coord:=GetPos(MatchList.settings.MenuPos,MatchList.MaxIndex()) Menu, MyMenu, Show, % Coord["x"], % Coord["y"] +MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp") Return ; Build menu based on defined editors @@ -17,9 +19,11 @@ BuildMenu: Menu, MyMenu, Add, Menu, MyMenu, DeleteAll +MenuName:="MyMenu" + for k, v in MatchList { - If (k = "settings") + If (k = "settings") or (k = "temp") Continue ; skip settings ExeName:=v.exe SplitPath, ExeName, ShortName @@ -30,36 +34,12 @@ for k, v in MatchList ShortName:=MenuPadding ShortName else ShortName:=MenuPadding "&" ShortName - Menu, MyMenu, Add, %ShortName%, MenuHandler - Try - { - If (v.icon = "") - Menu, MyMenu, Icon, %ShortName%, % StrReplace(ExeName,"%Commander_Path%",Commander_Path) - Else - Menu, MyMenu, Icon, %ShortName%, % StrReplace(v.icon,"%Commander_Path%",Commander_Path) - } - Catch ; it is not an EXE - { - Menu, MyMenu, Icon, %ShortName%, shell32.dll, 3 - } - If (k = 1) ; Add line after default editors - Menu, MyMenu, Add + Gosub, AddMenuEntry + } -; Program options -Menu, MyMenu, Add -Menu, MyMenu, Add, %MenuPadding%Add new Editor, ConfigEditorsNew -Menu, MyMenu, Icon, %MenuPadding%Add new Editor, shell32.dll, 176 -Menu, MyMenu, Add, %MenuPadding%Settings, MenuHandler -Menu, MyMenu, Icon, %MenuPadding%Settings, shell32.dll, 170 -Menu, MyMenu, Add, %MenuPadding%Configure Editors, ConfigEditors -Menu, MyMenu, Icon, %MenuPadding%Configure Editors, shell32.dll, 70 -Menu, MyMenu, Add, %MenuPadding%Scan Document Templates, DocumentTemplatesScan -Menu, MyMenu, Icon, %MenuPadding%Scan Document Templates, shell32.dll, 172 - -Menu, MyMenu, Add, %MenuPadding%Exit, MenuHandler -Menu, MyMenu, Icon, %MenuPadding%Exit, shell32.dll, 132 +Gosub, AddMenuProgramOptions Return @@ -71,7 +51,7 @@ Return ; Tray menu MenuHandler: -; MsgBox % A_ThisMenuItemPos-1 ":" MatchList[A_ThisMenuItemPos-1].exe ; debug +; MsgBox % A_ThisMenu ":" A_ThisMenuItemPos-1 ":" MatchList[A_ThisMenuItemPos-1].exe ; debug ; Easy & Quick options first If (A_ThisMenuItem = "&Open") @@ -114,6 +94,57 @@ Else If (A_ThisMenuItemPos = 1) ; Default editor Return } Else - ProcessFiles(Matchlist, A_ThisMenuItemPos-1) ; proceed with the selected editor. Menu order = editor order. + If (MatchList.Temp.SelectedExtensions = "") or (A_ThisMenu = "MyMenu") ; entire Foreground menu + { + ProcessFiles(Matchlist, A_ThisMenuItemPos-1) ; proceed with the selected editor. Menu order = editor order. + MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp"),MatchListReference:="" + } + else ; filtered Foreground menu + { + ProcessFiles(Matchlist, MatchListReference[A_ThisMenuItemPos]) + MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp"),MatchListReference:="" + } + +Return + +AddMenuEntry: + + Menu, %MenuName%, Add, %ShortName%, MenuHandler + + Try + { + If (v.icon = "") + Menu, %MenuName%, Icon, %ShortName%, % StrReplace(ExeName,"%Commander_Path%",Commander_Path) + Else + Menu, %MenuName%, Icon, %ShortName%, % StrReplace(v.icon,"%Commander_Path%",Commander_Path) + } + Catch ; it is not an EXE + { + Menu, %MenuName%, Icon, %ShortName%, shell32.dll, 3 + } + If (k = 1) ; Add line after default editors + Menu, %MenuName%, Add + +If debug + { + debug_menu .= MenuCounter " : " ShortName "`n" + } +Return + +AddMenuProgramOptions: + +; Program options +Menu, %MenuName%, Add +Menu, %MenuName%, Add, %MenuPadding%Add new Editor, ConfigEditorsNew +Menu, %MenuName%, Icon, %MenuPadding%Add new Editor, shell32.dll, 176 +Menu, %MenuName%, Add, %MenuPadding%Settings, MenuHandler +Menu, %MenuName%, Icon, %MenuPadding%Settings, shell32.dll, 170 +Menu, %MenuName%, Add, %MenuPadding%Configure Editors, ConfigEditors +Menu, %MenuName%, Icon, %MenuPadding%Configure Editors, shell32.dll, 70 +Menu, %MenuName%, Add, %MenuPadding%Scan Document Templates, DocumentTemplatesScan +Menu, %MenuName%, Icon, %MenuPadding%Scan Document Templates, shell32.dll, 172 + +Menu, %MenuName%, Add, %MenuPadding%Exit, MenuHandler +Menu, %MenuName%, Icon, %MenuPadding%Exit, shell32.dll, 132 Return diff --git a/inc/Settings.ahk b/inc/Settings.ahk index dd4613b..aecf6da 100644 --- a/inc/Settings.ahk +++ b/inc/Settings.ahk @@ -12,9 +12,9 @@ Gui, Browse:Destroy ; Variables SelectMenuPos:=MatchList.settings.MenuPos SelectTCStart:=MatchList.settings.TCStart -Checked:=MatchList.settings.F4MMClose FGHKey:=MatchList.settings.ForegroundHotkey BGHKey:=MatchList.settings.BackgroundHotkey +TMHKey:=MatchList.settings.FilteredHotkey ;SettingsFormat:=MatchList.settings.SettingsFormat ;If (SettingsFormat = "") @@ -27,12 +27,15 @@ HotKeyState:="Off" Gosub, SetHotkeys ; Gui for general program settings +Gui, +OwnDialogs Gui, font, % dpi("s8") -Gui, Add, GroupBox, % dpi("x16 y7 w540 h45"), Menu +Gui, Add, GroupBox, % dpi("x16 y7 w540 h70"), Menu Gui, Add, Text, % dpi("x25 y25 w309 h16"), &Selection menu appears Gui, Add, DropDownList, % dpi("x328 y20 w219 h25 r4 Choose" SelectMenuPos " vMenuPos AltSubmit"), 1 - At Mouse cursor|2 - Centered in window|3 - Right next to current file|4 - Docked next to current file (opposite panel) +Gui, Add, Text, % dpi("x25 yp+35 w309 h16"), &Accelerator key for full menu (for use in filtered menu, 1 char.) +Gui, Add, Edit, % dpi("x328 yp-5 w219 h21 vFullMenu"), % MatchList.settings.FullMenu ; % -Gui, Add, GroupBox, % dpi("x16 yp+40 w540 h45"), Files +Gui, Add, GroupBox, % dpi("x16 yp+60 w540 h45"), Files Gui, Add, Text, % dpi("x25 yp+20 w309 h16"), &Maximum number of files to be opened Gui, Add, Edit, % dpi("x328 yp-5 w219 h21 Number vMaxFiles"), % MatchList.settings.Maxfiles ; % @@ -50,9 +53,14 @@ If !FileExist(MatchList.settings.TCPath) Gui, Add, Edit , % dpi("xp+53 yp-5 w180 h21 vTCPath"), % MatchList.settings.TCPath ; % Gui, Add, Button, % dpi("xp+187 yp w30 h20 gSelectExe"), >> -Gui, Add, Checkbox, % dpi("x25 yp+30 w400 h16 Checked" checked " vF4MMClose"), Close F4MiniMenu when you close Total Commander. (experiment) - -Gui, Add, GroupBox, % dpi("x16 yp+35 w395 h90"), Hotkeys +Checked:=MatchList.settings.F4MMCloseAll +Gui, Add, Checkbox, % dpi("x25 yp+30 w250 h16 Checked" checked " vF4MMCloseAll"), Close F4MM when all copies of TC close +Checked:=MatchList.settings.F4MMClosePID +Gui, Add, Checkbox, % dpi("xp+250 yp w250 h16 Checked" checked " vF4MMClosePID"), Close F4MM when TC closes started by F4MM +Gui, Font, cGreen +Gui, Add, Text, % dpi("xp+250 yp gFMMCloseHelpText"), (?) +Gui, Font, cBlack +Gui, Add, GroupBox, % dpi("x16 yp+35 w395 h120"), Hotkeys Gui, Add, Text, % dpi("x25 yp+25 w150 h16"), &Background mode (direct) Gui, Add, Radio, % dpi("xp+130 yp w45 h16 vBesc"), Esc @@ -96,11 +104,32 @@ If InStr(FGHKey,"Esc &") Gui, Add, Hotkey, % dpi("xp+50 yp-3 w140 h20 vFGHKey"), %FGHKey% -Gui, Add, Button, % dpi("xp+177 yp-48 w120 h25 gButtonOK"), OK -Gui, Add, Button, % dpi("xp yp+30 w120 h25 gButtonClear"), Clear Hotkeys -Gui, Add, Button, % dpi("xp yp+30 w120 h25 gGuiClose"), Cancel +Gui, Add, Text, % dpi("x25 yp+35 w150 h16"), Fil&tered mode (menu) +Gui, Add, Radio, % dpi("xp+130 yp w45 h16 vTesc"), Esc +Gui, Add, Radio, % dpi("xp+45 yp w45 h16 vTWin"), Win + +If InStr(TMHKey,"#") + { + StringReplace, TMHKey, TMHKey, #, , All + GuiControl, ,TWin, 1 + } + +If InStr(TMHKey,"Esc &") + { + StringReplace, TMHKey, TMHKey, Esc &, , All + StringReplace, TMHKey, TMHKey, Esc &`;, , All + StringReplace, TMHKey, TMHKey, Esc &, , All + StringReplace, TMHKey, TMHKey, %A_Space%, , All + GuiControl, , TEsc, 1 + } + +Gui, Add, Hotkey, % dpi("xp+50 yp-3 w140 h20 vTMHKey"), %TMHKey% -Gui, Add, GroupBox, % dpi("x16 yp+35 w540 h70"), Currently Available Document Templates: +Gui, Add, Button, % dpi("xp+177 yp-78 w120 h25 gButtonOK"), OK +Gui, Add, Button, % dpi("xp yp+40 w120 h25 gButtonClear"), Clear Hotkeys +Gui, Add, Button, % dpi("xp yp+40 w120 h25 gGuiClose"), Cancel + +Gui, Add, GroupBox, % dpi("x16 yp+40 w540 h70"), Currently Available Document Templates: Gui, Add, Edit, % dpi("x25 yp+20 ReadOnly h40 w385 vDocumentTemplates"), % MatchList.Settings.templatesExt Gui, Add, Button, % dpi("xp+402 yp w120 h25 gButtonDocumentTemplates"), Update (scan) @@ -114,7 +143,7 @@ Gui, Add, Link, % dpi("x25 yp+65"), F4MiniMenu %F4Version%: Open selected file ;Gui, Add, GroupBox, xp+400 yp-85 w122 h60 ;Gui, Add, Link, xp+5 yp+13, Feedback welcome at`nTotal Commander forum`nor GitHub Issues. -Gui, Show, % dpi("center w570 h410"), Settings +Gui, Show, % dpi("center w570"), Settings Return ButtonDocumentTemplates: @@ -134,12 +163,16 @@ If (MaxFiles > 50) MatchList.settings.MaxFiles:=MaxFiles MatchList.settings.TCStart:=TCStart MatchList.settings.TCPath:=TCPath -MatchList.settings.F4MMClose:=F4MMClose +MatchList.settings.F4MMCloseAll:=F4MMCloseAll +MatchList.settings.F4MMClosePID:=F4MMClosePID +MatchList.settings.FullMenu:=trim(SubStr(FullMenu,1,1)," `t&") GuiControlGet, EscFG, , FEsc GuiControlGet, WinFG, , FWin GuiControlGet, EscBG, , BEsc GuiControlGet, WinBG, , BWin +GuiControlGet, EscTM, , TEsc +GuiControlGet, WinTM, , TWin ; Revert the boxes to the Hotkey def. If WinFG @@ -150,15 +183,22 @@ If WinBG BGHKey:="#" BGHKey If (EscBG = 1) and (RegExMatch(BGHKey,"[\^\+\!\#]") = 0) BGHKey:="Esc & " BGHKey +If WinTM + TMHKey:="#" TMHKey +If (EscTM = 1) and (RegExMatch(TMHKey,"[\^\+\!\#]") = 0) + TMHKey:="Esc & " TMHKey MatchList.settings.ForegroundHotkey:=FGHKey MatchList.settings.BackgroundHotkey:=BGHKey +MatchList.settings.FilteredHotkey:=TMHKey HotKeyState:="On" Gosub, SetHotkeys Gui, Destroy -Gosub, SaveSetup +Gosub, SaveSettings +Sleep 500 Reload ; v0.96 we may have changed F4MMClose so we need to reload the script to (de)activate the WinWait in F4MiniMenu.ahk +Sleep 500 Return ButtonClear: @@ -166,8 +206,11 @@ GuiControl, , FEsc, 0 GuiControl, , FWin, 0 GuiControl, , BEsc, 0 GuiControl, , BWin, 0 -GuiControl, , BGHKey, -GuiControl, , FGHKey, +GuiControl, , TEsc, 0 +GuiControl, , TWin, 0 +GuiControl, , BGHKey, +GuiControl, , FGHKey, +GuiControl, , TMHKey, Return GuiEscape: @@ -176,4 +219,18 @@ Gui, Destroy HotKeyState:="On" Gosub, SetHotkeys -Return \ No newline at end of file +Return + +FMMCloseHelpText: +MsgBox, 32, F4MMClose (experimental), +(join`n +F4MiniMenu - %F4Version% can automatically exit from memory using the following rules: + +[1] Close F4MM when all copies of TC close: +waits until all running copies of Total Commander are closed. + +[2] Close F4MM when TC closes started by F4MM: +If you have started (a new) Total Commander via F4MiniMenu, wait until that specific Total Commander closes, + +) +Return diff --git a/lib/iob.ahk b/lib/iob.ahk index c23f326..6dc13c9 100644 --- a/lib/iob.ahk +++ b/lib/iob.ahk @@ -15,7 +15,7 @@ iob(Filename="") { Global MatchList:=[] - SectionKeys:="BackgroundHotkey,ForegroundHotkey,MaxFiles,MenuPos,TCPath,TCStart,F4MMClose" + SectionKeys:="BackgroundHotkey,ForegroundHotkey,MaxFiles,MenuPos,TCPath,TCStart,F4MMCloseAll,F4MMClosePID,FilteredHotkey,FullMenu" Loop, parse, SectionKeys, CSV { IniRead, OutputVar, %Filename%, Settings, %A_LoopField% @@ -44,7 +44,7 @@ iob_save(ObjectName,Filename="") { ; Object parameter isn't used but just added global MatchList FileCopy, %Filename%, %Filename%.bak, 1 FileDelete, %Filename% - SectionKeys:="BackgroundHotkey,ForegroundHotkey,MaxFiles,MenuPos,TCPath,TCStart,F4MMClose" + SectionKeys:="BackgroundHotkey,ForegroundHotkey,MaxFiles,MenuPos,TCPath,TCStart,F4MMCloseAll,F4MMClosePID,FilteredHotkey,FullMenu" Loop, parse, SectionKeys, CSV IniWrite, % MatchList["Settings",A_LoopField], %Filename%, Settings, %A_LoopField% SectionKeys:="Delay,Exe,Ext,Method,Open,Windowmode,StartDir,Parameters,Icon,Name"