├── .gitattributes ├── DocumentTemplates ├── DocumentTemplatesExamples.zip └── readme.md ├── F4MiniMenu.ahk ├── F4TCIE.ahk ├── changelog.md ├── img ├── f4-configure-editors.png ├── f4-confirm-maximum.png ├── f4-editor-setttings.png ├── f4-foreground-menu.png └── f4-general-settings.png ├── inc ├── CLIParser.ahk ├── Editors.ahk ├── FilteredMenu.ahk ├── HelperFunctions.ahk ├── LoadSettings1.ahk ├── LoadSettings2.ahk ├── Menu.ahk ├── Settings.ahk └── TotalCommanderPath.ahk ├── lib ├── AutoXYWH.ahk ├── DoubleCommander.ahk ├── DropFiles.ahk ├── Everything.ahk ├── Explorer.ahk ├── GetPos.ahk ├── QDir.ahk ├── XA.ahk ├── XYPlorer.ahk ├── class_lv_rows.ahk ├── dpi.ahk ├── iob.ahk ├── log.ahk ├── osdtip.ahk └── tc.ahk ├── license.txt ├── readme.md └── res └── f4.ico /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /DocumentTemplates/DocumentTemplatesExamples.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hi5/F4MiniMenu/34d131ef7b47bef92dd4e120032674ac249ce5b3/DocumentTemplates/DocumentTemplatesExamples.zip -------------------------------------------------------------------------------- /DocumentTemplates/readme.md: -------------------------------------------------------------------------------- 1 | # Document Templates for F4TCIE.ahk 2 | 3 | Note that this is an additional functionality, if you don't place any template.* files 4 | in this folder F4TCIE will not use it. 5 | 6 | ## Introduction 7 | 8 | By default you can use the keyboard shortcut Shift+F4 or the 9 | *cm_EditNewFile* command to create a new text file and open this in your defined text 10 | editor. 11 | 12 | By setting F4TCIE.ahk as editor: 13 | 14 | TC, Configuration, Edit/View, Editor: 15 | drive:\path-to\F4TCIE.ahk "%1" 16 | 17 | you can extend this functionality to the programs you defined in F4MiniMenu. 18 | 19 | Unlike text editors, many program simply don't accept or understand the new empty 20 | file Total Commander creates. They may not start correctly or generate an error message. 21 | Here is where F4TCIE comes in. It checks if there is a "template.ext" file for the new 22 | file you just created, if so it copies that template to your current active panel and 23 | start your preferred program which you defined in F4MiniMenu. 24 | 25 | So instead of opening your text editor when you create a new "MyImageFile.PNG" it 26 | can start your preferred Graphics program for PNG files. 27 | 28 | If it can't find a template, it will simply launch your default editor. 29 | 30 | When you add new templates to this folder you need to Update (scan) the 31 | available templates via the "Scan Document Templates" in the Tray or Foreground 32 | menu OR restart F4MiniMenu. 33 | 34 | You can find two examples in DocumentTemplatesExamples.zip to illustrate how it 35 | works (RTF, PNG) - you can of course replace these with your own Template files. 36 | 37 | ## Limitation(s) 38 | 39 | * It won't work in/with ZIP files (but will copy file to Active panel) 40 | * Shift+F4 doesn't work in FTP panels (default TC behaviour) 41 | 42 | -------------------------------------------------------------------------------- /F4MiniMenu.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Script : F4MiniMenu.ahk for Total Commander - AutoHotkey 1.1+ (Ansi and Unicode) 4 | Version : v1.47 5 | Author : hi5 6 | Last update : 09 February 2025 7 | Purpose : Minimalistic clone of the F4 Menu program for Total Commander (open selected files in editor(s)) 8 | Source : https://github.com/hi5/F4MiniMenu 9 | 10 | Note : ; % used to resolve syntax highlighting feature bug of N++ 11 | 12 | */ 13 | 14 | #Requires AutoHotkey v1.1.31+ 15 | #SingleInstance, Force 16 | #UseHook 17 | #NoEnv 18 | SetBatchlines, -1 19 | SetWorkingDir, %A_ScriptDir% 20 | SetTitleMatchMode, 2 21 | ; Setup variables, menu, hotkeys etc 22 | 23 | F4Version:="v1.47" 24 | 25 | ; 26 | ;@Ahk2Exe-SetFileVersion 1.47 27 | ;@Ahk2Exe-SetProductName F4MiniMenu 28 | ;@Ahk2Exe-SetDescription F4MiniMenu: Open files from TC 29 | ;@Ahk2Exe-SetProductVersion Compiled with AutoHotkey v%A_AhkVersion% 30 | ;@Ahk2Exe-SetCopyright MIT License - (c) https://github.com/hi5 31 | ; 32 | 33 | ; 34 | IfNotExist, %A_ScriptDir%\res 35 | FileCreateDir, %A_ScriptDir%\res 36 | FileInstall, res\f4.ico, %A_ScriptDir%\res\f4.ico 37 | ; 38 | 39 | global AllExtensions:="" 40 | global TmpFileList:="" 41 | global Commander_Path:="" 42 | global Commander_Ini:="" 43 | MatchList:="" 44 | MenuPadding:=" " 45 | DefaultShortName:="" 46 | 47 | EnvGet, TmpFileList, temp 48 | 49 | If (TmpFileList = "") 50 | TmpFileList:=A_ScriptDir 51 | 52 | TmpFileList .= "\$$f4mtmplist$$.m3u" 53 | 54 | ; shared with F4TCIE 55 | #Include %A_ScriptDir%\inc\LoadSettings1.ahk 56 | 57 | GroupAdd, TCOnly, ahk_class TTOTAL_CMD ahk_exe TOTALCMD.EXE 58 | GroupAdd, TCOnly, ahk_class TTOTAL_CMD ahk_exe TOTALCMD64.EXE 59 | 60 | FileDelete, % TmpFileList 61 | 62 | Try 63 | Menu, tray, icon, res\f4.ico 64 | Menu, tray, Tip , F4MiniMenu - %F4Version% 65 | Menu, tray, NoStandard 66 | Menu, tray, Add, F4MiniMenu - %F4Version%, DoubleTrayClick 67 | Try 68 | Menu, tray, icon, F4MiniMenu - %F4Version%, res\f4.ico 69 | Menu, tray, Default, F4MiniMenu - %F4Version% 70 | Menu, tray, Click, 1 ; this will show the tray menu because we send {rbutton} at the DoubleTrayClick label 71 | Menu, tray, Add, 72 | Menu, tray, Add, &Open, MenuHandler 73 | Menu, tray, Add, &Reload this script, MenuHandler 74 | Menu, tray, Icon,&Reload this script, shell32.dll, 239 75 | 76 | Menu, tray, Add, &Edit this script, MenuHandler 77 | Try 78 | Menu, tray, Icon,&Edit this script, comres.dll, 7 79 | If A_IsCompiled 80 | Menu, tray, Disable, &Edit this script 81 | 82 | Menu, tray, Add, 83 | Menu, tray, Add, &Suspend Hotkeys, MenuHandler 84 | Try 85 | Menu, tray, Icon,&Suspend Hotkeys, %A_AhkPath%, 3 86 | Menu, tray, Add, &Pause Script, MenuHandler 87 | Try 88 | Menu, tray, Icon,&Pause Script, %A_AhkPath%, 4 89 | Menu, tray, Add, 90 | Menu, tray, Add, Settings, Settings 91 | Try 92 | Menu, tray, Icon, Settings, shell32.dll, 170 93 | Menu, tray, Add, Configure editors, ConfigEditors 94 | Try 95 | Menu, tray, Icon, Configure Editors, shell32.dll, 70 96 | Menu, tray, Add, Scan Document Templates, DocumentTemplatesScan 97 | Try 98 | Menu, tray, Icon, Scan Document Templates, shell32.dll, 172 99 | Menu, tray, Add, 100 | Menu, tray, Add, Exit, ExitSettings 101 | Try 102 | Menu, tray, Icon, Exit, shell32.dll, 132 103 | 104 | If !FileExist(F4ConfigFile) and !FileExist(F4ConfigFile ".bak") ; most likely first run, no need to show error message 105 | Gosub, CreateNewConfig 106 | 107 | ; shared with F4TCIE 108 | #Include %A_ScriptDir%\inc\LoadSettings2.ahk 109 | 110 | If (Error = 1) 111 | { 112 | ErrorText= 113 | (Join`n LTRIM 114 | There seems to be an error with the settings file. 115 | F4MiniMenu will try to create default configuration and restart. 116 | Be sure to check the last backup of your settings in "%F4ConfigFile%" 117 | Be sure to exit F4MiniMenu before trying to restore any backup settings. 118 | ) 119 | 120 | MsgBox, 16, F4MiniMenu, %ErrorText% 121 | Reload 122 | } 123 | 124 | ; Create backup file 125 | FileCopy, %F4ConfigFile%, %F4ConfigFile%.bak, 1 126 | 127 | ; Hotkey groups (menus) 128 | GroupAdd, TCF4Windows, ahk_class TTOTAL_CMD ahk_exe TOTALCMD.EXE 129 | GroupAdd, TCF4Windows, ahk_class TTOTAL_CMD ahk_exe TOTALCMD64.EXE 130 | GroupAdd, TCF4Windows, ahk_class TQUICKSEARCH 131 | 132 | If MatchList.settings.Lister 133 | GroupAdd, TCF4Windows, ahk_class TLister 134 | If MatchList.settings.FindFiles 135 | GroupAdd, TCF4Windows, ahk_class TFindFile 136 | 137 | 138 | ; Add other file managers if any 139 | If MatchList.settings.Explorer 140 | { 141 | GroupAdd, TCF4Windows, ahk_class CabinetWClass 142 | GroupAdd, TCF4Windows, ahk_class ExploreWClass 143 | } 144 | 145 | If MatchList.settings.Everything 146 | { 147 | GroupAdd, TCF4Windows, ahk_exe Everything.exe 148 | GroupAdd, TCF4Windows, ahk_exe Everything64.exe 149 | } 150 | 151 | If (MatchList.settings.DoubleCommander <> "") ; note that some versions of DC report ahk_class TTOTAL_CMD ahk_exe doublecmd.exe 152 | { 153 | GroupAdd, TCF4Windows, ahk_class DClass ahk_exe doublecmd.exe ; v0.9 154 | GroupAdd, TCF4Windows, ahk_class TTOTAL_CMD ahk_exe doublecmd.exe ; v1.0 155 | } 156 | 157 | If (MatchList.settings.XYPlorer <> "") 158 | { 159 | GroupAdd, TCF4Windows, ahk_exe XYPlorer.exe 160 | GroupAdd, TCF4Windows, ahk_exe XYPlorerFree.exe 161 | } 162 | 163 | If (MatchList.settings.QDir <> "") 164 | { 165 | GroupAdd, TCF4Windows, ahk_exe Q-Dir.exe 166 | GroupAdd, TCF4Windows, ahk_exe Q-Dir_x64.exe 167 | } 168 | 169 | ; /Add other file managers if any 170 | 171 | If (MatchList.settings.TCStart = 2) and !WinExist("ahk_class TTOTAL_CMD") 172 | { 173 | If FileExist(MatchList.settings.TCPath) 174 | Run % MatchList.settings.TCPath,,UseErrorLevel,TCOutputVarPID ; % 175 | WinWait, ahk_class TTOTAL_CMD 176 | } 177 | 178 | If (MatchList.settings.TCStart = 3) 179 | { 180 | If FileExist(MatchList.settings.TCPath) 181 | Run % MatchList.settings.TCPath,,UseErrorLevel,TCOutputVarPID ; % 182 | WinWait, ahk_class TTOTAL_CMD 183 | } 184 | 185 | #Include %A_ScriptDir%\inc\CLIParser.ahk 186 | 187 | 188 | ; shared with F4MM 189 | #Include %A_ScriptDir%\inc\TotalCommanderPath.ahk 190 | 191 | Gosub, DocumentTemplatesScan 192 | 193 | Gosub, BuildMenu 194 | 195 | ; Build master list to quickly open in default program if not found 196 | Gosub, GetAllExtensions 197 | 198 | HotKeyState:="On" 199 | Gosub, SetHotkeys 200 | 201 | ; Clear tmp file(s) 202 | OnExit, ExitSettings 203 | 204 | If CLI_Editors 205 | { 206 | Gosub, ConfigEditors 207 | WinWaitClose, F4MiniMenu - Editor Settings ahk_class AutoHotkeyGUI 208 | Sleep 1000 209 | ExitApp 210 | } 211 | 212 | If CLI_Settings 213 | { 214 | Gosub, Settings 215 | WinWaitClose, F4MiniMenu - Settings ahk_class AutoHotkeyGUI 216 | Sleep 1000 217 | ExitApp 218 | } 219 | 220 | If CLI_ShowMenu 221 | { 222 | Gosub, ShowMenu 223 | Sleep 1000 224 | ExitApp 225 | } 226 | 227 | If CLI_FilteredMenu 228 | { 229 | Gosub, FilteredMenu 230 | Sleep 1000 231 | ExitApp 232 | } 233 | 234 | If CLI_Exit and ((CLI_ShowMenu <> 1) and (CLI_FilteredMenu <> 1)) 235 | { 236 | Gosub, Process 237 | Sleep 1000 238 | MsgBox 239 | ExitApp 240 | } 241 | 242 | ; End of Auto-execute section 243 | If (Matchlist.settings.F4MMCloseAll = 1) 244 | { 245 | WinWaitClose, ahk_class TTOTAL_CMD 246 | ExitApp 247 | } 248 | Else If (Matchlist.settings.F4MMClosePID = 1) 249 | { 250 | Sleep 5000 251 | WinWaitClose, ahk_pid %TCOutputVarPID% 252 | ExitApp 253 | } 254 | Return 255 | 256 | Process: 257 | ProcessFiles(MatchList) 258 | MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp") 259 | If CLI_Exit 260 | ExitApp 261 | Return 262 | 263 | ; Function executed by background hotkey (open directly) 264 | ProcessFiles(MatchList, SelectedEditor = "-1") 265 | { 266 | Global ArchiveExtentions 267 | Done:=[] 268 | Stop:=0 269 | If (MatchList.Temp.Files = "") 270 | Files:=GetFiles() ; Get list of selected files in TC, one per line 271 | else 272 | Files:=MatchList.Temp.Files 273 | MatchList.Temp.Files:="" 274 | 275 | ; Check if we possibly have selected file(s) from an archive 276 | If RegExMatch(Files,"iUm)" ArchiveExtentions) 277 | { 278 | Files:=StrReplace(Files,"`r","") 279 | If InStr(Files,"`n") 280 | Check:=SubStr(Files,1,InStr(Files,"`n")-1) 281 | Else 282 | Check:=Files 283 | 284 | If WinActive("ahk_class TTOTAL_CMD ahk_exe TOTALCMD.EXE") or WinActive("ahk_class TTOTAL_CMD ahk_exe TOTALCMD64.EXE") 285 | { 286 | IfNotExist, %check% ; additional check, if the file is from an archive it won't exist 287 | { ; therefore we resort to the internal TC Edit command - added for v0.51 288 | SendMessage 1075, 904, 0, , ahk_class TTOTAL_CMD ; Edit (Notepad) 289 | Return 290 | } 291 | } 292 | 293 | If MatchList.settings.DoubleCommander and DoubleCommander_Active() 294 | { 295 | IfNotExist, %check% ; additional check, if the file is from an archive it won't exist 296 | { ; therefore we resort to sending enter, now user can choose what to do (close or edit using default program) 297 | Send {enter} 298 | Return 299 | } 300 | } 301 | 302 | If MatchList.settings.Explorer and Explorer_Active() 303 | { 304 | IfNotExist, %check% ; additional check, if the file is from an archive it won't exist 305 | { ; don't allow it and return for Explorer 306 | MsgBox, 16, F4MiniMenu, You can not edit files from Archives when using Explorer. 307 | Return 308 | } 309 | } 310 | 311 | } 312 | 313 | SelectedFiles:=CountFiles(Files) 314 | 315 | If (SelectedFiles > MatchList.settings.MaxFiles) 316 | { 317 | ; Technique from http://www.autohotkey.com/docs/scripts/MsgBoxButtonNames.htm 318 | SetTimer, ChangeButtonNames, 10 319 | MsgBox, 4150, Maximum files, % "Number of selected files: [" SelectedFiles "]`nDo wish to process them all`nor stop at the maximum?: [" MatchList.settings.MaxFiles "]" ; % 320 | IfMsgBox, Cancel 321 | Return 322 | else IfMsgBox, Continue 323 | Stop:=1 324 | } 325 | 326 | Loop, parse, Files, `n, `r 327 | { 328 | If (Stop = 1) and (A_Index > Matchlist.settings.MaxFiles) 329 | Break 330 | open:=A_LoopField 331 | SplitPath, A_LoopField, , , OutExtension 332 | 333 | ; TODO: check for "checked" (= active) editor from settings 334 | for k, v in MatchList 335 | { 336 | Index:=A_Index 337 | CheckFileExt:=RegExExtensions(v.ext) 338 | If CheckFile(done,open) ; safety check - otherwise each file would be processed for all editors 339 | Break 340 | If (SelectedEditor < 0) ; Find out which editor to use, first come first serve 341 | { 342 | ;If OutExtension not in %AllExtensions% ; Open in default program 343 | If !RegExMatch(OutExtension,AllExtensions) ; Open in default program - v0.9 allow for wildcards 344 | { 345 | FileList1 .= open "`n" 346 | Done.Insert(open) 347 | } 348 | ;Else If OutExtension in % v.ext ; Open in defined program % 349 | Else If RegExMatch(OutExtension,CheckFileExt) ; Open in defined program - v0.9 allow for wildcards 350 | { 351 | FileList%Index% .= open "`n" 352 | Done.Insert(open) 353 | } 354 | } 355 | Else If (SelectedEditor > 0) ; Use selected editor from the Menu (Foreground option) 356 | { 357 | FileList%SelectedEditor% .= open "`n" 358 | Done.Insert(open) 359 | } 360 | } 361 | } 362 | 363 | for k, v in MatchList 364 | { 365 | Index:=A_Index 366 | list:=Trim(FileList%Index%,"`n") 367 | If (list = "") 368 | Continue 369 | If (v.Method = "cmdline") 370 | { 371 | cmdfiles:="" 372 | Loop, parse, list, `n, `r 373 | cmdfiles .= """" A_LoopField """" A_Space ; " fix highlighting 374 | OpenFile(v, cmdfiles, MatchList.Settings.MaxWinWaitSec) 375 | If MatchList.Settings.log 376 | Log(A_Now " : ProcessFiles, cmdline -> " v.exe "|" cmdfiles "|" MatchList.Settings.MaxWinWaitSec,MatchList.Settings.logFile) 377 | cmdfiles:="" 378 | } 379 | else If (v.Method = "FileList") 380 | { 381 | FileDelete, % TmpFileList 382 | FileAppend, %list%, %TmpFileList%, UTF-8-RAW 383 | OpenFile(v, TmpFileList, MatchList.Settings.MaxWinWaitSec) 384 | If MatchList.Settings.log 385 | Log(A_Now " : ProcessFiles, FileList -> " v.exe "|" TmpFileList "|" MatchList.Settings.MaxWinWaitSec,MatchList.Settings.logFile) 386 | } 387 | Else If (v.Method <> "Files") 388 | { 389 | Loop, parse, list, `n 390 | { 391 | If (A_LoopField = "") 392 | Continue 393 | OpenFile(v, A_LoopField, MatchList.Settings.MaxWinWaitSec) 394 | If MatchList.Settings.log 395 | Log("`n" A_Now " : ProcessFiles, Files -> " v.exe "|" A_LoopField "|" MatchList.Settings.MaxWinWaitSec,MatchList.Settings.logFile) 396 | } 397 | } 398 | } 399 | PostMessage 1075, 524, 0, , ahk_class TTOTAL_CMD ; Unselect all (files+folders) 400 | } 401 | 402 | ; Get a list of extensions from selected files we can use to build filtered menu 403 | GetExt(Files) 404 | { 405 | Global MatchList 406 | Loop, parse, files, `n, `r 407 | { 408 | SplitPath, A_LoopField,,, OutExtension 409 | Ext .= OutExtension "|" 410 | } 411 | MatchList.Temp["SelectedExtensions"]:=Trim(Ext,"|") 412 | } 413 | 414 | ; Process other applications and windows first (find files, lister) 415 | ; Get a list of selected files using internal TC commands (see totalcmd.inc for references) 416 | GetFiles() 417 | { 418 | Global MatchList, CLI_Exit, CLI_File, ListerWindowClose 419 | 420 | If CLI_Exit 421 | { 422 | FileRead, Files, %CLI_File% 423 | MatchList.Temp["Files"]:=Files 424 | If MatchList.Settings.log 425 | Log(A_Now " : GetFiles, CLI_Exit ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 426 | Return Files 427 | } 428 | 429 | If MatchList.settings.Explorer and Explorer_Active() 430 | { 431 | Files:=Explorer_GetSelection() 432 | MatchList.Temp["Files"]:=Files 433 | If MatchList.Settings.log 434 | Log(A_Now " : GetFiles, Explorer ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 435 | Return Files 436 | } 437 | 438 | If MatchList.settings.Everything and Everything_Active() 439 | { 440 | Files:=Everything_GetSelection() 441 | MatchList.Temp["Files"]:=Files 442 | If MatchList.Settings.log 443 | Log(A_Now " : GetFiles, Everything ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 444 | Return Files 445 | } 446 | 447 | If MatchList.settings.DoubleCommander and DoubleCommander_Active() 448 | { 449 | Files:=DoubleCommander_GetSelection() 450 | MatchList.Temp["Files"]:=Files 451 | If MatchList.Settings.log 452 | Log(A_Now " : GetFiles, DoubleCommander ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 453 | Return Files 454 | } 455 | 456 | If MatchList.settings.XYPlorer and XYPlorer_Active() 457 | { 458 | Files:=XYPlorer_GetSelection() 459 | MatchList.Temp["Files"]:=Files 460 | If MatchList.Settings.log 461 | Log(A_Now " : GetFiles, XYPlorer ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 462 | Return Files 463 | } 464 | 465 | If MatchList.settings.QDir and QDir_Active() 466 | { 467 | Files:=QDir_GetSelection() 468 | MatchList.Temp["Files"]:=Files 469 | If MatchList.Settings.log 470 | Log(A_Now " : GetFiles, QDir ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 471 | Return Files 472 | } 473 | 474 | If WinActive("ahk_class TLister") 475 | { 476 | WinGetActiveTitle, Files 477 | ; check once if ListerWindowClose was already read in case F4MM was started before TC 478 | ; to obtain environment variable Commander_Ini_Path) and read value from wincmd.ini 479 | If (ListerWindowClose = "") or (ListerWindowClose = "ERROR") 480 | ListerWindowClose() 481 | Files:=RegExReplace(Files,"U)^.*\[(.*).$","$1") 482 | If ListerWindowClose in 2,3 483 | WinClose, A 484 | If MatchList.Settings.log 485 | Log(A_Now " : GetFiles, Lister ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 486 | Return Files 487 | } 488 | 489 | If MatchList.settings.QuickView 490 | { 491 | WinGetText, Files, ahk_class TTOTAL_CMD, Lister 492 | If (Files <> "") 493 | { 494 | RegExMatch(Files,"U) - \K\[(.*)\]`r?`n",Files) 495 | If MatchList.Settings.log 496 | Log(A_Now " : GetFiles, QuickView ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 497 | Return Files1 498 | } 499 | } 500 | 501 | If WinActive("ahk_class TFindFile") ; class names may change between versions, below for TC11 502 | { 503 | ; ControlGet, Files, Choice,, TWidthListBox1, ahk_class TFindFile; for TC10 504 | ControlGet, Files, Choice,, TMyListBox2, ahk_class TFindFile 505 | If (ErrorLevel = 1) or (Files = "") 506 | ControlGet, Files, Choice,, LCLListbox2, ahk_class TFindFile 507 | IfNotInString, Files,[ ; make sure you haven't selected a directory or the first line 508 | { 509 | If MatchList.Settings.log 510 | Log(A_Now " : GetFiles, Find files ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 511 | Return Files 512 | } 513 | } 514 | 515 | ClipboardSave:=ClipboardAll 516 | Clipboard:="" 517 | PostMessage 1075, 2018, 0, , ahk_class TTOTAL_CMD ; Copy names with full path to clipboard 518 | Sleep 100 519 | Files:=Clipboard 520 | Clipboard:=ClipboardSave 521 | ClipboardSave:="" 522 | ; PostMessage 1075, 524, 0, , ahk_class TTOTAL_CMD ; Unselect all (files+folders) 523 | MatchList.Temp["Files"]:=Files 524 | If MatchList.Settings.log 525 | Log(A_Now " : GetFiles, TC File Panel ->`n" Files "`n-----------------------",MatchList.Settings.logFile) 526 | Return Files 527 | } 528 | 529 | ; Function to determine which method to use to open a file 530 | ; normal: filepath\file1.ext 531 | ; cmdline: "filepath\file1.ext" "filepath\file2.ext" "filepath\file3.ext" 532 | ; filelist: %temp%\$$f4mtmplist$$.m3u OR %A_ScriptDir%\$$f4mtmplist$$.m3u 533 | ; drag&drop: filepath\file1.ext 534 | OpenFile(Editor,open,MaxWinWaitSec=2) 535 | { 536 | If (MaxWinWaitSec = "") or (MaxWinWaitSec < 2) or (MaxWinWaitSec = "ERROR") 537 | MaxWinWaitSec:=2 538 | func:=Editor.Method 539 | title:="ahk_exe " Editor.Exe 540 | If (func = "FileList") 541 | { 542 | ; if GetInput() was cancelled don't process windowmode below 543 | result:=Normal(Editor.Exe,open,Editor.Delay,Editor.Parameters,Editor.StartDir) 544 | } 545 | Else If IsFunc(func) ; takes care of normal, drag & drop, and cmdline 546 | { 547 | ; if GetInput() was cancelled don't process windowmode below 548 | result:=%func%(Editor.Exe,open,Editor.Delay,Editor.Parameters,Editor.StartDir) 549 | } 550 | 551 | ; Moved above window actions in v1.1 552 | ; Added WinExist check to give program some time to start first 553 | ; before proceeding - similar to Delay 554 | If !WinExist(title) 555 | Sleep % Editor.open 556 | 557 | ; Program was started so we can continue. 558 | ; Result can be > 1 if defined program was not found 559 | ; and we resorted to default editor as a fall back, see normal() 560 | if (result = 1) 561 | { 562 | If (Editor.windowmode = 1) ; normal (activate) 563 | { 564 | WinWait, %title%,, % MaxWinWaitSec 565 | WinActivate, %title% 566 | } 567 | Else If (Editor.windowmode = 2) ; maximize 568 | { 569 | WinWait, %title%,, % MaxWinWaitSec 570 | WinMaximize, %title% 571 | } 572 | Else If (Editor.windowmode = 3) ; minimize 573 | { 574 | WinWait, %title%,, % MaxWinWaitSec 575 | WinMinimize, %title% 576 | } 577 | } 578 | 579 | ;@Ahk2Exe-IgnoreBegin 580 | #include *i %A_ScriptDir%\inc\WinActivatePrivateRules.ahk 581 | ;@Ahk2Exe-IgnoreEnd 582 | 583 | Return open 584 | } 585 | 586 | Normal(program,file,delay,parameters,startdir) 587 | { 588 | ; Run, Target, WorkingDir, Max|Min|Hide 589 | Global MatchList 590 | ;program:=GetTCCommander_Path(program) 591 | program:=GetPath(program) 592 | execute:=1 593 | GetInput(parameters,file,startdir,execute,program) 594 | if !execute 595 | Return execute 596 | startdir:=GetPath(startdir) 597 | if (file = "") 598 | Try 599 | { 600 | Run, %program% %parameters%, %startdir% 601 | } 602 | Catch 603 | { 604 | ;program:=GetTCCommander_Path(MatchList[1].Exe) 605 | program:=GetPath(MatchList[1].Exe) 606 | startdir:=GetPath(startdir) 607 | Run, %program% %parameters%, %startdir% 608 | execute++ 609 | } 610 | else 611 | Try 612 | { 613 | if (file <> "") 614 | Run, %program% %parameters% "%file%", %startdir% 615 | else 616 | Run, %program% %parameters%, %startdir% 617 | } 618 | Catch 619 | { 620 | ;program:=GetTCCommander_Path(MatchList[1].Exe) 621 | program:=GetPath(MatchList[1].Exe) 622 | startdir:=GetPath(startdir) 623 | Run, %program% %parameters% "%file%", %startdir% 624 | ; OSDTIP_Pop(MainText, SubText, TimeOut, Options, FontName, Transparency) 625 | OSDTIP_Pop("F4MiniMenu", "Defined editor/program not found`nReverting to default editor", -750,"W230 H80 U1") 626 | execute++ 627 | } 628 | Return execute 629 | } 630 | 631 | cmdline(program,file,delay,parameters,startdir) 632 | { 633 | ; Run, Target, WorkingDir, Max|Min|Hide 634 | ;program:=GetTCCommander_Path(program) 635 | program:=GetPath(program) 636 | execute:=1 637 | GetInput(parameters,file,startdir,execute,program) 638 | if !execute 639 | Return execute 640 | startdir:=GetPath(startdir) 641 | Run, %program% %parameters% %file%, %startdir% 642 | Return execute 643 | } 644 | 645 | DragDrop(program,file,delay,parameters,startdir) 646 | { 647 | ; Run, Target, WorkingDir, Max|Min|Hide 648 | ;program:=GetTCCommander_Path(program) 649 | program:=GetPath(program) 650 | title:="ahk_exe " program 651 | IfWinNotExist, %title% 652 | { 653 | startdir:=GetPath(startdir) 654 | Run, %program% %parameters% "%file%", %startdir% 655 | ; in case there are more files to be processed we need the extra time after 656 | ; first startup as some programs are sloooooow and we have to make sure it 657 | ; can accept drag & drop files. It is is only for the first file in the list 658 | Sleep %delay% 659 | Return 1 660 | } 661 | 662 | ;@Ahk2Exe-IgnoreBegin 663 | #include *i %A_ScriptDir%\inc\DragDropPrivateRules.ahk 664 | ;@Ahk2Exe-IgnoreEnd 665 | 666 | Return 1 667 | } 668 | 669 | ; Helper functions & Labels 670 | 671 | CheckCmdLine(Method,CountFiles) 672 | { 673 | If (Method <> "cmdline") 674 | Return 1 675 | StrReplace(CountFiles, Chr(34) A_Space Chr(34), , OutputVarCount) 676 | If (OutputVarCount > 1) 677 | Return 0 678 | Return 1 679 | } 680 | 681 | GetInput(byref parameters, byref file, byref startdir, byref execute, program) 682 | { 683 | WinGetActiveStats, A, W, H, X, Y 684 | X:=X+(W/2)-205 685 | Y:=Y+(H/2)-110 686 | if InStr(parameters,"?") 687 | { 688 | AskParameters:=1 689 | StringReplace, parameters, parameters, ?,, All 690 | } 691 | if InStr(startdir,"?") 692 | { 693 | AskStartDir:=1 694 | StringReplace, startdir, startdir, ?,, All 695 | } 696 | if InStr(parameters,"%p") 697 | parameters:=StrReplace(parameters,"%p",GetTCFields("%p")) 698 | if InStr(parameters,"%t") 699 | parameters:=StrReplace(parameters,"%t",GetTCFields("%t")) 700 | if InStr(parameters,"%o") 701 | parameters:=StrReplace(parameters,"%o",GetTCFields("%o",file)) 702 | if InStr(parameters,"%n") 703 | parameters:=StrReplace(parameters,"%n",GetTCFields("%n",file)) 704 | if InStr(parameters,"%m") 705 | parameters:=StrReplace(parameters,"%m",GetTCFields("%m",file)) 706 | if InStr(parameters,"%$date") 707 | { 708 | DateTimeObject:=GetTCFields(parameters) 709 | parameters:=StrReplace(parameters,DateTimeObject[1],DateTimeObject[2]) 710 | DateTimeObject:="" 711 | } 712 | 713 | if InStr(parameters,"%e") 714 | parameters:=StrReplace(parameters,"%e",GetTCFields("%e",file)) 715 | ; %f4? placeholders for optional parameters: 716 | ; %f41 placeholder to alter position of filenames on the command line. 717 | ; 718 | if InStr(parameters,"%f41") 719 | { 720 | parameters:=StrReplace(parameters, "%f41", file) 721 | file:="" 722 | } 723 | 724 | if InStr(startdir,"%p") 725 | startdir:=StrReplace(startdir,"%p",GetTCFields("%p")) 726 | if InStr(startdir,"%t") 727 | startdir:=StrReplace(startdir,"%t",GetTCFields("%t")) 728 | 729 | if (AskParameters = 1) or (AskStartDir = 1) 730 | { 731 | Gui, AskInput: +AlwaysOnTop +ToolWindow 732 | Gui, AskInput: Margin, 5, 5 733 | if (AskParameters = 1) 734 | { 735 | Gui, AskInput:Add, Text, xp y5 , Command line parameters: 736 | Gui, AskInput:Add, Edit, xp yp+20 w400 h20 , %parameters% 737 | } 738 | if (AskParameters <> 1) and (parameters <> "") 739 | { 740 | Gui, AskInput:Add, Text, xp y58 , Command line parameters: 741 | Gui, AskInput:Add, Edit, xp yp+20 w400 h20 ReadOnly , %parameters% 742 | } 743 | 744 | ; if (file <> "") 745 | ; { 746 | ; Gui, AskInput:Add, Text, x5 yp+30 , File(s): 747 | ; Gui, AskInput:Add, Edit, x5 yp+20 w400 h20 , %file% 748 | ; } 749 | 750 | if (AskStartDir = 1) 751 | { 752 | Gui, AskInput:Add, Text, xp yp+30 , Start directory: 753 | Gui, AskInput:Add, Edit, xp yp+20 w400 h20 , %startdir% 754 | } 755 | if (AskStartDir <> 1) and (startdir <> "") 756 | { 757 | Gui, AskInput:Add, Text, xp yp+30 , Start directory: 758 | Gui, AskInput:Add, Edit, xp yp+20 w400 h20 ReadOnly , %startdir% 759 | } 760 | 761 | ; Gui, AskInput:Add, Text, x5 yp+30 w400 h20, Will run as: 762 | ; Gui, AskInput:Add, Edit, x5 yp+20 w400 h50 ReadOnly, %program% %parameters% %file%, %startdir% 763 | 764 | Gui, AskInput:Add, Button, xp+110 yp+60 w100 h25 gAskInputOK Default, &OK 765 | Gui, AskInput:Add, Button, xp+110 yp w100 h25 gAskInputCancel, &Cancel 766 | Gui, AskInput:Show, w410 x%X% y%Y%,F4MiniMenu Input 767 | } 768 | While (WinExist("F4MiniMenu Input ahk_class AutoHotkeyGUI")) 769 | { 770 | Sleep 100 771 | } 772 | Return 773 | 774 | AskInputGuiEscape: 775 | AskInputGuiClose: 776 | AskInputCancel: 777 | Gui, AskInput:Destroy 778 | execute:=0 779 | Return 780 | 781 | AskInputOK: 782 | Gui, AskInput:Default 783 | GuiControlGet, parameters, , Edit1 784 | ; GuiControlGet, file , , Edit2 785 | GuiControlGet, startdir , , Edit2 ; edit3 if file is uncommented above 786 | StringReplace, startdir, startdir,",,All ; remove quotes just to be sure ;" 787 | Gui, AskInput:Destroy 788 | execute:=1 789 | Return 790 | } 791 | 792 | CheckFile(list,file) 793 | { 794 | For k, v in list 795 | If (v = file) 796 | Return 1 797 | Return 0 798 | } 799 | 800 | CountFiles(Files) 801 | { 802 | StringReplace, Files, Files, `n, `n, UseErrorLevel 803 | Return ErrorLevel+1 804 | } 805 | 806 | GetTCFields(opt,file="") 807 | { 808 | ; %P causes the source path to be inserted into the command line, including a backslash (\) at the end. 809 | ; %T inserts the current target path. Especially useful for packers. 810 | 811 | ; first we deal with non TC 812 | 813 | if MatchList.settings.Explorer or MatchList.settings.XYPlorer or MatchList.settings.QDir or MatchList.settings.Everything 814 | { 815 | if (opt = "%p") or (opt = "%t") 816 | { 817 | SplitPath, file, , OutDir ; panel 818 | Return OutDir 819 | } 820 | } 821 | 822 | ; SP = Source Path, TP = Target Path 823 | if (opt = "%p") or (opt = "%t") 824 | { 825 | /* 826 | ; cm_CopySrcPathToClip=2029 ; Copy source path to clipboard 827 | ; cm_CopyTrgPathToClip=2030 ; Copy target path to clipboard 828 | ; % (panel = "%p") ? "source" : "target" 829 | ClipSaveAll:=ClipboardAll 830 | Clipboard:="" 831 | SendMessage 1075, % (opt = "%p") ? 2029 : 2030, 0, , ahk_class TTOTAL_CMD 832 | panel:=Clipboard "\" 833 | Clipboard:=ClipSaveAll 834 | */ 835 | panel:=TC_SendData((opt = "%p") ? "SP" : "TP") 836 | Return panel 837 | } 838 | 839 | ; SN = Source Name Caret, TN = Target Name Caret 840 | if (opt = "%n") or (opt = "%m") 841 | { 842 | NameCaret:=TC_SendData((opt = "%n") ? "SN" : "TN") 843 | Return NameCaret 844 | } 845 | 846 | 847 | ; %O places the current filename without extension into the command line. 848 | ; %E places the current extension (without leading period) into the command line. 849 | if (opt = "%o") or (opt = "%e") 850 | { 851 | if InStr(file,""" """) ; we have multiple files so we need to parse them to get all names + ext 852 | { 853 | StringReplace, file, file, " ",|, All 854 | Loop, parse, % Trim(file,""""), | ; """ fix for highlighting issue in editor 855 | { 856 | SplitPath, A_LoopField, , , OutExtension, OutNameNoExt 857 | filenames .= """" OutNameNoExt """" A_Space ; " fix for highlighting issue in editor 858 | fileext .= """" OutExtension """" A_Space ; " fix for highlighting issue in editor 859 | } 860 | } 861 | else 862 | { 863 | SplitPath, file, , , OutExtension, OutNameNoExt 864 | filenames .= OutNameNoExt 865 | fileext .= OutExtension 866 | } 867 | Return % (opt = "%o") ? filenames : fileext 868 | } 869 | 870 | if InStr(opt, "%$date") 871 | { 872 | 873 | /* TC HELP 874 | 875 | %$DATE% Inserts the 24 hour date and time in the form YYYYMMDDhhmmss -> A_Now in AutoHotkey 876 | 877 | %$DATE:placeholders% 878 | Inserts the date in the form specified by placeholders. 879 | Same as in multi-rename tool: -> AHK 880 | y Paste year in 2 digit form -> yy 881 | Y Paste year in 4 digit form -> yyyy 882 | M Paste month, always 2 digit -> MM 883 | D Paste day, always 2 digit -> dd 884 | h Paste hours, always in 24 hour 2 digit format (0-23) -> H 885 | H Paste hours, always in 12 hour 2 digit format (1-12) -> hh 886 | i1 same but 1 character a/p only -> t 887 | i am/pm indicator in English -> tt 888 | m Paste minutes, always in 2 digit format -> mm 889 | s Paste seconds, always in 2 digit format -> ss 890 | any non-alpha character like a dot or dash will be added directly 891 | 892 | F4MM addition: |value|timeunit 893 | 894 | */ 895 | 896 | DateTimeObject:=[] 897 | 898 | ; output entire string, output1 time formatting options 899 | RegExMatch(opt,"Ui)%\$date:*([^%]*)%",output) 900 | 901 | if (output = "%$DATE%") 902 | { 903 | FormatTime, DateTime, , %A_Now% 904 | DateTimeObject[1]:="%$DATE%" 905 | DateTimeObject[2]:=DateTime 906 | return % DateTimeObject 907 | } 908 | else ; output1 -> we have placeholders 909 | { 910 | OutputData:=StrSplit(output1,"|") 911 | ; 1 placeholder, 2 value, 3 time units 912 | ; the order in which we process the format is important (y before Y, h-zzzzz-H, i1 before i) 913 | OutputData[1]:=RegExReplace(OutputData[1],"y","yy") 914 | OutputData[1]:=RegExReplace(OutputData[1],"Y","yyyy") 915 | OutputData[1]:=RegExReplace(OutputData[1],"M","MM") 916 | OutputData[1]:=RegExReplace(OutputData[1],"D","dd") 917 | OutputData[1]:=RegExReplace(OutputData[1],"h","zzzzz") ; we need to swap lower case h for temp char z 918 | OutputData[1]:=RegExReplace(OutputData[1],"H","hh") ; we we can safely process H hh conversion 919 | OutputData[1]:=RegExReplace(OutputData[1],"zzzzz","H") ; and now use char z for h->H conversion 920 | OutputData[1]:=RegExReplace(OutputData[1],"i1","t") 921 | OutputData[1]:=RegExReplace(OutputData[1],"i","tt") 922 | OutputData[1]:=RegExReplace(OutputData[1],"m","mm") 923 | OutputData[1]:=RegExReplace(OutputData[1],"s","ss") 924 | DateTimeFormat:=OutputData[1] 925 | 926 | FormatTime, DateTime,, yyyyMMddHHmmss 927 | EnvAdd, DateTime, % OutputData[2], % OutputData[3] ; do math if any 928 | FormatTime, DateTime, %DateTime%, %DateTimeFormat% ; format the time 929 | DateTimeObject[1]:=output 930 | DateTimeObject[2]:=DateTime 931 | return % DateTimeObject 932 | } 933 | } 934 | } 935 | 936 | SetHotkeys: 937 | 938 | Hotkey, IfWinActive, ahk_group TCONLY 939 | 940 | ;If MatchList.settings.EVDirTree 941 | ; Hotkey, % MatchList.settings.EVDirTree, Everything_DirectoryTree, %HotKeyState% ; % 942 | 943 | Hotkey, IfWinActive, 944 | 945 | Hotkey, IfWinActive, ahk_group TCF4Windows 946 | 947 | ; ~ native function will not be blocked 948 | ; $ prefix forces the keyboard hook to be used to implement this hotkey 949 | 950 | If (MatchList.settings.ForegroundHotkey <> "ERROR") and (MatchList.settings.ForegroundHotkey <> "") 951 | { 952 | hk_prefix:="$" 953 | ;If (RegExMatch(MatchList.settings.ForegroundHotkey,"[\^\+\!\# \&]")) 954 | ; hk_prefix:="~" 955 | FGHKey:=MatchList.settings.ForegroundHotkey 956 | StringReplace, FGHKey, FGHKey, &`;amp`;, & , All 957 | StringReplace, FGHKey, FGHKey, &`;, &, All 958 | If (InStr(FGHKey,"ESC")) 959 | hk_prefix:="~" 960 | 961 | Hotkey, % hk_prefix FGHKey, ShowMenu, %HotKeyState% ; % 962 | ; MsgBox % "Show Menu: " hk_prefix . FGHKey ; debug 963 | } 964 | 965 | If (MatchList.settings.BackgroundHotkey <> "ERROR") and (MatchList.settings.BackgroundHotkey <> "") 966 | { 967 | hk_prefix:="$" 968 | ;If (RegExMatch(MatchList.settings.BackgroundHotkey,"[\^\+\!\# \&]")) ; for example if hotkey is Esc & F4 not adding the ~ would mean Esc is actually disabled in "in place rename" (shift-f6) operations in a panel, or at least that is my experience. 969 | ; hk_prefix:="~" 970 | BGHKey:=MatchList.settings.BackgroundHotkey 971 | StringReplace, BGHKey, BGHKey, &`;amp`;, & , All 972 | StringReplace, BGHKey, BGHKey, &`;, &, All 973 | If (InStr(BGHKey,"ESC")) 974 | hk_prefix:="~" 975 | 976 | Hotkey, % hk_prefix BGHKey, Process, %HotKeyState% ; % 977 | ; MsgBox % "OpenItDirectly: " hk_prefix . BGHKey ; debug 978 | } 979 | 980 | If (MatchList.settings.FilteredHotkey <> "ERROR") and (MatchList.settings.FilteredHotkey <> "") 981 | { 982 | hk_prefix:="$" 983 | TMHKey:=MatchList.settings.FilteredHotkey 984 | StringReplace, TMHKey, TMHKey, &`;amp`;, & , All 985 | StringReplace, TMHKey, TMHKey, &`;, &, All 986 | If (InStr(TMHKey,"ESC")) 987 | hk_prefix:="~" 988 | 989 | Hotkey, % hk_prefix . TMHKey, FilteredMenu, %HotKeyState% ; % 990 | } 991 | 992 | If (InStr(FGHKey BGHKey TMHKey,"Esc")) 993 | EscHotkeys:=1 994 | 995 | Hotkey, IfWinActive 996 | Return 997 | 998 | #If EscHotkeys and MatchList.settings.Everything and Everything_Active() 999 | $Esc:: 1000 | if (A_PriorHotkey <> "$Esc" or A_TimeSincePriorHotkey > 400) 1001 | { 1002 | Keywait Esc 1003 | Return 1004 | } 1005 | Else 1006 | { 1007 | WinClose ahk_exe everything.exe 1008 | WinClose ahk_exe everything64.exe 1009 | } 1010 | Return 1011 | #If 1012 | 1013 | /* 1014 | 1015 | ; use *Enter to open folders in TC panels, disable for now 20250209 1016 | 1017 | #If MatchList.settings.Everything and Everything_Active() 1018 | 1019 | Enter:: ; open in source panel/tab 1020 | TCCD(MatchList.settings.TCPath," /O /S ",Everything_GetSelection(dir="1")) 1021 | Return 1022 | 1023 | ^Enter:: ; open in source panel, new tab foreground 1024 | TCCD(MatchList.settings.TCPath," /O /S /T ",Everything_GetSelection(dir="1")) 1025 | Return 1026 | 1027 | ^+Enter:: ; open in source panel, new tab background 1028 | TCCD(MatchList.settings.TCPath," /O /S /B",Everything_GetSelection(dir="1")) 1029 | Return 1030 | 1031 | !Enter:: ; open in target panel/tab 1032 | TCCD(MatchList.settings.TCPath," /O /S /R=",Everything_GetSelection(dir="1")) 1033 | Return 1034 | 1035 | !^Enter:: ; open in target panel, new tab foreground 1036 | TCCD(MatchList.settings.TCPath," /O /S /T /R=",Everything_GetSelection(dir="1")) 1037 | Return 1038 | 1039 | !+Enter:: ; open in target panel, new tab background 1040 | TCCD(MatchList.settings.TCPath," /O /S /B /R=",Everything_GetSelection(dir="1")) 1041 | Return 1042 | 1043 | #If 1044 | 1045 | TCCD(tc,par,dir) 1046 | { 1047 | WinClose ahk_exe everything.exe 1048 | WinClose ahk_exe everything64.exe 1049 | If !InStr(par,"/R=") 1050 | Run, %tc% %par% "%dir%\" 1051 | Else 1052 | Run, %tc% %par%"%dir%\" 1053 | } 1054 | 1055 | */ 1056 | 1057 | SaveSettings: 1058 | MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp") 1059 | %F4Save%("MatchList", F4ConfigFile) 1060 | FileDelete, % TmpFileList 1061 | Return 1062 | 1063 | ExitSettings: 1064 | FileDelete, % TmpFileList 1065 | If CLI_MenuPos 1066 | MatchList.settings.MenuPos:=CLI_MenuPos 1067 | 1068 | If (Error = 1) ; we can't read settings so create a new clean version 1069 | { 1070 | FileDelete, %F4ConfigFile% 1071 | Gosub, CreateNewConfig 1072 | } 1073 | ExitApp 1074 | Return 1075 | 1076 | ; Used in ProcessFiles() - Technique from http://www.autohotkey.com/docs/scripts/MsgBoxButtonNames.htm 1077 | ChangeButtonNames: 1078 | IfWinNotExist, Maximum files ahk_class #32770 1079 | Return ; Keep waiting... 1080 | SetTimer, ChangeButtonNames, off 1081 | ; WinActivate 1082 | ControlSetText, Button2, Process All, Maximum files ahk_class #32770 1083 | ControlSetText, Button3, Stop at Max., Maximum files ahk_class #32770 1084 | Return 1085 | 1086 | GetAllExtensions: 1087 | AllExtensions:="" 1088 | ; Loop % MatchList.MaxIndex() ; % 1089 | for k, v in MatchList 1090 | AllExtensions .= v.ext "," 1091 | AllExtensions:=Trim(AllExtensions,",") 1092 | AllExtensions:=RegExExtensions(AllExtensions) 1093 | Return 1094 | 1095 | CreateNewConfig: 1096 | if InStr(F4ConfigFile,"xml") 1097 | { 1098 | FileDelete, F4MiniMenu.xml 1099 | FileAppend, 1100 | ( 1101 | 1102 | 1103 | 1104 | F4 1105 | Esc & F4 1106 | 1107 | 1 1108 | 30 1109 | 3 1110 | c:\totalcmd\TotalCmd.exe 1111 | 1112 | 1 1113 | 0 1114 | 0 1115 | z 1116 | 0 1117 | 0 1118 | 2 1119 | 1 1120 | 1 1121 | 1 1122 | 0 1123 | %A_ScriptDir%\logfile.txt 1124 | 1125 | 1126 | c:\WINDOWS\notepad.exe 1127 | txt,xml 1128 | Normal 1129 | 1 1130 | 1131 | 1132 | ), F4MiniMenu.xml, UTF-8 1133 | } 1134 | else ; INI 1135 | { 1136 | FileDelete, F4MiniMenu.ini 1137 | FileAppend, 1138 | ( 1139 | [settings] 1140 | BackgroundHotkey=F4 1141 | ForegroundHotkey=Esc & F4 1142 | FilteredHotkey= 1143 | MaxFiles=30 1144 | MenuPos=3 1145 | FilteredMenuAutoEdit=1 1146 | TCPath=c:\totalcmd\TotalCmd.exe 1147 | TCStart=1 1148 | TCIniPath= 1149 | F4MMCloseAll=0 1150 | F4MMClosePID=0 1151 | FullMenu=z 1152 | Explorer=0 1153 | Everything=0 1154 | MaxWinWaitSec=2 1155 | Lister=1 1156 | FindFiles=1 1157 | QuickView=1 1158 | log=0 1159 | logfile=%A_ScriptDir%\logfile.txt 1160 | [1] 1161 | delay=0 1162 | exe=c:\WINDOWS\notepad.exe 1163 | ext=txt,xml 1164 | method=Normal 1165 | windowmode=1 1166 | ), F4MiniMenu.ini, UTF-16 1167 | } 1168 | Return 1169 | 1170 | 1171 | ; Check DocumentTemplates\ - this setting can be used in F4TCIE.ahk (not required) 1172 | DocumentTemplatesScan: 1173 | If (FileExist(A_ScriptDir "\DocumentTemplates\") = "D") ; " fix highlighting 1174 | { 1175 | templatesExtBeforeScan:=MatchList.Settings["templatesExt"] 1176 | Loop, %A_ScriptDir%\DocumentTemplates\template.* 1177 | { 1178 | SplitPath, A_LoopFileName, , , TemplatesOutExtension 1179 | templatesExt .= TemplatesOutExtension "," 1180 | } 1181 | ; only update when its has been changed 1182 | If (templatesExtBeforeScan <> Trim(templatesExt,",")) 1183 | { 1184 | MatchList.Settings["templatesExt"]:=Trim(templatesExt,",") 1185 | %F4Save%("MatchList", F4ConfigFile) 1186 | } 1187 | templatesExt:="",TemplatesOutExtension:="",templatesExtBeforeScan:="" 1188 | } 1189 | Return 1190 | 1191 | ; Includes 1192 | 1193 | #include %A_ScriptDir%\inc\Menu.ahk 1194 | #include %A_ScriptDir%\inc\FilteredMenu.ahk 1195 | #include %A_ScriptDir%\inc\Settings.ahk 1196 | #include %A_ScriptDir%\inc\Editors.ahk 1197 | #include %A_ScriptDir%\inc\HelperFunctions.ahk ; shared with F4TCIE 1198 | #include %A_ScriptDir%\lib\XA.ahk ; shared with F4TCIE 1199 | #include %A_ScriptDir%\lib\iob.ahk ; shared with F4TCIE 1200 | #include %A_ScriptDir%\lib\class_lv_rows.ahk 1201 | #include %A_ScriptDir%\lib\DropFiles.ahk 1202 | #include %A_ScriptDir%\lib\GetPos.ahk 1203 | #include %A_ScriptDir%\lib\dpi.ahk 1204 | #include %A_ScriptDir%\lib\tc.ahk ; wm_copydata 1205 | #include %A_ScriptDir%\lib\log.ahk 1206 | #include %A_ScriptDir%\lib\AutoXYWH.ahk 1207 | 1208 | ;@Ahk2Exe-IgnoreBegin 1209 | #include *i %A_ScriptDir%\..\ButtonBarKeyboard\ButtonBarKeyboard.ahk 1210 | ;@Ahk2Exe-IgnoreEnd 1211 | -------------------------------------------------------------------------------- /F4TCIE.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Script : F4TCIE.ahk for Total Commander - AutoHotkey 1.1+ (Ansi and Unicode) 4 | Version : 1.3 5 | Author : hi5 6 | Last update : 30 October 2023 7 | Purpose : Helper script for F4MiniMenu program to allow internal editor to function 8 | now you can edit files from within Archives and FTP (and have TC update/upload them) 9 | Notes : It will always use the "normal" method to open programs, so the "drag & drop", "filelist" 10 | and "cmdline" methods will not be used (TC doesn't see file changes when using these methods) 11 | If you are using INI make sure to rename "F4TCIE" to end with an "i" (same method as F4MiniMenu) 12 | Source : https://github.com/hi5/F4MiniMenu 13 | 14 | Setup : TC, Configuration, Edit/View, Editor: 15 | drive:\path-to\F4TCIE.ahk "%1" 16 | 17 | Templates : Create a DocumentTemplates\ folder and place files for each template you'd like to use for 18 | the Shift-F4 'enter file name to edit' function of TC. File names are template.ext 19 | This will copy the template.ext to the panel with the new name so you can work on it the 20 | defined editor. Not all programs allow empty files at start up so this will resolve that 21 | problem for say Office applications or Graphics programs. 22 | See DocumentTemplates\readme.md for more info. 23 | 24 | */ 25 | 26 | #Requires AutoHotkey v1.1.31+ 27 | #NoTrayIcon 28 | #NoEnv 29 | 30 | ; 31 | ;@Ahk2Exe-SetFileVersion 1.3 32 | ;@Ahk2Exe-SetProductName F4MiniMenu (IE) 33 | ;@Ahk2Exe-SetDescription F4MiniMenu (IE): Open files from TC 34 | ;@Ahk2Exe-SetProductVersion Compiled with AutoHotkey v%A_AhkVersion% 35 | ;@Ahk2Exe-SetCopyright MIT License - (c) https://github.com/hi5 36 | ; 37 | 38 | SetWorkingDir, %A_ScriptDir% 39 | 40 | File=%1% ; cmd line parameter "%1" it receives from TC 41 | SplitPath, File, , , OutExtension 42 | StringUpper, OutExtension, OutExtension 43 | 44 | If !File ; if empty 45 | ExitApp 46 | 47 | ; shared with F4MM 48 | #Include %A_ScriptDir%\inc\LoadSettings1.ahk 49 | #Include %A_ScriptDir%\inc\LoadSettings2.ahk 50 | 51 | If Error 52 | { 53 | MsgBox, 16, F4MiniMenu/F4TCIE, Couldn't load configuration file (%F4ConfigFile%), closing script and starting default Windows editor.`n`nMay not work if there is no "Edit" defined for this filetype:`n`n%OutExtension%`n`nNote: do check if F4MiniMenu/F4TCIE have the same naming convention (for INI both program names have to end with an "i")`nSee "XML or INI" https://github.com/hi5/F4MiniMenu/blob/master/readme.md 54 | Try 55 | Run edit "%file%" ; run Windows editor for this filetype 56 | Catch 57 | Run %A_WinDir%\notepad.exe "%file%" ; alas no type defined so run notepad as a last resort 58 | ExitApp 59 | } 60 | 61 | templateExt:=MatchList.Settings.templatesExt 62 | 63 | ; shared with F4MM 64 | #Include %A_ScriptDir%\inc\TotalCommanderPath.ahk 65 | 66 | for k, v in MatchList 67 | { 68 | if (k = "settings") 69 | continue 70 | if (v.ext = "") ; reported by Ovg if EXT is empty it would not launch the default editor 71 | continue 72 | if RegExMatch(OutExtension,RegExExtensions(v.ext)) ; Open in defined program - v0.9 allow for wildcards 73 | { 74 | ;editor:=GetTCCommander_Path(v.exe) 75 | editor:=GetPath(v.exe) 76 | If OutExtension in %templateExt% 77 | { 78 | IfExist, %file% ; file is already present, this could be that TC created it just now (0 bytes) or that is already existed. 79 | { 80 | FileGetSize, NewFileSize, %file% 81 | If (NewFileSize = 0) ; TC created it, so overwrite with our template, otherwise don't. This to avoid overwriting existing documents. 82 | FileCopy, %A_ScriptDir%\DocumentTemplates\template.%OutExtension%, %file%, 1 83 | } 84 | } 85 | if editor 86 | { 87 | Sleep % v.delay 88 | Try 89 | { 90 | Run "%editor%" "%file%" 91 | Sleep 100 ; added explicit Exit as compiled version sometimes kept running 30/10/2023 92 | ExitApp 93 | } 94 | Catch 95 | { 96 | editor:=GetPath(matchlist[1].exe) 97 | Run "%editor%" "%file%" 98 | ; OSDTIP_Pop(MainText, SubText, TimeOut, Options, FontName, Transparency) 99 | OSDTIP_Pop("F4MiniMenu/F4TCIE", "Defined editor/program not found`nReverting to default editor", -750,"W230 H80 U1") 100 | Sleep 100 ; added explicit Exit as compiled version sometimes kept running 30/10/2023 101 | ExitApp 102 | } 103 | } 104 | ExitApp ; we only have one file to process so we're done 105 | } 106 | } 107 | 108 | ; We couldn't find a defined Editor so launch the default Editor [1] 109 | editor:=GetPath(matchlist[1].exe) 110 | Run "%editor%" "%file%" 111 | Sleep 100 ; added explicit Exit as compiled version sometimes kept running 30/10/2023 112 | ExitApp 113 | 114 | ; shared with F4MM 115 | #include %A_ScriptDir%\inc\HelperFunctions.ahk 116 | 117 | ; just for loading the Matchlist object, we don't need all the rest 118 | #include %A_ScriptDir%\lib\xa.ahk 119 | #include %A_ScriptDir%\lib\iob.ahk 120 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | 3 | * 20250209 - v1.47 a) Allow resizing of Configure Editors GUI (browse list) using AutoXYWH() 4 | b) Some code cleanup re Enter shortcuts; add everything64.exe to Esc Winclose routine 5 | c) Trace menu steps and result of GetFiles in log 6 | 7 | * 20250209 - v1.46 a) Finetuning Everything_GetSelection() to check for selected rows in listview (if none get first result only) 8 | 9 | * 20250208 - v1.45 a) Finetuning Everything_Active() (using "A" not "Everything" in WinGet to detect active window) 10 | b) Use TXT as default extension for default editor if user doesn't set one - otherwise it would not match correctly for defined extensions https://www.ghisler.ch/board/viewtopic.php?p=468305#p468305 11 | c) log option (manual setting, don't document) 12 | 13 | * 20250208 - v1.44 a) Add Everything64.exe to ahk_group TCF4Windows; updated Everything-functions to check for Everything.exe or Everything64.exe - added notes to help tip and docs 14 | 15 | * 20250111 - v1.43 a) Fix: moved INI selection routine introduced in v1.42 as it interferred with selecting a (new) editor https://www.ghisler.ch/board/viewtopic.php?p=466621#p466621 16 | b) Additional hint in "Other programs" section re Hotkey to "Copy File Name(s) with Full Path" 17 | c) Added two ;@Ahk2Exe-Set* for compiled script properties (incl. AutoHotkey version) 18 | 19 | * 20240130 - v1.42 a) New: Enable/Disable using F4MM in Lister, Find Files and QuickView (Use elsewhere in TC) 20 | Fix: Resort to reading multiple locations in the registry + settings option to locate `wincmd.ini` to be able to read `F4Edit` setting 21 | and additional setting `INI Path` 22 | Hopefully this is now correctly handled in all cases (F4MM starts before TC, TC starts before F4MM) 23 | 24 | * 20240127 - v1.41 a) Fix: Check to see if TC is running in order to be able to read F4Edit= correctly (using environment variable %Commander_ini_Path%) 25 | 26 | * 20240123 - v1.4 a) New: enable/disable F4MM for Lister and Find Files (search results) windows (see settings). If Lister setting is active and F4Edit>1 in wincmd.ini: close Lister 27 | In TC 11.03 the press "F4 to open currently viewed file in Lister" was added. 28 | (See F4Edit= options in TC help file on how to handle F4 in lister via wincmd.ini. F4TCIE _could_ be used.) 29 | 30 | * 20231121 - v1.3 31 | a) Fix: `%N` and `%M` now processed correctly 32 | b) Added "#Requires AutoHotkey v1.1.31+" directive for users with v1 & v2 installed, added note in documention about using v1 AutoHotkey.exe in setup 33 | 34 | * 20231030 - v1.2 35 | a) Updated class name for Find Results control class (TMyListBox2, 32bit) for TC11 36 | b) Added: Help MsgBox-es in Settings Gui now Task Modal (32+8192=8224) 37 | c) Added: Settings label to Gui to better handle closing the Gui https://github.com/hi5/F4MiniMenu/issues/24#issuecomment-1573127847 38 | d) Added: GuiEscape for Add/Modify editors dialog to allow Esc to exit (next to Alt+c) https://github.com/hi5/F4MiniMenu/issues/24#issuecomment-1573127847 39 | e) Fix: no longer require full path for programs in PATH e.g. `write.exe` v `c:\windows\write.exe`, bug introduced in v1.1 due to GetFullPathName() https://github.com/hi5/F4MiniMenu/issues/24#issuecomment-1573127847 40 | f) Fix: use SplitPath for `%p` parameter when not using TC https://github.com/hi5/F4MiniMenu/issues/24#issuecomment-1573127847 41 | g) Change: `%p` and `%t` now use wm_copydata 42 | h) New: `%N` and `%M` to place filename under the cursor into the command line (source and target directory) using wm_copydata 43 | i) New: Added support for `%$DATE%`, `%$DATE:YMD%` + offset calculations via `%$DATE:YMD|value|timeunits%` 44 | j) Fix: F4TCIE quote file path for `%file%` to resolve paths\files with spaces 45 | k) Fix: F4TCIE `Run notepad` changed to `Run %A_WinDir%\notepad.exe` to avoid any potential path issues. Added ExitApp after Run command 46 | 47 | * 20230402 - v1.1 48 | a) Fix: TRY to catch all empty hotkeys to avoid errors at startup 49 | b) Change: Double click on an "editor" in Configure Editors listview now opens modify window 50 | c) Change: Settings - replace Radio controls for Esc/Win with DropDownLists (not thoroughly tested) 51 | d) Fix: WinMin/Hide/Maximize and Sleep function should work better (or again) 52 | e) Fix: additional check to prevent Modify Gui throwing "The same variable cannot be used for more than one control" error; modify window now always on top of editors window (); sysmenu removed 53 | f) New: TRY, catch -> revert to standard editor if defined editor can not be found, show notification using OSDTIP_Pop() for both F4MiniMenu and F4TCIE 54 | g) New: support `%windir%`, `%A_ScriptDir%` and other path variables (see list "Path variables" in readme.md) https://github.com/hi5/F4MiniMenu/issues/25 55 | h) New: Filtered foreground Menu - setting to launch program directly if only one program is found https://github.com/hi5/F4MiniMenu/issues/26 56 | i) New: Global setting MaxWinWaitSec to prevent stalling F4MM 57 | j) Fix: INI when reading a global setting as "Error" set as empty (lib\iob.ahk) 58 | * 20220528 - v1.0 59 | a) Fix: "Start Total Commander if not running" feature #23 https://github.com/hi5/F4MiniMenu/issues/23 60 | b) Fix: Use another method to calculate Y for Position = 2 in GetPos (as this is now default for c)) 61 | c) Rudimentary support for Windows Explorer, Double Commander, XYPlorer, and Everything(e) (default foreground menu to center in Window) 62 | d) Passive mode using parameters to use F4MiniMenu via Button bar, Start Menu, or F4 Editor (start F4MM, processes files, close F4MM, so not a persistent script) 63 | e) Fix: Path from Lister Windows Title failed if file name started/ended with [ or ] characters e.g. "[2000] My Document.txt" 64 | f) remove stray file inc\inc.zip from repository 65 | * 20190622 - v0.97 66 | 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 67 | b) Fix: correctly use %commander_path% in Editor listview IL_Add routine (if v.Icon isn't set) 68 | c) Fix: Editor - Set as Default should now work correctly 69 | d) Fix: Editor - cancel should now work more reliably by using .clone() 70 | e) Only save settings when actually changing them e.g. no longer at each start/exit of the script 71 | f) New: Option(s) to Close F4MiniMenu when TC closes 72 | * 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 73 | * 20190606 - v0.96.1 - Fix: adding close F4MiniMenu setting to INI version (iob.ahk) https://www.ghisler.ch/board/viewtopic.php?p=355998#p355998 74 | * 20190527 - v0.96 75 | a) Added options to "Total Commander" startup settings on request https://www.ghisler.ch/board/viewtopic.php?p=355595#p355595 (always start, close F4MiniMenu) 76 | b) dpi + fix to avoid Gui error when calling New editor from menu while Browse Gui was active. 77 | c) tray menu: icons, left click opens tray menu, added "Open" to check key history etc. 78 | * 20170710 - v0.95 Added F4TCIE and introduced DocumentTemplates. #13 https://github.com/hi5/F4MiniMenu/issues/13 79 | New icon :-) 80 | * 20170607 - v0.94c Minor fix to empty file and quoted startdir variables in GetInput(). Fix for %ComSpec% in Editor names. 81 | * 20170106 - v0.94b Minor fix to ensure Commander_Path is not empty 82 | * 20170105 - v0.94a Minor fix for launching via Drag&Drop (no longer worked correctly/reliably in v0.94) 83 | * 20161231 - v0.94 84 | a) Added 4th method: cmdline -> program.exe file1 file2 file3 #14 https://github.com/hi5/F4MiniMenu/issues/14 85 | b) Accept TC Fields %P %T %O %E and ? in Parameters and Startdir. Introduced %f41. #15 https://github.com/hi5/F4MiniMenu/issues/15 86 | c) Build foreground menu only once vs delete/recreate (updating menu only after editing editors). Refactored menu code. 87 | d) Now use %TEMP%\$$f4mtmplist$$.m3u instead of ScriptFolder - [requested by Ovg](http://ghisler.ch/board/viewtopic.php?p=319773&sid=2e2472aec32f6906e699d095b4998ea3#319773) 88 | e) Fixed hotkeys - #12 https://github.com/hi5/F4MiniMenu/issues/12 89 | f) You can now specify an Icon and Menu name when you configure an Editor. #17 https://github.com/hi5/F4MiniMenu/issues/17 90 | g) %Commander_Path% now accepted in Editor and Icon paths. 91 | h) Removed F4MiniMenui.ahk - to use INI simply rename/copy the (compiled) script to end with "i". 92 | * 20161023 - v0.93 OpenFile: add WinWait before WinActivate, merge request @nameanyone #10 https://github.com/hi5/F4MiniMenu/issues/10 93 | * 20160618 - v0.92 Fix error checking on startup in case script is compiled - HT Ovg 94 | * 20160618 - v0.91 Fix for INI Editors include (save to INI not XML when making backup). Refinement of regular expression for wildcards - HT [Ovg](http://ghisler.ch/board/viewtopic.php?p=310538#310538) 95 | * 20160618 - v0.9 Added support for wildcards (? and *) in extensions #6 https://github.com/hi5/F4MiniMenu/issues/6. Added open delay (delay in ms between opening files) 96 | * 20160617 - v0.83 Adding specific #include path for lib files to avoid possible error for portable users when compiling. HT [Ovg](ghisler.ch/board/viewtopic.php?p=310187#310187) 97 | * 20151104 - v0.82 Further refinement of confusing error message at very first startup (missing configuration XML) - now also checks if BAK is present. 98 | * 20151103 - v0.81 Fixed confusing error message at very first startup (missing configuration XML) 99 | * 20141107 - v0.8 Added F4 functions to Lister (grabbing the filename from the Window title) and the search results in the Find Files dialog. Comment: if you use the Esc & Key as Foreground menu option it will fail as pressing Esc will close Lister and the Find Files dialog. The Winkey & Key combination does work - the menu will appear at the top of the window. 100 | * 20140806 - v0.7 replaced Loop, object.MaxIndex() with proper for-loop to parse each key-value pair in the MatchList object; Added &letter to foreground menu options (program names) 101 | * 20130731 - v0.61 added rudimentary backup & safety feature in case of a faulty/missing settings XML 102 | * 20130701 - v0.6 a) [Class LV_Rows](http://www.autohotkey.com/board/topic/94364-class-lv-rows-copy-cut-paste-and-drag-listviews/) by [Pulover](https://github.com/Pulover/) replaces [LV_MoveRow()](http://www.autohotkey.com/board/topic/56396-techdemo-move-rows-in-a-listview/). 103 | This resolves the problem with the listview not updating icons while moving the editors in the settings Gui; 104 | b) Added Unicode support for drag & drop method so F4MiniMenu should now be compatible with both Ansi and Unicode versions of AutoHotkey. 105 | * 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. 106 | * 20130330 - v0.5 a) Process entire file list first and open per program; 107 | b) Introduced [Filelist](readme.md#filelist) method; 108 | c) Removed "Open Mode". 109 | * 20121117 - v0.4 Configuration GUIs, tray menu. First editor now considered default editor. 110 | * 20121111 - v0.3 Added menu for "foreground" feature - open all selected files with specific editor (its behaviour may change in future). 111 | * 20121108 - v0.2 Added 0 (zero) entry in XML as default editor. 112 | * 20121101 - v0.1 Initial very basic version. 113 | 114 | -------------------------------------------------------------------------------- /img/f4-configure-editors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hi5/F4MiniMenu/34d131ef7b47bef92dd4e120032674ac249ce5b3/img/f4-configure-editors.png -------------------------------------------------------------------------------- /img/f4-confirm-maximum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hi5/F4MiniMenu/34d131ef7b47bef92dd4e120032674ac249ce5b3/img/f4-confirm-maximum.png -------------------------------------------------------------------------------- /img/f4-editor-setttings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hi5/F4MiniMenu/34d131ef7b47bef92dd4e120032674ac249ce5b3/img/f4-editor-setttings.png -------------------------------------------------------------------------------- /img/f4-foreground-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hi5/F4MiniMenu/34d131ef7b47bef92dd4e120032674ac249ce5b3/img/f4-foreground-menu.png -------------------------------------------------------------------------------- /img/f4-general-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hi5/F4MiniMenu/34d131ef7b47bef92dd4e120032674ac249ce5b3/img/f4-general-settings.png -------------------------------------------------------------------------------- /inc/CLIParser.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | CLIParser to start F4MiniMenu via F4 (editor), Buttonbar or Startmenu 3 | 4 | F4MiniMenu %L /P? /M? 5 | 6 | /P1 = Menu position at Mouse cursor 7 | /P2 = Menu position Centered in window 8 | (see GetPos.ahk) 9 | 10 | /M1 = Full menu 11 | /M2 = Filtered menu 12 | 13 | /SET = open settings 14 | 15 | /ED = open editors 16 | 17 | */ 18 | 19 | If (A_Args.Length() <> 0) 20 | { 21 | CLI_Exit:=1 22 | CLI_File:=A_Args[1] 23 | for k, v in A_Args 24 | { 25 | if (v = "/P1") 26 | { 27 | CLI_MenuPos:=MatchList.settings.MenuPos 28 | MatchList.settings.MenuPos:=1 29 | } 30 | if (v = "/P2") 31 | { 32 | CLI_MenuPos:=MatchList.settings.MenuPos 33 | MatchList.settings.MenuPos:=2 34 | } 35 | if (v = "/M1") 36 | CLI_ShowMenu:=1 37 | if (v = "/M2") 38 | CLI_FilteredMenu:=1 39 | if (v = "/SET") 40 | CLI_Settings:=1 41 | if (v = "/ED") 42 | CLI_Editors:=1 43 | } 44 | If MatchList.Settings.log 45 | Log(A_Now " : CLI Params -> CLI_ShowMenu: " CLI_ShowMenu " CLI_FilteredMenu: " CLI_FilteredMenu "CLI_Settings: " CLI_Settings " CLI_Editors: " CLI_Editors,MatchList.Settings.logFile) 46 | } 47 | -------------------------------------------------------------------------------- /inc/Editors.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Gui for managing Editors 4 | Include for F4MiniMenu.ahk 5 | 6 | */ 7 | 8 | ; This label is used when "Add new Editor" is selected in the foreground menu, 9 | ; we only need to set a variable and the proceed with the regular editor Gui 10 | 11 | ConfigEditorsNew: 12 | New:=1 13 | 14 | 15 | ConfigEditors: 16 | 17 | ; Variables 18 | 19 | ; Backup Object so we can use this for CANCEL 20 | Backup:=MatchList.Clone() 21 | 22 | GetList:="Exe|Parameters|StartDir|WindowMode|Ext|Method|Delay|Open|Editor|Icon|Name" 23 | 24 | infotext= 25 | (join`n 26 | Important: 27 | 1 - The first editor will be considered to the default editor. 28 | 29 | Info: 30 | 1 - Delay (in miliseconds) D&&D = Drag && Drop, Open = startup. 31 | 2 - Sort using Ctrl+UP / Ctrl+DOWN or use Edit menu 32 | (multiple rows possible). 33 | ) 34 | 35 | IfWinExist, F4MiniMenu - Editor Settings ahk_class AutoHotkeyGUI 36 | { 37 | WinActivate, F4MiniMenu - Editor Settings ahk_class AutoHotkeyGUI 38 | If New 39 | Gosub, NewEditor 40 | Return 41 | } 42 | 43 | Gui, Browse: +Resize +MinSize790x427 44 | 45 | Menu, EditMenu, Add, Move Up`tCtrl+Up, MoveUp 46 | Menu, EditMenu, Add, Move Down`tCtrl+Down, MoveDown 47 | Menu, MenuBar, Add, %A_Space%Edit, :EditMenu 48 | Gui, Browse:Menu, MenuBar 49 | 50 | ; INI Gui 51 | Gui, Browse:font, % dpi("s8") 52 | Gui, Browse:Add, ListView, % dpi("x6 y5 w780 h285 grid hwndhLV vLV gLVLabel"), Program|Parameters|Start Dir.|Window|Extensions|Method|D&D|Open|Editor|Icon|Name 53 | Gui, Browse:Add, GroupBox, % dpi("x6 yp+290 w390 h120 vGroupBoxInfo"), Comments 54 | Gui, Browse:Add, Text, % dpi("x16 yp+20 w340 vInfoText"), %infotext% 55 | Gui, Browse:Add, Button, % dpi("xp+445 yp w70 h24 gSettings vButtonSettings"), &Settings 56 | Gui, Browse:Add, Button, % dpi("xp+80 yp w70 h24 gAdd vButtonAdd"), &Add 57 | Gui, Browse:Add, Button, % dpi("xp+80 yp w70 h24 gModify vButtonModify"), &Modify 58 | Gui, Browse:Add, Button, % dpi("xp+80 yp w70 h24 gRemove vButtonRemove"), &Remove 59 | Gui, Browse:Add, Button, % dpi("xp-240 yp+40 w150 h24 gOK vButtonOK"), &OK 60 | Gui, Browse:Add, Button, % dpi("xp+160 yp w150 h24 gCancel vButtonCancel"), &Cancel 61 | Gui, Browse:Add, Link, % dpi("xp-160 yp+40 w310 h16 vLinkText"), F4MiniMenu %F4Version% -- More info at Github.com/hi5/F4MiniMenu 62 | Gosub, UpdateListview 63 | LvHandle := New LV_Rows(hLV) 64 | Gui, Browse:Show, % dpi("x261 y211 h427 w790 center"), F4MiniMenu - Editor Settings 65 | 66 | Sleep 100 67 | 68 | BrowseGuiSize: 69 | If (A_EventInfo = 1) ; The window has been minimized. 70 | Return 71 | AutoXYWH("w h" , "Lv") 72 | AutoXYWH("y" , "GroupBoxInfo") 73 | AutoXYWH("y" , "InfoText") 74 | AutoXYWH("x y" , "ButtonSettings") 75 | AutoXYWH("x y" , "ButtonAdd") 76 | AutoXYWH("x y" , "ButtonModify") 77 | AutoXYWH("x y" , "ButtonRemove") 78 | AutoXYWH("x y" , "ButtonOK") 79 | AutoXYWH("x y" , "ButtonCancel") 80 | AutoXYWH("x y" , "LinkText") 81 | ControlGetPos, , , OutWidth, , Syslistview321, F4MiniMenu - Editor Settings 82 | LV_ModifyCol(1, (dpifactor*250) + (OutWidth-780)) 83 | Return 84 | 85 | NewEditor: 86 | If (New = 1) ; we choose "Add new Editor in foreground menu" 87 | { 88 | Gosub, Add 89 | ; get list of selected files so we can set the Extensions automatically 90 | SelectedExtensions:="" 91 | Files:=GetFiles() 92 | Loop, parse, Files, `n, `r 93 | { 94 | SplitPath, A_LoopField, , , OutExtension 95 | If OutExtension not in %SelectedExtensions% 96 | SelectedExtensions .= OutExtension "," 97 | } 98 | SelectedExtensions:=Rtrim(SelectedExtensions,",") 99 | GuiControl,Modify: , Ext, %SelectedExtensions% 100 | SelectedExtensions:="" 101 | Files:="" 102 | } 103 | 104 | New:=0 105 | Return 106 | 107 | ; Approved chances, read ListView to store new or changed data 108 | Ok: 109 | Backup:=[] 110 | Backup:=MatchList.settings 111 | MatchList:=[] 112 | MatchList.settings:=Backup 113 | Gui, Browse:Default 114 | Gui +LastFound 115 | Loop, % LV_GetCount() ; % 116 | { 117 | Row:=A_Index 118 | Loop, parse, GetList, | 119 | LV_GetText(%A_LoopField%, Row, A_Index) 120 | MatchList[Row,"Exe"]:=Exe 121 | MatchList[Row,"Parameters"]:=Parameters 122 | MatchList[Row,"StartDir"]:=StartDir 123 | MatchList[Row,"Method"]:=Method 124 | MatchList[Row,"WindowMode"]:=WindowMode 125 | MatchList[Row,"Ext"]:=Ext 126 | MatchList[Row,"Delay"]:=Delay 127 | MatchList[Row,"Open"]:=Open 128 | MatchList[Row,"Icon"]:=Icon 129 | MatchList[Row,"Name"]:=Name 130 | } 131 | 132 | If (Trim(MatchList.1.Ext,"`n`r`t ") = "") 133 | MatchList.1.Ext:="txt" ; safety as we need at least one extension for the default editor 134 | 135 | Backup:="" 136 | %F4Save%("MatchList",F4ConfigFile) 137 | Gui, Browse:Destroy 138 | Gosub, BuildMenu 139 | Gosub, GetAllExtensions 140 | Return 141 | 142 | BrowseGuiEscape: 143 | Cancel: 144 | MatchList:=[] 145 | MatchList:=Backup 146 | Backup:="" 147 | Gosub, BuildMenu 148 | Gosub, BrowseGuiClose 149 | Return 150 | 151 | Remove: 152 | Ask:="" 153 | Gui, Browse:Default 154 | Gui, Browse:Submit, NoHide 155 | SelItem := LV_GetNext() 156 | If (SelItem = 0) 157 | SelItem = 1 158 | LV_GetText(Ask, SelItem, 1) 159 | MsgBox, 52, Remove editor (one entry),Do you want to remove:`n%Ask%? 160 | IfMsgBox, Yes 161 | { 162 | LV_Delete(SelItem) 163 | MatchList.Remove(Editor) 164 | } 165 | Gosub, BuildMenu 166 | Return 167 | 168 | ; We can use the same Gui to ADD or MODIFY an editor we only need 169 | ; to set a variable and the proceed with the regular Modify Gui 170 | 171 | Add: 172 | New:=1 173 | 174 | Modify: 175 | 176 | Gui, Modify:Destroy ; https://www.ghisler.ch/board/viewtopic.php?p=423475#p423475 177 | 178 | ; Clear variables just to be sure 179 | Loop, parse, GetList, | 180 | %A_LoopField%:="" 181 | 182 | If New 183 | { 184 | Delay:=0 185 | Method:="Normal" 186 | WindowMode:=1 187 | } 188 | 189 | ; We want to modify existing entry, get info from listview and set variables for use in Gui 190 | If !New 191 | { 192 | Gui, Browse:Default 193 | Gui, Browse:Submit, NoHide 194 | SelItem := LV_GetNext() 195 | If (SelItem = 0) 196 | SelItem = 1 197 | Loop, parse, GetList, | 198 | { 199 | LV_GetText(%A_LoopField%, SelItem, A_Index) 200 | } 201 | } 202 | 203 | Gui, Modify:+OwnerBrowse -SysMenu 204 | Gui, Modify:font, % dpi("s8") 205 | Gui, Modify:Add, Text, % dpi("x10 y10 w77 h18"), &Exe 206 | Gui, Modify:Add, Edit, % dpi("x89 y8 w290 h20 vExe"), %Exe% 207 | Gui, Modify:Add, Button, % dpi("x386 y8 w30 h20 gSelectExe"), >> 208 | Gui, Modify:Add, Checkbox, % dpi("x426 y8 w200 h20 vDefault"), Set as &Default 209 | 210 | Gui, Modify:Add, Text, % dpi("x10 yp+32 w77 h18"), &Icon 211 | Gui, Modify:Add, Edit, % dpi("x89 yp-2 w170 h20 vIcon"), %Icon% 212 | Gui, Modify:Add, Button, % dpi("x266 yp w30 h20 gSelectIcon"), >> 213 | Gui, Modify:Add, Text, % dpi("xp+41 yp+2 w60 h18"), Menu &Name 214 | Gui, Modify:Add, Edit, % dpi("xp+70 yp-2 w150 h20 vName"), %Name% 215 | 216 | Gui, Modify:Add, Text, % dpi("x10 yp+32 w77 h16"), Para&meters 217 | Gui, Modify:Add, Edit, % dpi("x89 yp-2 w438 h20 vParameters"), %Parameters% 218 | 219 | Gui, Modify:Add, Text, % dpi("x10 yp+32 w77 h16"), &Start Dir 220 | Gui, Modify:Add, Edit, % dpi("x89 yp-2 w323 h20 vStartDir"), %StartDir% 221 | Gui, Modify:Add, Button, % dpi("xp+328 yp h20 w110 gCopyPath"), Copy path from Exe. 222 | 223 | Gui, Modify:Add, Text, % dpi("x10 yp+32 w78 h28"), &Method 224 | If (Method = "Normal") 225 | Method:=1 226 | Else If (Method = "DragDrop") 227 | Method:=2 228 | Else If (Method = "FileList") 229 | Method:=3 230 | Else If (Method = "cmdline") 231 | Method:=4 232 | Gui, Modify:Add, DropDownList, % dpi("x89 yp-3 w238 h21 R4 Choose" Method " vMethod AltSubmit"), 1 - Normal|2 - Drag & Drop|3 - FileList|4 - cmdline 233 | 234 | Gui, Modify:Add, Text, % dpi("xp+250 yp+3 h16"), [Delays] D&&D: 235 | Gui, Modify:Add, Edit, % dpi("xp+70 yp-3 h20 w40 vDelay Number"), %Delay% 236 | Gui, Modify:Add, Text, % dpi("xp+45 yp+3 h16"), Open: 237 | Gui, Modify:Add, Edit, % dpi("xp+32 yp-3 h20 w40 vOpen Number"), %Open% 238 | 239 | Gui, Modify:Add, Text, % dpi("x10 yp+32 w78 h28"), &Window 240 | Gui, Modify:Add, DropDownList, % dpi("x89 yp-3 w238 h21 R3 Choose" WindowMode " vWindowMode AltSubmit"), 1 - Normal|2 - Maximized|3 - Minimized 241 | 242 | ;Gui, Modify:Add, Text, x10 y160 w78 h16, &Open Mode 243 | ;Gui, Modify:Add, DropDownList, x89 y158 w438 h21 Choose%Mode% vMode AltSubmit, (not yet implemented)| 244 | ;Gui, Modify:Default 245 | ;GuiControl, Disable, Mode 246 | 247 | Gui, Modify:Add, Text, % dpi("x10 yp+32 w77 h80"), Ex&tensions (Default editor must have at least one ext.`nTXT is set if not defined) 248 | Gui, Modify:Add, Edit, % dpi("x89 yp-2 w438 h80 vExt"), %Ext% 249 | 250 | Gui, Modify:Add, Link, % dpi("x10 yp+100 w310 h16"), F4MiniMenu %F4Version% --- More info at Github.com/hi5/F4MiniMenu 251 | 252 | Gui, Modify:Add, Button, % dpi("x340 yp-5 w90 h24"), &OK 253 | Gui, Modify:Add, Button, % dpi("x437 yp w90 h24"), &Cancel 254 | 255 | Gui, Modify:Show, % dpi("w542 center"), Editor configuration 256 | Return 257 | 258 | SelectIcon: 259 | FileSelectFile, Icon, 3, , Select Icon, Icon (*.ico) 260 | if (Icon = "") 261 | Return 262 | GuiControl, Modify: ,Icon,%Icon% 263 | 264 | Return 265 | 266 | SelectExe: 267 | Exe:="" 268 | FileSelectFile, Exe, 3, , Select program, Executables (*.exe`;*.cmd`;*.bat`;*.com`;*.ahk) 269 | if (Exe = "") 270 | Return 271 | 272 | If WinActive("Editor configuration") 273 | { 274 | ; New program so no doubt new StartDir and Parameters, clear Gui controls 275 | GuiControl, Modify: ,Exe, %Exe% 276 | GuiControl, Modify: ,Icon,%Icon% 277 | GuiControl, Modify: ,Name,%Name% 278 | GuiControl, Modify: ,StartDir, 279 | GuiControl, Modify: ,Parameters, 280 | GuiControl, Modify: ,Delay,0 281 | GuiControl, Modify: ,Open,0 282 | } 283 | Else If WinActive("Settings") and (Exe) 284 | { 285 | GuiControl, ,TCPath, %Exe% 286 | } 287 | Return 288 | 289 | SelectIni: 290 | FileIni:="" 291 | FileSelectFile, FileIni, 3, , Select TC INI location, INI (*.ini) 292 | if (FileIni = "") 293 | Return 294 | 295 | If WinActive("Settings") and (FileIni) 296 | { 297 | GuiControl, ,TCIniPath, %FileIni% 298 | } 299 | Return 300 | 301 | ; Note: deactivated Everything Directory Tree settings for now 302 | /* 303 | SelectEv: 304 | FileSelectFile, EvPath, 3, c:\program files\everything\, Path to Everything, Executable (*.exe) 305 | if (EvPath = "") 306 | Return 307 | 308 | If WinActive("Settings") 309 | { 310 | GuiControl, ,EvPath, %EvPath% 311 | } 312 | Return 313 | */ 314 | 315 | CopyPath: 316 | GuiControlGet, CopyPath, ,Exe 317 | SplitPath, CopyPath, , StartDir 318 | GuiControl, Modify: , StartDir, %StartDir%\ 319 | CopyPath:="" 320 | Return 321 | 322 | ModifyButtonOK: 323 | Gui, Modify:Default 324 | Gui, Submit, NoHide 325 | If (Editor = "") ; we have a new editor 326 | Editor:=MatchList.MaxIndex() + 1 327 | 328 | MatchList[Editor,"Exe"]:=Exe 329 | MatchList[Editor,"Icon"]:=Icon 330 | MatchList[Editor,"Name"]:=Name 331 | MatchList[Editor,"Parameters"]:=Parameters 332 | MatchList[Editor,"StartDir"]:=StartDir 333 | If (Method = 1) 334 | Method:="Normal" 335 | Else If (Method = 2) 336 | Method:="DragDrop" 337 | Else If (Method = 3) 338 | Method:="FileList" 339 | Else If (Method = 4) 340 | Method:="cmdline" 341 | MatchList[Editor,"Method"]:=Method 342 | MatchList[Editor,"WindowMode"]:=WindowMode 343 | 344 | StringReplace, Ext, Ext, `r`n, , All 345 | StringReplace, Ext, Ext, `n, , All 346 | StringReplace, Ext, Ext, `r, , All 347 | MatchList[Editor,"Ext"]:=Ext 348 | 349 | If (Trim(MatchList.1.Ext,"`n`r`t ") = "") 350 | MatchList.1.Ext:="txt" ; safety as we need at least one extension for the default editor 351 | 352 | MatchList[Editor,"Delay"]:=Delay 353 | MatchList[Editor,"Open"]:=Open 354 | MatchList[Editor,"Editor"]:=Editor 355 | 356 | If Default 357 | { 358 | DefaultMatchEditor:=[] 359 | DefaultMatchEditor:=MatchList[Editor] 360 | DefaultMatchEditor["Editor"]:="" 361 | MatchList.Remove(Editor) 362 | MatchList.InsertAt(1,DefaultMatchEditor) 363 | DefaultMatchEditor:="" 364 | } 365 | 366 | Gui, Modify:Destroy 367 | Gui, Browse:Default 368 | 369 | If (Editor = Matchlist.MaxIndex()) or (Default) 370 | Gosub, UpdateListview 371 | Else 372 | LV_Modify(SelItem, "",Exe,Parameters,StartDir,WindowMode,Ext,Method,Delay,Open,Editor,Icon,Name) 373 | New:=0,Default:=0 374 | Gosub, BuildMenu 375 | Return 376 | 377 | ModifyGuiEscape: 378 | ModifyButtonCancel: 379 | ModifyGuiClose: 380 | New:=0 381 | Gui, Modify:Destroy 382 | Return 383 | 384 | BrowseGuiClose: 385 | Gui, Browse:Destroy 386 | Return 387 | 388 | UpdateListview: 389 | Gui, Browse:Default 390 | 391 | ; Icon wizardry comes directly from AutoHotkey Listview documentation 392 | ; It works with both Ansi & Unicode versions 393 | ; Calculate buffer size required for SHFILEINFO structure. 394 | sfi_size := A_PtrSize + 8 + (A_IsUnicode ? 680 : 340) 395 | VarSetCapacity(sfi, sfi_size) 396 | 397 | IL_Destroy(ImageListID1) 398 | ; Create an ImageList so that the ListView can display some icons: 399 | ImageListID1 := IL_Create(65, 10, IconSize) 400 | ; Attach the ImageLists to the ListView so that it can later display the icons: 401 | LV_SetImageList(ImageListID1) 402 | LV_Delete() 403 | Count=0 404 | ; Loop % MatchList.MaxIndex() ; Exe|Parameters|StartDir|WindowMode|Ext|Method|Delay|Editor|Icon|Name ; % 405 | for k, v in MatchList 406 | { 407 | If (k = "settings") or (k = "temp") 408 | Continue 409 | FileName := v.Exe ; Must save it to a writable variable for use below. 410 | If (FileName = "") 411 | Continue 412 | If (v.Icon <> "") 413 | ; FileName := StrReplace(v.Icon,"%Commander_Path%",Commander_Path) 414 | FileName := GetPath(v.Icon) 415 | 416 | If InStr(FileName,"%Commander_Path%") 417 | ; FileName := StrReplace(FileName,"%Commander_Path%",Commander_Path) 418 | FileName := GetPath(FileName) 419 | 420 | ; Build a unique extension ID to avoid characters that are illegal in variable names, 421 | ; such as dashes. This unique ID method also performs better because finding an item 422 | ; in the array does not require search-loop. 423 | SplitPath, FileName,,, FileExt ; Get the file's extension. 424 | FileName:=GetPath(FileName) 425 | if FileExt in EXE,ICO,ANI,CUR 426 | { 427 | ExtID := FileExt ; Special ID as a placeholder. 428 | IconNumber = 0 ; Flag it as not found so that these types can each have a unique icon. 429 | } 430 | else ; Some other extension/file-type, so calculate its unique ID. 431 | { 432 | ExtID = 0 ; Initialize to handle extensions that are shorter than others. 433 | Loop 7 ; Limit the extension to 7 characters so that it fits in a 64-bit value. 434 | { 435 | StringMid, ExtChar, FileExt, A_Index, 1 436 | if not ExtChar ; No more characters. 437 | break 438 | ; Derive a Unique ID by assigning a different bit position to each character: 439 | ExtID := ExtID | (Asc(ExtChar) << (8 * (A_Index - 1))) 440 | } 441 | ; Check if this file extension already has an icon in the ImageLists. If it does, 442 | ; several calls can be avoided and loading performance is greatly improved, 443 | ; especially for a folder containing hundreds of files: 444 | IconNumber := IconArray%ExtID% 445 | } 446 | if not IconNumber ; There is not yet any icon for this extension, so load it. 447 | { 448 | ; Get the high-quality small-icon associated with this file extension: 449 | if not DllCall("Shell32\SHGetFileInfo" . (A_IsUnicode ? "W":"A"), "str", FileName 450 | , "uint", 0, "ptr", &sfi, "uint", sfi_size, "uint", 0x101) ; 0x101 is SHGFI_ICON+SHGFI_SMALLICON 451 | IconNumber = 9999999 ; Set it out of bounds to display a blank icon. 452 | else ; Icon successfully loaded. 453 | { 454 | ; Extract the hIcon member from the structure: 455 | hIcon := NumGet(sfi, 0) 456 | ; Add the HICON directly to the small-icon and large-icon lists. 457 | ; Below uses +1 to convert the returned index from zero-based to one-based: 458 | IconNumber := DllCall("ImageList_ReplaceIcon", "ptr", ImageListID1, "int", -1, "ptr", hIcon) + 1 459 | DllCall("ImageList_ReplaceIcon", "ptr", ImageListID2, "int", -1, "ptr", hIcon) 460 | ; Now that it's been copied into the ImageLists, the original should be destroyed: 461 | DllCall("DestroyIcon", "ptr", hIcon) 462 | ; Cache the icon to save memory and improve loading performance: 463 | IconArray%ExtID% := IconNumber 464 | } 465 | } 466 | 467 | ; Create the new row in the ListView and assign it the icon number determined above: 468 | 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) 469 | } 470 | dpifactor:=dpi() 471 | LV_ModifyCol(1, dpifactor*250), LV_ModifyCol(2, dpifactor*70), LV_ModifyCol(3, dpifactor*70) 472 | LV_ModifyCol(4, dpifactor*50), LV_ModifyCol(5, dpifactor*165), LV_ModifyCol(6, dpifactor*70) 473 | LV_ModifyCol(7, dpifactor*40), LV_ModifyCol(8, dpifactor*40), LV_ModifyCol(9, 0) 474 | LV_ModifyCol(10, 0), LV_ModifyCol(11, 0) ; icon, name 475 | Return 476 | 477 | ; Hotkeys & Functions to move a listview row 478 | ; TODO: Fix icon which does not move with the listview row 479 | 480 | ; ListViews G-Label. 481 | LVLabel: 482 | ; Detect Drag event. 483 | If A_GuiEvent = D 484 | LvHandle.Drag() ; Call Drag function using the Handle. 485 | If A_GuiEvent = DoubleClick 486 | Gosub, Modify 487 | return 488 | 489 | MoveUp: 490 | LvHandle.Move(1) ; Move selected rows up. 491 | return 492 | 493 | MoveDown: 494 | LvHandle.Move() ; Move selected rows down. 495 | return 496 | 497 | #include 498 | -------------------------------------------------------------------------------- /inc/FilteredMenu.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Foreground menu - show matching programs only based on .ext - uses lib\GetPos.ahk 4 | Shares code with menu.ahk (building menu, AddMenuEntry + AddMenuProgramOptions labels, menuhandler) 5 | Include for F4MiniMenu.ahk 6 | 7 | */ 8 | 9 | 10 | FilteredMenu: 11 | GetExt(GetFiles()) 12 | If debug 13 | { 14 | debug_ext:=MatchList.Temp.SelectedExtensions 15 | debug_files:=MatchList.Temp.Files 16 | } 17 | CoordMode, Menu, Client 18 | Gosub, BuildFilteredMenu 19 | ; MsgBox % MatchList.settings.FilteredMenuAutoEdit 20 | If (MenuCounter = 3) and (MatchList.Settings.FilteredMenuAutoEdit = 2) 21 | { 22 | ; only found one editor so run automatically 23 | ; TODO how to get from here to openfiles???? 24 | ProcessFiles(Matchlist, MatchListReference[3]) 25 | OSDTIP_Pop("F4MiniMenu", "Only found one editor.`nOpening file automatically", -750,"W230 H80 U1") 26 | ; MsgBox 27 | } 28 | Else 29 | { 30 | Coord:=GetPos(MatchList.settings.MenuPos,MatchList.MaxIndex()) 31 | Menu, %MenuName%, Show, % Coord["x"], % Coord["y"] 32 | } 33 | MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp") 34 | MenuCounter:="" 35 | Return 36 | 37 | ; Build menu based on defined editors 38 | 39 | BuildFilteredMenu: 40 | Menu, MyFilteredMenu, Add, 41 | Menu, MyFilteredMenu, DeleteAll 42 | 43 | MenuName:="MyFilteredMenu" 44 | 45 | MatchListReference:=[] ; Object and counter below used to keep track of the original position in MatchList so 46 | MenuCounter:=0 ; we select the correct editor in the filtered menu as we use A_ThisMenuItemPos in menuhandler 47 | 48 | for k, v in MatchList 49 | { 50 | If (k = "settings") or (k = "temp") 51 | Continue ; skip settings 52 | If RegExMatch(MatchList.Temp.SelectedExtensions,StrReplace(RegExExtensions(v.ext),",","|")) or (k = 1) 53 | { 54 | MenuCounter++ 55 | ExeName:=v.exe 56 | SplitPath, ExeName, ShortName 57 | If (v.name <> "") 58 | ShortName:=v.name 59 | 60 | If InStr(ShortName,"&") 61 | ShortName:=MenuPadding ShortName 62 | else 63 | ShortName:=MenuPadding "&" ShortName 64 | 65 | MatchListReference[MenuCounter]:=A_Index 66 | 67 | If (k = 1) ; because we add a separator line we need to keep track of this 68 | MenuCounter++ 69 | 70 | Gosub, AddMenuEntry 71 | } 72 | } 73 | 74 | Menu, MyFilteredMenu, Add, 75 | Menu, MyFilteredMenu, Add, % MatchList.settings.FullMenu ? "&" MatchList.settings.FullMenu " Full menu" : " Full menu", :MyMenu 76 | Try 77 | Menu, MyFilteredMenu, Icon, % MatchList.settings.FullMenu ? "&" MatchList.settings.FullMenu " Full menu" : " Full menu", res\f4.ico 78 | 79 | Gosub, AddMenuProgramOptions 80 | 81 | 82 | 83 | If (MenuCounter = 2) ; we haven't found any matches, so just show full menu 84 | MenuName:="MyMenu" 85 | 86 | Return 87 | -------------------------------------------------------------------------------- /inc/HelperFunctions.ahk: -------------------------------------------------------------------------------- 1 | ; used in F4MiniMenu and F4TCIE 2 | 3 | GetPath(path) 4 | { 5 | global MyComSpec,Commander_Path,MyProgramFiles,MyProgramFilesx86,MyProgramW6432,A_UserProfile 6 | ; path:=StrReplace(path,"%ComSpec%",MyComSpec) 7 | if !InStr(path,"\") ; for programs in path environment e.g. wordpad, write 8 | Return path 9 | if !InStr(path,"%") ; no special treatment required 10 | Return GetFullPathName(path) 11 | Loop, parse, % "Commander_Path,A_ScriptDir,A_ComputerName,A_UserName,A_WinDir,A_ProgramFiles,ProgramFiles,A_AppData,A_AppDataCommon,A_Desktop,A_DesktopCommon,A_StartMenu,A_StartMenuCommon,A_Programs,A_ProgramsCommon,A_Startup,A_StartupCommon,A_MyDocuments,A_UserProfile", CSV 12 | path:=StrReplace(path,"%" A_LoopField "%",%A_LoopField%) 13 | ; special cases 14 | path:=StrReplace(path,"%WinDir%",A_WinDir) 15 | path:=StrReplace(path,"%ProgramFiles%",MyProgramFiles) 16 | path:=StrReplace(path,"%ProgramFiles(x86)%",MyProgramFilesx86) 17 | path:=StrReplace(path,"%ProgramW6432%",MyProgramW6432) 18 | Return GetFullPathName(path) 19 | } 20 | 21 | ; get absolute path from relative path 22 | ; https://www.autohotkey.com/boards/viewtopic.php?p=289536#p289536 23 | GetFullPathName(path) { 24 | cc := DllCall("GetFullPathName", "str", path, "uint", 0, "ptr", 0, "ptr", 0, "uint") 25 | VarSetCapacity(buf, cc*(A_IsUnicode?2:1)) 26 | DllCall("GetFullPathName", "str", path, "uint", cc, "str", buf, "ptr", 0, "uint") 27 | return buf 28 | } 29 | 30 | xGetTCCommander_Path(editor) 31 | { 32 | global MyComSpec 33 | editor:=StrReplace(editor,"%Commander_Path%",Commander_Path) 34 | editor:=StrReplace(editor,"%ComSpec%",MyComSpec) 35 | Return editor 36 | } 37 | 38 | RegExExtensions(in) 39 | { 40 | out:="iU)\b(" StrReplace(StrReplace(StrReplace(in,",","|"),"?",".?"),"*",".*") ")\b" ; v0.9 allow for wildcards 41 | Return out 42 | } 43 | 44 | -------------------------------------------------------------------------------- /inc/LoadSettings1.ahk: -------------------------------------------------------------------------------- 1 | ; used in F4MiniMenu and F4TCIE 2 | 3 | SplitPath, A_ScriptName, , , , OutNameNoExt 4 | If (SubStr(OutNameNoExt,0) <> "i") 5 | { 6 | F4ConfigFile:="F4MiniMenu.xml" 7 | F4Load:="XA_Load" 8 | F4Save:="XA_Save" 9 | } 10 | else 11 | { 12 | F4ConfigFile:="F4MiniMenu.ini" 13 | F4Load:="iob" 14 | F4Save:="iob_save" 15 | } 16 | 17 | Error:=0 18 | ; http://en.wikipedia.org/wiki/List_of_archive_formats 19 | ArchiveExtentions:="\.(a|ar|cpio|shar|iso|lbr|mar|tar|bz2|F|gz|lz|lzma|lzo|rz|sfark|xz|z|infl|7z|s7z|ace|afa|alz|apk|arc|arj|ba|bh|cab|cfs|cpt|dar|dd|dgc|dmg|gca|ha|hki|ice|j|kgb|lzh|lha|lzx|pak|partimg|paq6|paq7|paq8|pea|pim|pit|qda|rar|rk|sda|sea|sen|sfx|sit|sitx|sqx|tar\.gz|tgz|tar\.Z|tar\.bz2|tbz2|tar\.lzma|tlz|uc|uc0|uc2|ucn|ur2|ue2|uca|uha|wim|xar|xp3|yz1|zip|zipx|zoo|zz)\\" 20 | 21 | ; get Environment variables 22 | EnvGet, MyComSpec, ComSpec 23 | EnvGet, MyProgramFiles, ProgramFiles 24 | EnvGet, MyProgramFilesx86, ProgramFiles(x86) 25 | EnvGet, MyProgramW6432, ProgramW6432 26 | EnvGet, A_UserProfile, UserProfile 27 | -------------------------------------------------------------------------------- /inc/LoadSettings2.ahk: -------------------------------------------------------------------------------- 1 | ; used in F4MiniMenu and F4TCIE 2 | 3 | ; Load settings on MatchList Object 4 | Try 5 | { 6 | %F4Load%(F4ConfigFile) 7 | } 8 | Catch 9 | { 10 | Error:=1 11 | } 12 | 13 | If ((MatchList.MaxIndex() = 0) or (MatchList.MaxIndex() = "")) 14 | Error:=1 15 | -------------------------------------------------------------------------------- /inc/Menu.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Foreground menu - uses lib\GetPos.ahk 4 | FilteredMenu.ahk makes use of various labels in Menu.ahk 5 | Include for F4MiniMenu.ahk 6 | 7 | */ 8 | 9 | ShowMenu: 10 | CoordMode, Menu, Client 11 | Coord:=GetPos(MatchList.settings.MenuPos,MatchList.MaxIndex()) 12 | Menu, MyMenu, Show, % Coord["x"], % Coord["y"] 13 | MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp") 14 | Return 15 | 16 | ; Build menu based on defined editors 17 | 18 | BuildMenu: 19 | Menu, MyMenu, Add, 20 | Menu, MyMenu, DeleteAll 21 | 22 | MenuName:="MyMenu" 23 | 24 | for k, v in MatchList 25 | { 26 | If (k = "settings") or (k = "temp") 27 | Continue ; skip settings 28 | ExeName:=v.exe 29 | SplitPath, ExeName, ShortName 30 | If (v.name <> "") 31 | ShortName:=v.name 32 | 33 | If InStr(ShortName,"&") 34 | ShortName:=MenuPadding ShortName 35 | else 36 | ShortName:=MenuPadding "&" ShortName 37 | 38 | Gosub, AddMenuEntry 39 | 40 | } 41 | 42 | Gosub, AddMenuProgramOptions 43 | 44 | Return 45 | 46 | ; If the tray icon is double click we do not actually want to do anything 47 | DoubleTrayClick: 48 | Send {rbutton} ; show tray menu 49 | Return 50 | 51 | 52 | ; Tray menu 53 | MenuHandler: 54 | ; MsgBox % A_ThisMenu ":" A_ThisMenuItemPos-1 ":" MatchList[A_ThisMenuItemPos-1].exe ; debug 55 | If MatchList.Settings.log 56 | Log(A_Now " : Menuhandler, call -> A_ThisMenu=" A_ThisMenu "| A_ThisMenuItemPos-1=" A_ThisMenuItemPos-1 "| Exe=" A_ThisMenuItem,MatchList.Settings.logFile) 57 | 58 | ; Easy & Quick options first 59 | If (A_ThisMenuItem = "&Open") 60 | { 61 | ListHotkeys 62 | Return 63 | } 64 | Else If (A_ThisMenuItem = "&Reload this script") 65 | { 66 | Reload 67 | Return 68 | } 69 | Else If (A_ThisMenuItem = "&Edit this script") 70 | { 71 | Run Edit %A_ScriptName% 72 | Return 73 | } 74 | Else If (A_ThisMenuItem = "&Suspend Hotkeys") 75 | { 76 | Menu, tray, ToggleCheck, &Suspend Hotkeys 77 | Suspend 78 | Return 79 | } 80 | Else If (A_ThisMenuItem = "&Pause Script") 81 | { 82 | Menu, tray, ToggleCheck, &Pause Script 83 | Pause 84 | Return 85 | } 86 | Else If (A_ThisMenuItem = " Exit") 87 | Return 88 | Else If (A_ThisMenuItem = " Settings") ; Settings menu 89 | { 90 | Gosub, Settings 91 | Return 92 | } 93 | Else If (A_ThisMenuItemPos = 1) ; Default editor 94 | { 95 | If MatchList.Settings.log 96 | Log(A_Now " : Menuhandler, selected editor -> Default editor" ,MatchList.Settings.logFile) 97 | ProcessFiles(Matchlist, 1) 98 | Return 99 | } 100 | Else 101 | If (MatchList.Temp.SelectedExtensions = "") or (A_ThisMenu = "MyMenu") ; entire Foreground menu 102 | { 103 | If MatchList.Settings.log 104 | Log(A_Now " : Menuhandler, selected editor -> editor from entire menu, Exe=" A_ThisMenuItem,MatchList.Settings.logFile) 105 | ProcessFiles(Matchlist, A_ThisMenuItemPos-1) ; proceed with the selected editor. Menu order = editor order. 106 | MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp"),MatchListReference:="" 107 | } 108 | else ; filtered Foreground menu 109 | { 110 | If MatchList.Settings.log 111 | Log(A_Now " : Menuhandler, selected editor -> editor from filtered menu, Exe=" A_ThisMenuItem,MatchList.Settings.logFile) 112 | ProcessFiles(Matchlist, MatchListReference[A_ThisMenuItemPos]) 113 | MatchList.Temp.Files:="",MatchList.Temp.SelectedExtensions:="",MatchList.Delete("Temp"),MatchListReference:="" 114 | } 115 | 116 | Return 117 | 118 | AddMenuEntry: 119 | 120 | Menu, %MenuName%, Add, %ShortName%, MenuHandler 121 | 122 | Try 123 | { 124 | If (v.icon = "") 125 | Menu, %MenuName%, Icon, %ShortName%, % StrReplace(ExeName,"%Commander_Path%",Commander_Path) 126 | Else 127 | Menu, %MenuName%, Icon, %ShortName%, % StrReplace(v.icon,"%Commander_Path%",Commander_Path) 128 | } 129 | Catch ; it is not an EXE 130 | { 131 | Menu, %MenuName%, Icon, %ShortName%, shell32.dll, 3 132 | } 133 | If (k = 1) ; Add line after default editors 134 | Menu, %MenuName%, Add 135 | 136 | If debug 137 | { 138 | debug_menu .= MenuCounter " : " ShortName "`n" 139 | } 140 | Return 141 | 142 | AddMenuProgramOptions: 143 | 144 | ; Program options 145 | Menu, %MenuName%, Add 146 | Menu, %MenuName%, Add, %MenuPadding%Add new Editor, ConfigEditorsNew 147 | Menu, %MenuName%, Icon, %MenuPadding%Add new Editor, shell32.dll, 176 148 | Menu, %MenuName%, Add, %MenuPadding%Configure Editors, ConfigEditors 149 | Menu, %MenuName%, Icon, %MenuPadding%Configure Editors, shell32.dll, 70 150 | Menu, %MenuName%, Add, %MenuPadding%Scan Document Templates, DocumentTemplatesScan 151 | Menu, %MenuName%, Icon, %MenuPadding%Scan Document Templates, shell32.dll, 172 152 | Menu, %MenuName%, Add, %MenuPadding%Settings, MenuHandler 153 | Menu, %MenuName%, Icon, %MenuPadding%Settings, shell32.dll, 170 154 | 155 | Menu, %MenuName%, Add, %MenuPadding%Exit, MenuHandler 156 | Menu, %MenuName%, Icon, %MenuPadding%Exit, shell32.dll, 132 157 | 158 | Return 159 | -------------------------------------------------------------------------------- /inc/Settings.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | General program settings GUI 4 | Include for F4MiniMenu.ahk 5 | 6 | */ 7 | 8 | Settings: 9 | 10 | Gui, Browse:Destroy 11 | 12 | ; Variables 13 | ;SelectMenuPos:=MatchList.settings.MenuPos 14 | ;SelectTCStart:=MatchList.settings.TCStart 15 | ;SettingsFormat:=MatchList.settings.SettingsFormat 16 | ;If (SettingsFormat = "") 17 | ; SettingsFormat:=1 18 | ;OldSettingsFormat:=SettingsFormat 19 | 20 | If (MatchList.settings.FilteredMenuAutoEdit = "") 21 | MatchList.settings.FilteredMenuAutoEdit:=1 22 | FGHKey:=MatchList.settings.ForegroundHotkey 23 | BGHKey:=MatchList.settings.BackgroundHotkey 24 | TMHKey:=MatchList.settings.FilteredHotkey 25 | 26 | 27 | ; Turn hotkeys off to be sure 28 | HotKeyState:="Off" 29 | Gosub, SetHotkeys 30 | 31 | ; Gui for general program settings 32 | Gui, Settings: +OwnDialogs 33 | Gui, Settings: font, % dpi("s8") 34 | Gui, Settings: Add, GroupBox, % dpi("x16 y7 w540 h70"), Menu 35 | Gui, Settings: Add, Text, % dpi("x25 y25 w309 h16"), &Selection menu appears (TC only) 36 | Gui, Settings: Add, DropDownList, % dpi("x328 y20 w219 h25 r4 Choose" MatchList.settings.MenuPos " vMenuPos AltSubmit"), 1 - At Mouse cursor|2 - Centered in window|3 - Right next to current file|4 - Docked next to current file (opposite panel) 37 | Gui, Settings: Add, Text, % dpi("x25 yp+35 w309 h16"), &Accelerator key for full menu (for use in filtered menu, 1 char.) 38 | Gui, Settings: Add, Edit, % dpi("x328 yp-5 w30 h21 vFullMenu"), % MatchList.settings.FullMenu ; % 39 | Gui, Settings: Add, Text, % dpi("x365 yp+5 w70 h16"), If one result: 40 | Gui, Settings: Add, DropDownList, % dpi("x430 yp-5 w117 h25 r2 Choose" MatchList.settings.FilteredMenuAutoEdit " vFilteredMenuAutoEdit AltSubmit"), 1 - Show menu|2 - Edit directly 41 | 42 | Gui, Settings: Add, GroupBox, % dpi("x16 yp+40 w260 h45"), Files 43 | Gui, Settings: Add, Text, % dpi("x25 yp+20 w209 h16"), &Maximum number of files to be opened 44 | Gui, Settings: Add, Edit, % dpi("x227 yp-5 w40 h21 Number vMaxFiles"), % MatchList.settings.Maxfiles ; % 45 | 46 | Gui, Settings: Add, GroupBox, % dpi("x280 yp-15 w276 h45"), WinWait 47 | Gui, Settings: Add, Text, % dpi("x289 yp+20 w209 h16"), &Seconds (max) to wait for program window 48 | Gui, Settings: Add, Edit, % dpi("x507 yp-5 w40 h21") 49 | Gui, Settings: Add, UpDown, vMaxWinWaitSec Range2-10, % MatchList.Settings.MaxWinWaitSec ; % 50 | 51 | 52 | Gui, Settings: Add, GroupBox, % dpi("x16 yp+40 w540 h100"), Total Commander 53 | Gui, Settings: Add, DropDownList, % dpi("x25 yp+20 w240 h25 R3 Choose" MatchList.settings.TCStart " vTCStart AltSubmit"), 1 - Do not start TC (default)|2 - Start TC if not Running (set TC Path)|3 - Always start TC (set TC Path) 54 | Gui, Settings: Add, Text, % dpi("xp+250 yp+5 w50 h16"), TC Path 55 | If !FileExist(MatchList.settings.TCPath) 56 | MatchList.settings.TCPath:="" 57 | Gui, Settings: Add, Edit , % dpi("xp+53 yp-5 w180 h21 vTCPath"), % MatchList.settings.TCPath ; % 58 | Gui, Settings: Add, Button, % dpi("xp+187 yp w30 h20 gSelectExe"), >> 59 | 60 | Gui, Settings: Add, Text, % dpi("xp-238 yp+30 w50 h16"), INI Path 61 | If !FileExist(MatchList.settings.TCIniPath) 62 | MatchList.settings.TCIniPath:="" 63 | 64 | Gui, Settings: Add, Edit , % dpi("xp+51 yp-5 w180 h21 vTCIniPath"), % MatchList.settings.TCIniPath ; % 65 | Gui, Settings: Add, Button, % dpi("xp+187 yp w30 h20 gSelectIni"), >> 66 | 67 | Checked:=MatchList.settings.F4MMCloseAll 68 | Gui, Settings: Add, Checkbox, % dpi("x25 yp+3 w240 h16 Checked" checked " vF4MMCloseAll"), Close F4MM when all copies of TC close 69 | Checked:=MatchList.settings.F4MMClosePID 70 | Gui, Settings: Add, Checkbox, % dpi("x25 yp+25 w240 h16 Checked" checked " vF4MMClosePID"), Close F4MM when TC closes started by F4MM 71 | Gui, Settings: Font, % dpi("cGreen") 72 | Gui, Settings: Add, Text, % dpi("xp+240 yp gFMMCloseHelpText"), (?) 73 | Gui, Settings: Add, Text, % dpi("xp+260 yp gFMMPathsHelpText"), (?) 74 | Gui, Settings: Font, % dpi("cBlack") 75 | Gui, Settings: Font, ; needed as theme is stripped from control @ https://www.autohotkey.com/boards/viewtopic.php?p=399355#p399355 76 | Gui, Settings: Font, % dpi("s8") 77 | 78 | Gui, Settings: Add, GroupBox, % dpi("x16 yp+35 w395 h120"), Hotkeys 79 | 80 | Gui, Settings: Add, Text, % dpi("x25 yp+25 w150 h16"), &Background mode (direct) 81 | ;Gui, Settings: Add, Radio, % dpi("xp+130 yp w45 h16 vBEsc"), Esc 82 | ;Gui, Settings: Add, Radio, % dpi("xp+45 yp w45 h16 vBWin"), Win 83 | Gui, Settings: Add, DropDownList, % dpi("xp+140 yp-3 w70 R3 vBMod"), |Esc|Win 84 | 85 | ; Always annoying to work around Hotkey control limit, use boxes for Win & Esc keys 86 | Gui, Settings: Default 87 | If InStr(BGHKey,"#") 88 | { 89 | StringReplace, BGHKey, BGHKey, #, , All 90 | GuiControl, Choose, BMod, 3 91 | } 92 | If InStr(BGHKey,"Esc &") 93 | { 94 | StringReplace, BGHKey, BGHKey, Esc &, , All 95 | StringReplace, BGHKey, BGHKey, Esc &`;, , All 96 | StringReplace, BGHKey, BGHKey, Esc &, , All 97 | StringReplace, BGHKey, BGHKey, %A_Space%, , All 98 | GuiControl, Choose, BMod, 3 99 | } 100 | 101 | Gui, Settings: Add, Hotkey, % dpi("xp+90 yp w140 h20 vBGHKey"), %BGHKey% 102 | 103 | Gui, Settings: Add, Text, % dpi("x25 yp+35 w150 h16"), &Foreground mode (menu) 104 | ;Gui, Settings: Add, Radio, % dpi("xp+130 yp w45 h16 vFEsc"), Esc 105 | ;Gui, Settings: Add, Radio, % dpi("xp+45 yp w45 h16 vFWin"), Win 106 | Gui, Settings: Add, DropDownList, % dpi("xp+140 yp-3 w70 R3 vFMod"), |Esc|Win 107 | 108 | Gui, Settings: Default 109 | 110 | If InStr(FGHKey,"#") 111 | { 112 | StringReplace, FGHKey, FGHKey, #, , All 113 | GuiControl, Choose, FMod, 3 114 | } 115 | 116 | If InStr(FGHKey,"Esc &") 117 | { 118 | StringReplace, FGHKey, FGHKey, Esc &, , All 119 | StringReplace, FGHKey, FGHKey, Esc &`;, , All 120 | StringReplace, FGHKey, FGHKey, Esc &, , All 121 | StringReplace, FGHKey, FGHKey, %A_Space%, , All 122 | GuiControl, Choose, FMod, 2 123 | } 124 | 125 | Gui, Settings: Add, Hotkey, % dpi("xp+90 yp w140 h20 vFGHKey"), %FGHKey% 126 | ;Gui, Settings: Add, Button, % dpi("xp+110 yp w30 h20 gButtonClearFG"), clear 127 | 128 | Gui, Settings: Add, Text, % dpi("x25 yp+35 w150 h16"), Fil&tered mode (menu) 129 | ;Gui, Settings: Add, Radio, % dpi("xp+130 yp w45 h16 vTEsc"), Esc 130 | ;Gui, Settings: Add, Radio, % dpi("xp+45 yp w45 h16 vTWin"), Win 131 | Gui, Settings: Add, DropDownList, % dpi("xp+140 yp-3 w70 R3 vTmod"), |Esc|Win 132 | 133 | Gui, Settings: Default 134 | 135 | If InStr(TMHKey,"#") 136 | { 137 | StringReplace, TMHKey, TMHKey, #, , All 138 | GuiControl, Choose , Tmod, 3 139 | } 140 | 141 | If InStr(TMHKey,"Esc &") 142 | { 143 | StringReplace, TMHKey, TMHKey, Esc &, , All 144 | StringReplace, TMHKey, TMHKey, Esc &`;, , All 145 | StringReplace, TMHKey, TMHKey, Esc &, , All 146 | StringReplace, TMHKey, TMHKey, %A_Space%, , All 147 | GuiControl, Choose, Tmod, 2 148 | } 149 | 150 | Gui, Settings: Add, Hotkey, % dpi("xp+90 yp w140 h20 vTMHKey"), %TMHKey% 151 | ; Gui, Settings: Add, Button, % dpi("xp+110 yp w30 h20 gButtonClearTM"), clear 152 | 153 | Gui, Settings: Add, Button, % dpi("xp+170 yp-75 w120 h25 gButtonOK"), OK 154 | Gui, Settings: Add, Button, % dpi("xp yp+40 w120 h25 gButtonClear"), Clear All Hotkeys 155 | Gui, Settings: Add, Button, % dpi("xp yp+40 w120 h25 gSettingsGuiClose"), Cancel 156 | 157 | Gui, Settings: Add, GroupBox, % dpi("x16 yp+40 w260 h72"), Other prg. (Hotkey: Copy File Names w. Full Path) 158 | 159 | Gui, Settings: Add, Text, % dpi("x25 yp+20 w100 h20"), Dbl Cmd: 160 | Gui, Settings: Add, Hotkey, % dpi("xp+52 yp-3 w90 h20 vDoubleCommander"), % MatchList.settings.DoubleCommander 161 | 162 | Gui, Settings: Add, Text, % dpi("x25 yp+30 w50 h20"), XYPlorer: 163 | Gui, Settings: Add, Hotkey, % dpi("xp+52 yp-3 w90 h20 vXYPlorer"), % MatchList.settings.XYPlorer 164 | 165 | Checked:=MatchList.settings.Explorer 166 | Gui, Settings: Add, Checkbox, % dpi("xp+100 yp-25 w60 h16 Checked" checked " vExplorer"), Explorer 167 | 168 | Checked:=MatchList.settings.Everything 169 | Gui, Settings: Add, Checkbox, % dpi("xp yp+28 w80 h16 Checked" checked " vEverything"), Everything 170 | 171 | Gui, Settings: Font, % dpi("s8 cGreen") 172 | Gui, Settings: Add, Text, % dpi("xp+70 yp-28 gFMMFileManText"), (?) 173 | Gui, Settings: Font, % dpi("cBlack") 174 | Gui, Settings: Font, ; see note above, required to reset style 175 | Gui, Settings: Font, % dpi("s8") 176 | 177 | Gui, Settings: Add, GroupBox, % dpi("xp+35 yp-19 w270 h72"), Use elsewhere in TC (no menu) 178 | 179 | Checked:=MatchList.settings.Lister 180 | Gui, Settings: Add, Checkbox, % dpi("xp+10 yp+20 w220 h16 Checked" checked " vLister"), Lister (+ use F4Edit setting in wincmd.ini) 181 | 182 | Checked:=MatchList.settings.QuickView 183 | Gui, Settings: Add, Checkbox, % dpi("xp yp+28 w120 h16 Checked" checked " vQuickView"), QuickView (see ?) 184 | 185 | Checked:=MatchList.settings.FindFiles 186 | Gui, Settings: Add, Checkbox, % dpi("xp+160 yp w80 h16 Checked" checked " vFindFiles"), Find Files 187 | 188 | Gui, Settings: Font, % dpi("s8 cGreen") 189 | Gui, Settings: Add, Text, % dpi("xp+70 yp-28 gFMMTCElseWhere"), (?) 190 | Gui, Settings: Font, % dpi("cBlack") 191 | Gui, Settings: Font, ; see note above, required to reset style 192 | Gui, Settings: Font, % dpi("s8") 193 | 194 | 195 | ; Note: deactivated Everything Directory Tree and DocumentTemplates settings for now 196 | /* 197 | Gui, Settings: Add, Text, % dpi("xp+70 yp+1 w100 h20"), Ev. Dir Tree: 198 | Gui, Settings: Add, Hotkey, % dpi("xp+100 yp-3 w90 h20 vEVDirTree"), % MatchList.settings.EVDirTree 199 | 200 | Gui, Settings: Add, Text, % dpi("xp+100 yp+1 w50 h20"), Ev. Path: 201 | Gui, Settings: Add, Edit , % dpi("xp+50 yp-5 w160 h21 vEvPath"), % MatchList.settings.EvPath ; % 202 | Gui, Settings: Add, Button, % dpi("xp+165 yp w30 h20 gSelectEv"), >> 203 | 204 | Gui, Settings: Add, GroupBox, % dpi("x16 yp+45 w540 h70"), Currently Available Document Templates 205 | Gui, Settings: Add, Edit, % dpi("x25 yp+20 ReadOnly h40 w385 vDocumentTemplates"), % MatchList.Settings.templatesExt 206 | Gui, Settings: Add, Button, % dpi("xp+402 yp w120 h25 gButtonDocumentTemplates"), Update (scan) 207 | */ 208 | 209 | ;Gui, Settings: Add, GroupBox, x16 yp+40 w395 h60 , Misc. 210 | ;perhaps in future versions 211 | ;Gui, Settings: Add, Text, x25 yp+25 w150 h16 , Store set&tings in: 212 | ;Gui, Settings: Add, DropDownList, xp+225 yp-5 w140 h25 r2 Choose%SettingsFormat% vSettingsFormat AltSubmit, 1 - XML Format|2 - INI format 213 | 214 | Gui, Settings: Add, Link, % dpi("x25 yp+60"), F4MiniMenu %F4Version%: Open selected file(s) from TC in defined editor(s). More info at Github.com/hi5/F4MiniMenu. 215 | 216 | ;Gui, Settings: Add, GroupBox, xp+400 yp-85 w122 h60 217 | ;Gui, Settings: Add, Link, xp+5 yp+13, Feedback welcome at`nTotal Commander forum`nor GitHub Issues. 218 | 219 | Gui, Settings: Show, % dpi("center w570"), F4MiniMenu - Settings 220 | Return 221 | 222 | ButtonDocumentTemplates: 223 | Gosub, DocumentTemplatesScan 224 | Gui, Settings: Default 225 | GuiControl,,DocumentTemplates, % MatchList.Settings.templatesExt 226 | Return 227 | 228 | ButtonOK: 229 | Gui, Settings: Submit, NoHide 230 | MatchList.settings.MenuPos:=MenuPos 231 | MatchList.settings.FilteredMenuAutoEdit:=FilteredMenuAutoEdit 232 | If (MaxFiles > 50) 233 | { 234 | MsgBox, 36, Confirm, Are you sure you want to`nset the maximum at %MaxFiles% files?`n(No will set the maximum to 50) 235 | IfMsgBox, No 236 | MaxFiles:=50 237 | } 238 | MatchList.settings.MaxFiles:=MaxFiles 239 | MatchList.settings.TCStart:=TCStart 240 | MatchList.settings.TCPath:=TCPath 241 | MatchList.settings.F4MMCloseAll:=F4MMCloseAll 242 | MatchList.settings.F4MMClosePID:=F4MMClosePID 243 | MatchList.settings.FullMenu:=trim(SubStr(FullMenu,1,1)," `t&") 244 | MatchList.settings.MaxWinWaitSec:=MaxWinWaitSec 245 | 246 | ;GuiControlGet, EscFG, , FEsc 247 | ;GuiControlGet, WinFG, , FWin 248 | ;GuiControlGet, EscBG, , BEsc 249 | ;GuiControlGet, WinBG, , BWin 250 | ;GuiControlGet, EscTM, , TEsc 251 | ;GuiControlGet, WinTM, , TWin 252 | 253 | ; Revert the boxes to the Hotkey def. 254 | If (FGHKey <> "") 255 | { 256 | If (FMod = "Win") 257 | FGHKey:="#" FGHKey 258 | If (FMod = "Esc" ) and (RegExMatch(FGHKey,"[\^\+\!\#]") = 0) 259 | FGHKey:="Esc & " FGHKey 260 | } 261 | 262 | If (BGHKey <> "") 263 | { 264 | If (BMod = "Win") 265 | BGHKey:="#" BGHKey 266 | If (BMod = "Esc") and (RegExMatch(BGHKey,"[\^\+\!\#]") = 0) 267 | BGHKey:="Esc & " BGHKey 268 | } 269 | 270 | If (TMHKey <> "") 271 | { 272 | If (TMod = "Win") 273 | TMHKey:="#" TMHKey 274 | If (TMod = "Esc") and (RegExMatch(TMHKey,"[\^\+\!\#]") = 0) 275 | TMHKey:="Esc & " TMHKey 276 | } 277 | 278 | MatchList.settings.ForegroundHotkey:=FGHKey 279 | MatchList.settings.BackgroundHotkey:=BGHKey 280 | MatchList.settings.FilteredHotkey:=TMHKey 281 | 282 | MatchList.settings.Explorer:=Explorer 283 | MatchList.settings.Everything:=Everything 284 | ;MatchList.settings.EvPath:=EvPath 285 | ;MatchList.settings.EVDirTree:=EVDirTree 286 | MatchList.settings.DoubleCommander:=DoubleCommander 287 | MatchList.settings.XYPlorer:=XYPlorer 288 | MatchList.settings.Lister:=Lister 289 | MatchList.settings.QuickView:=QuickView 290 | MatchList.settings.FindFiles:=FindFiles 291 | 292 | HotKeyState:="On" 293 | Gosub, SetHotkeys 294 | Gui, Settings:Destroy 295 | Gosub, SaveSettings 296 | Sleep 500 297 | Reload ; v0.96 we may have changed F4MMClose so we need to reload the script to (de)activate the WinWait in F4MiniMenu.ahk 298 | Sleep 500 299 | Return 300 | 301 | ButtonClear: 302 | Gui, Settings: Default 303 | GuiControl, Choose, BMod, 0 304 | GuiControl, Choose, FMod, 0 305 | GuiControl, Choose, TMod, 0 306 | GuiControl, , BGHKey, 307 | GuiControl, , FGHKey, 308 | GuiControl, , TMHKey, 309 | Return 310 | 311 | SettingsGuiEscape: 312 | SettingsGuiClose: 313 | Gui, Settings: Destroy 314 | 315 | HotKeyState:="On" 316 | Gosub, SetHotkeys 317 | Return 318 | 319 | FMMPathsHelpText: 320 | MsgBox, 8224, TC/INI Paths (experimental), 321 | (join`n 322 | TC Path: Attempt is made to read from the registry, can be set manually. 323 | 324 | INI Path: As F4MM can be launched first or used "portable", it may not be able to read one or more settings from wincmd.ini. 325 | Set manually if this is the case (see Lister/F4Edit setting). 326 | 327 | When set manually the registry will not be read. 328 | 329 | (Relative paths from the F4MM program folder). 330 | ) 331 | Return 332 | 333 | FMMCloseHelpText: 334 | MsgBox, 8224, F4MMClose (experimental), 335 | (join`n 336 | F4MiniMenu - %F4Version% can automatically exit from memory using the following rules: 337 | 338 | [1] Close F4MM when all copies of TC close: 339 | waits until all running copies of Total Commander are closed. 340 | 341 | [2] Close F4MM when TC closes started by F4MM: 342 | If you have started (a new) Total Commander via F4MiniMenu, wait until that specific Total Commander closes. 343 | 344 | ) 345 | Return 346 | 347 | FMMFileManText: 348 | MsgBox, 8224, Other file managers (experimental), 349 | (join`n 350 | F4MiniMenu can also work with other programs.`nTo activate, enter the keyboard shortcut to "Copy File Name(s) with Full Path"`n` 351 | Double Commander default:`tShift+Ctrl+C`n 352 | XYPlorer default:`t`t`tCtrl+p`n 353 | Explorer, Everything:`t`tCheckbox to use F4MM`n`n 354 | Notes: 355 | ℹ Everything >v1.5: F4 may override "Focus Next Selected" 356 | ⚠ Use at your own risk. 357 | ) 358 | Return 359 | 360 | FMMTCElseWhere: 361 | MsgBox, 8224, Use elsewhere in TC (experimental), 362 | (join`n 363 | As of TC 11.03 it is natively possible to "Edit" files from Lister (see TC Help, especially [lister] F4Edit and Editor settings). 364 | F4MM also opens files that are shown using plugins whereas TC only when used in internal mode (no plugins). 365 | 366 | F4MM can read the F4Edit and also close the Lister window, or use TC's native "edit" feature by unchecking the Lister box. 367 | 368 | F4MM also works in the Find Files window by default, this can be turn off. Otherwise TC will use the Editor defined in the configuration (note F4TCIE could be used there). 369 | 370 | QuickView is experimental: when checked, it will try to open the file that is currently open in the QuickView panel, even if multiple files are selected in the active TC panel and 371 | the focus is NOT on the QuickView panel it self. 372 | The foreground and filtered menus can be opened in the QuickView panel, but here also only the one "viewed" file will be opened. 373 | When unchecked all selected files will be opened even when QuickView is being used. 374 | 375 | ) 376 | 377 | ;Ev DirTree:`tReplace TC Dir Tree (Alt-F10)`n 378 | ;Ev Path:`t`tPath to eEverything.exe (required by DirTree)`n`n 379 | Return 380 | -------------------------------------------------------------------------------- /inc/TotalCommanderPath.ahk: -------------------------------------------------------------------------------- 1 | ; used in F4MiniMenu and F4TCIE 2 | 3 | ; try to get Commander_Path and Commander_Ini, 4 | ; these will be empty if TC is not running (yet) or F4MM was started _before_ TC 5 | ; we check for values in settings first, if not available, try to read from the 6 | ; environment, fall back to registry 7 | 8 | If FileExist(MatchList.settings.TCPath) 9 | { 10 | Commander_Path:=StrReplace(MatchList.settings.TCPath,"\TOTALCMD.EXE") 11 | Commander_Path:=StrReplace(Commander_Path,"\TOTALCMD64.EXE") 12 | } 13 | else 14 | { 15 | EnvGet, Commander_Path, Commander_Path 16 | If (Commander_Path = "") ; try to read registry 17 | Commander_Path:=TCRegistryCheck("InstallDir") 18 | If FileExist(Commander_Path) 19 | MatchList.settings.TCPath:=Commander_Path "\TotalCmd.exe" ; assume 32bit, user can change this in settings 20 | } 21 | 22 | ; we only use Commander_Ini / MatchList.settings.TCIniPath for ListerWindowClose 23 | If FileExist(MatchList.settings.TCIniPath) 24 | Commander_Ini:=MatchList.settings.TCIniPath 25 | else 26 | { 27 | EnvGet, Commander_Ini, Commander_Ini 28 | If (Commander_Ini = "") ; try to read registry 29 | Commander_Ini:=TCRegistryCheck("IniFileName") 30 | If (Commander_Ini = ".\wincmd.ini") 31 | Commander_Ini:=Commander_Path "\wincmd.ini" 32 | If FileExist(Commander_Ini) 33 | MatchList.settings.TCIniPath:=Commander_Ini 34 | } 35 | 36 | ; TODO consider other method, also for non TC uers who now always get this warning 37 | ; Inform user just in case 38 | If (Commander_Path = "") 39 | { 40 | FileRead, check_for_path, %F4ConfigFile% 41 | If RegExMatch(check_for_path,"iU)(.*exe|TCPath=.*exe)") 42 | MsgBox, 16, F4MiniMenu: Not found, F4MiniMenu:`nThe Commander_Path environment variable can not be found.`nStarting applications may not work in some cases.`nStart TC first (and check the Settings). 43 | check_for_path:="" 44 | } 45 | 46 | ListerWindowClose() 47 | { 48 | Global 49 | IniRead, ListerWindowClose, % MatchList.settings.TCIniPath, Lister, F4Edit 50 | } 51 | 52 | TCRegistryCheck(key) 53 | { 54 | ; source: https://ghisler.ch/board/viewtopic.php?t=258 55 | ; Search in this order, the 1st key that exist should be used: 56 | ; 1. HKCU\Software\Ghisler\Total Commander 57 | ; 2. HKLM\Software\Ghisler\Total Commander 58 | ; 3. HKCU\Software\Ghisler\Windows Commander 59 | ; 4. HKLM\Software\Ghisler\Windows Commander 60 | ; Under each key there should be three values: 61 | ; 1. "InstallDir" - Path where TC/WC is installed 62 | ; 2. "IniFileName" - Relative* path to the "WinCmd.ini" 63 | ; 3. "FtpIniName" - Relative* path to the "wcx_ftp.ini" 64 | ; 65 | ; IniFileName=%AppData%\Ghisler\wincmd.ini (Option "Application Data") 66 | ; IniFileName=%UserProfile%\wincmd.ini (Option "Documents and Settings") 67 | ; under older systems: Windows directory 68 | 69 | Loop, parse, % "HKCU,HKLM", CSV 70 | { 71 | main:=A_LoopField 72 | Loop, parse, % "Total Commander,Windows Commander", CSV 73 | { 74 | program:=A_LoopField 75 | RegRead key, %main%, Software\Ghisler\%program%, %key% 76 | if (key <> "") 77 | break 2 78 | } 79 | } 80 | Return key 81 | } 82 | -------------------------------------------------------------------------------- /lib/AutoXYWH.ahk: -------------------------------------------------------------------------------- 1 | ; ================================================================================= 2 | ; Function: AutoXYWH 3 | ; Move and resize control automatically when GUI resizes. 4 | ; Parameters: 5 | ; DimSize - Can be one or more of x/y/w/h optional followed by a fraction 6 | ; add a '*' to DimSize to 'MoveDraw' the controls rather then just 'Move', this is recommended for Groupboxes 7 | ; cList - variadic list of ControlIDs 8 | ; ControlID can be a control HWND, associated variable name, ClassNN or displayed text. 9 | ; The later (displayed text) is possible but not recommend since not very reliable 10 | ; Examples: 11 | ; AutoXYWH("xy", "Btn1", "Btn2") 12 | ; AutoXYWH("w0.5 h 0.75", hEdit, "displayed text", "vLabel", "Button1") 13 | ; AutoXYWH("*w0.5 h 0.75", hGroupbox1, "GrbChoices") 14 | ; --------------------------------------------------------------------------------- 15 | ; Version: 2015-5-29 / Added 'reset' option (by tmplinshi) 16 | ; 2014-7-03 / toralf 17 | ; 2014-1-2 / tmplinshi 18 | ; requires AHK version : 1.1.13.01+ 19 | ; ================================================================================= 20 | AutoXYWH(DimSize, cList*){ ; http://ahkscript.org/boards/viewtopic.php?t=1079 21 | static cInfo := {} 22 | 23 | If (DimSize = "reset") 24 | Return cInfo := {} 25 | 26 | For i, ctrl in cList { 27 | ctrlID := A_Gui ":" ctrl 28 | If ( cInfo[ctrlID].x = "" ){ 29 | GuiControlGet, i, %A_Gui%:Pos, %ctrl% 30 | MMD := InStr(DimSize, "*") ? "MoveDraw" : "Move" 31 | fx := fy := fw := fh := 0 32 | For i, dim in (a := StrSplit(RegExReplace(DimSize, "i)[^xywh]"))) 33 | If !RegExMatch(DimSize, "i)" dim "\s*\K[\d.-]+", f%dim%) 34 | f%dim% := 1 35 | cInfo[ctrlID] := { x:ix, fx:fx, y:iy, fy:fy, w:iw, fw:fw, h:ih, fh:fh, gw:A_GuiWidth, gh:A_GuiHeight, a:a , m:MMD} 36 | }Else If ( cInfo[ctrlID].a.1) { 37 | dgx := dgw := A_GuiWidth - cInfo[ctrlID].gw , dgy := dgh := A_GuiHeight - cInfo[ctrlID].gh 38 | For i, dim in cInfo[ctrlID]["a"] 39 | Options .= dim (dg%dim% * cInfo[ctrlID]["f" dim] + cInfo[ctrlID][dim]) A_Space 40 | GuiControl, % A_Gui ":" cInfo[ctrlID].m , % ctrl, % Options 41 | } } } 42 | -------------------------------------------------------------------------------- /lib/DoubleCommander.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | DoubleCommander functions 3 | */ 4 | 5 | DoubleCommander_Active() 6 | { 7 | IfWinActive ahk_exe doublecmd.exe 8 | Return 1 9 | } 10 | 11 | DoubleCommander_GetSelection() 12 | { 13 | global matchlist 14 | ClipboardSave:=ClipboardAll 15 | Clipboard:="" 16 | Send % MatchList.settings.DoubleCommander 17 | Result:=Clipboard 18 | Sleep 100 19 | Clipboard:=ClipboardSave 20 | Return Result 21 | } 22 | -------------------------------------------------------------------------------- /lib/DropFiles.ahk: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | 4 | DropFiles: 5 | combined from two functions - ideally they should be merged into one "smarter" 6 | function but this will do for now. 7 | 8 | - SKAN - http://www.autohotkey.com/board/topic/41467-make-ahk-drop-files-into-other-applications/#entry258810 9 | - nimda - http://www.autohotkey.com/board/topic/79145-help-converting-ahk-ahk-l/#entry502676 10 | 11 | Example: 12 | 13 | DropFiles( "C:\SomeName.txt", "ahk_class Notepad" ) 14 | 15 | */ 16 | 17 | DropFiles( FileList, wTitle="", Ctrl="", X=0, Y=0, NCA=0 ) { 18 | If (A_IsUnicode = 1) 19 | { ; from nimda - http://www.autohotkey.com/board/topic/79145-help-converting-ahk-ahk-l/#entry502676 20 | fns:=RegExReplace(FileList,"\n$") 21 | fns:=RegExReplace(fns,"^\n") 22 | hDrop:=DllCall("GlobalAlloc","UInt",0x42,"UPtr",20+StrLen(fns)+2) 23 | p:=DllCall("GlobalLock","UPtr",hDrop) 24 | NumPut(20, p+0) ;offset 25 | NumPut(x, p+4) ;pt.x 26 | NumPut(y, p+8) ;pt.y 27 | NumPut(0, p+12) ;fNC 28 | NumPut(0, p+16) ;fWide 29 | p2:=p+20 30 | Loop,Parse,fns,`n,`r 31 | { 32 | DllCall("RtlMoveMemory","UPtr",p2,"AStr",A_LoopField,"UPtr",StrLen(A_LoopField)) 33 | p2+=StrLen(A_LoopField)+1 34 | } 35 | DllCall("GlobalUnlock","UPtr",hDrop) 36 | PostMessage, 0x233, hDrop, 0, %Ctrl%, %wTitle% 37 | } 38 | Else If (A_IsUnicode <> 1) 39 | { ; from DropFilesA - SKAN - http://www.autohotkey.com/board/topic/41467-make-ahk-drop-files-into-other-applications/#entry258810 40 | StringReplace, FileList, FileList, `r`n, `n , All 41 | VarSetCapacity( DROPFILES, 20, 32 ), DROPFILES .= FileList "`n`n", nSize:=StrLen(DROPFILES) 42 | StringReplace, DROPFILES, DROPFILES, `n, `n, UseErrorLevel 43 | Loop %ErrorLevel% 44 | NumPut( 0, DROPFILES, InStr(DROPFILES,"`n",0,0)-1, "Char" ) 45 | pDP:=&DROPFILES, NumPut(20,pDP+0), NumPut(X,pDP+4), NumPut(Y,pDP+8), NumPut(NCA,pDP+12) 46 | NumPut(0,pDP+16), hDrop := DllCall( "GlobalAlloc", UInt, 0x42, UInt, nSize ) 47 | pData := DllCall( "GlobalLock", UInt, hDrop ) 48 | DllCall( "RtlMoveMemory", UInt, pData, UInt, pDP, UInt, nSize ) 49 | DllCall( "GlobalUnlock", UInt, hDrop ) 50 | PostMessage, 0x233, hDrop, 0, %Ctrl%, %wTitle% 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/Everything.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | Everything functions 3 | - Note: deactivated Everything_DirectoryTree() for now 4 | - 20250209 If there are no selected rows, get entire list and grab first one 5 | - 20250208 Added Everything64.exe; for 1.5 alpha the F4MM shortcut F4 overrides "F4 = Focus Next Selected" 6 | */ 7 | 8 | Everything_Active() 9 | { 10 | WinGet, EverythingExe, ProcessName, A 11 | if EverythingExe in Everything.exe,Everything64.exe 12 | Return 1 13 | } 14 | 15 | Everything_GetSelection(dir="0") 16 | { 17 | WinGet, EverythingExe, ProcessName, Everything 18 | ControlGet, OutputVar, List, Selected, SysListView321, ahk_exe %EverythingExe% 19 | If (OutputVar = "") ; there was no selection so just grab the first result only 20 | { 21 | ControlGet, OutputVar, List, , SysListView321, ahk_exe %EverythingExe% 22 | OutputVar:=StrSplit(OutputVar,"`n").1 23 | } 24 | Loop, parse, OutputVar, `n, `r 25 | { 26 | filepath:=StrSplit(A_LoopField,A_Tab) 27 | result .= filepath[2] "\" filepath[1] "`n" 28 | } 29 | ; If dir 30 | ; Return % Trim(StrSplit(result,"`n").1,"`n") "\" 31 | ; else 32 | Return % Trim(result,"`n") 33 | } 34 | 35 | /* 36 | Everything_DirectoryTree() 37 | { 38 | global MatchList 39 | count:=0 40 | AutoTrim, Off 41 | SendMessage, 1074, 17, , , ahk_class TTOTAL_CMD 42 | WinGetText, PathInTC, ahk_id %ErrorLevel% 43 | drive:=SubStr(PathInTC,1,1) ":" 44 | dir:=Trim(PathInTC,"<>`r`n") 45 | StartSearch:=MatchList.settings.EvPath 46 | if InStr(StartSearch,"/dir") 47 | StartSearch:=StrReplace(StartSearch,"/drive") 48 | StartSearch:=StrReplace(StartSearch,"/drive",drive) 49 | StartSearch:=StrReplace(StartSearch,"/dir",dir) 50 | Run, % StartSearch 51 | WinWaitActive, ahk_exe Everything.exe ; note 20250209 everything64.exe v1.5 alpha 52 | ControlSend, Edit1, {space}, ahk_exe Everything.exe 53 | } 54 | 55 | Everything_DirectoryTree: 56 | Everything_DirectoryTree() 57 | Return 58 | */ 59 | -------------------------------------------------------------------------------- /lib/Explorer.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | Explorer functions 3 | */ 4 | 5 | Explorer_Active() 6 | { 7 | WinGetClass, winClass, % "ahk_id" . hWnd := WinExist("A") 8 | if winClass in CabinetWClass,ExploreWClass 9 | Return 1 10 | } 11 | 12 | Explorer_GetSelection() ; https://www.autohotkey.com/boards/viewtopic.php?t=60403#p255169 13 | { 14 | WinGetClass, winClass, % "ahk_id" . hWnd := WinExist("A") 15 | if winClass not in CabinetWClass,ExploreWClass 16 | Return 17 | for window in ComObjCreate("Shell.Application").Windows 18 | if (hWnd = window.HWND) && (oShellFolderView := window.document) 19 | break 20 | for item in oShellFolderView.SelectedItems 21 | result .= (result = "" ? "" : "`n") . item.path 22 | if !result 23 | result := oShellFolderView.Folder.Self.Path 24 | Return result 25 | } 26 | 27 | /* 28 | ; better? https://www.autohotkey.com/boards/viewtopic.php?p=462887#p462887 29 | Explorer_GetSelection() { 30 | WinGetClass, winClass, % "ahk_id" . hWnd := WinExist("A") 31 | if !(winClass ~= "^(Progman|WorkerW|(Cabinet|Explore)WClass)$") 32 | Return 33 | 34 | shellWindows := ComObjCreate("Shell.Application").Windows 35 | if (winClass ~= "Progman|WorkerW") ; IShellWindows::Item: https://goo.gl/ihW9Gm 36 | ; IShellFolderViewDual: https://goo.gl/gnntq3 37 | shellFolderView := shellWindows.Item( ComObject(VT_UI4 := 0x13, SWC_DESKTOP := 0x8) ).Document 38 | else { 39 | for window in shellWindows ; ShellFolderView object: https://is.gd/eyZ4zG 40 | if (hWnd = window.HWND) && (shellFolderView := window.Document) 41 | break 42 | } 43 | for item in shellFolderView.SelectedItems 44 | result .= (result = "" ? "" : "`n") . item.Path 45 | ;~ if !result 46 | ;~ result := shellFolderView.Folder.Self.Path 47 | Return result 48 | } -------------------------------------------------------------------------------- /lib/GetPos.ahk: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | 4 | GetPos() for Menu X,Y co-ordinates from Listbox position with alternatives 5 | by hi5 - developed for F4MiniMenu - https://github.com/hi5/ 6 | 7 | Assumption: 8 | 9 | CoordMode, Menu|ToolTip, Client 10 | 11 | Returned position: 12 | 13 | 1: At Mouse cursor 14 | 2: Centered in window 15 | 3: Right next of current file 16 | 4: Docked next of current file (Opposite panel) 17 | 18 | */ 19 | 20 | GetPos(Position="1", MenuSize="5", Offset=40) 21 | { 22 | Pos:=[] 23 | If (Position = 1) ; fastest method so deal with it first 24 | { 25 | MouseGetPos, X, Y 26 | Pos.Insert("x", X), Pos.Insert("y", Y-Offset) 27 | Return Pos 28 | } 29 | 30 | If Explorer_Active() or DoubleCommander_Active() or XYPlorer_Active() ; can't be bothered to figure it out for the time being so always center in explorer window 31 | Position = 2 32 | 33 | ; Get Active Window statistics 34 | WinGetPos, WinX, WinY, WinWidth, WinHeight, A 35 | 36 | If (Position = 2) ; second fastest method so deal with it first 37 | { 38 | X:=WinWidth/2-100, Y:=WinHeight/2-WinY ; Y:=WinHeight/2-(MenuSize*15)-50 ; Crude calculation 39 | Pos.Insert("x", X), Pos.Insert("y", Y) 40 | Return Pos 41 | } 42 | 43 | ; Get focused control info + Listbox properties to calculate Y position of popup menu 44 | ControlGetFocus, FocusCtrl, A 45 | ControlGetPos, CtrlX, CtrlY, CtrlWidth, CtrlHeight, %FocusCtrl%, A 46 | SendMessage, 0x1A1, 0, 0, %FocusCtrl%, A ; 0x1A1 is LB_GETITEMHEIGHT 47 | LB_GETITEMHEIGHT:=ErrorLevel ; 48 | SendMessage, 0x188, 0, 0, %FocusCtrl%, A ; 0x188 is LB_GETCURSEL 49 | LB_GETCURSEL:=ErrorLevel + 1 ; Convert from zero-based to one-based. 50 | SendMessage, 0x18E, 0, 0, %FocusCtrl%, A ; 0x18E is LB_GETTOPINDEX Gets the index of the first visible item in a list box. Initially the item with index 0 is at the top of the list box, but if the list box contents have been scrolled another item may be at the top. The first visible item in a multiple-column list box is the top-left item. 51 | LB_GETTOPINDEX:=ErrorLevel ; 52 | SendMessage, 0x18B, 0, 0, %FocusCtrl%, A ; 0x18B is LB_GETCOUNT Gets the number of items in a list box. 53 | LB_GETCOUNT:=ErrorLevel 54 | 55 | ; Start calculations 56 | YMulti:=LB_GETCURSEL-LB_GETTOPINDEX 57 | VisibleCount:=LB_GETCOUNT - LB_GETTOPINDEX ; Maximum number of visible rows 58 | 59 | If (LB_GETCURSEL > VisibleCount) 60 | YMulti:=VisibleCount 61 | If (LB_GETCURSEL < LB_GETTOPINDEX) or (YMulti < 1) 62 | YMulti:=1 63 | 64 | Y:=CtrlY + (YMulti * LB_GETITEMHEIGHT) 65 | If (Y > (CtrlHeight+CtrlY)) 66 | Y:=CtrlHeight+CtrlY 67 | Y-=Offset ; We assume client mode for the menu so need some offset here 68 | 69 | If (Position = 3) 70 | { 71 | X:=CtrlX + 100 72 | Pos.Insert("x", X), Pos.Insert("y", Y) 73 | Return Pos 74 | } 75 | Else If (Position = 4) 76 | { 77 | X:= CtrlX + CtrlWidth - 5 78 | Pos.Insert("x", X), Pos.Insert("y", Y) 79 | Return Pos 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /lib/QDir.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | Q-Dir functions 3 | */ 4 | 5 | QDir_Active() 6 | { 7 | IfWinActive ahk_exe Q-Dir.exe 8 | Return 1 9 | IfWinActive ahk_exe Q-Dir_x64.exe 10 | Return 1 11 | } 12 | 13 | QDir_GetSelection() 14 | { 15 | global matchlist 16 | ClipboardSave:=ClipboardAll 17 | Clipboard:="" 18 | Send % MatchList.settings.QDir 19 | Result:=Clipboard 20 | Sleep 100 21 | Clipboard:=ClipboardSave 22 | Return Result 23 | } 24 | -------------------------------------------------------------------------------- /lib/XA.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Save/Load Arrays - trueski - http://www.autohotkey.com/board/topic/85461-ahk-l-saveload-arrays/ 4 | 5 | Examples: 6 | 7 | XA_Save("Array", Path) ; put variable name in quotes 8 | XA_Load(Path) ; the name of the variable containing the array is returned 9 | 10 | Note: indented code to personal pref. 11 | 12 | */ 13 | 14 | XA_Save(Array, Path) { 15 | FileDelete, % Path 16 | FileAppend, % "`n<" . Array . ">`n" . XA_ArrayToXML(Array) . "`n", % Path, UTF-8 17 | If (ErrorLevel) 18 | Return 1 19 | Return 0 20 | } 21 | 22 | XA_Load(Path) { 23 | Local XMLText, XMLObj, XMLRoot, Root1, Root2 24 | 25 | If (!FileExist(Path)) 26 | Return 1 27 | 28 | FileRead, XMLText, % Path 29 | StringReplace, XMLText, XMLText, %A_Space%&%A_Space%, %A_Space%&%A_Space%, All ; dirty hack 30 | 31 | XMLObj := XA_LoadXML(XMLText) 32 | XMLObj := XMLObj.selectSingleNode("/*") ; */ 33 | XMLRoot := XMLObj.nodeName 34 | %XMLRoot% := XA_XMLToArray(XMLObj.childNodes) 35 | 36 | Return XMLRoot 37 | } 38 | 39 | XA_XMLToArray(nodes, NodeName="") { 40 | Obj := Object() 41 | 42 | for node in nodes 43 | { 44 | if (node.nodeName != "#text") ;NAME 45 | { 46 | If (node.nodeName == "Invalid_Name" && node.getAttribute("ahk") == "True") 47 | NodeName := node.getAttribute("id") 48 | Else 49 | NodeName := node.nodeName 50 | } 51 | 52 | else ;VALUE 53 | Obj := node.nodeValue 54 | 55 | if node.hasChildNodes 56 | { 57 | ; Same node name was used for multiple nodes 58 | If ((node.nextSibling.nodeName = node.nodeName || node.nodeName = node.previousSibling.nodeName) && node.nodeName != "Invalid_Name" && node.getAttribute("ahk") != "True") 59 | { 60 | ; Create object 61 | If (!node.previousSibling.nodeName) 62 | { 63 | Obj[NodeName] := Object() 64 | ItemCount := 0 65 | } 66 | ItemCount++ 67 | 68 | ; Use the supplied ID if available 69 | If (node.getAttribute("id") != "") 70 | Obj[NodeName][node.getAttribute("id")] := XA_XMLToArray(node.childNodes, node.getAttribute("id")) 71 | 72 | ; Use ItemCount if no ID was provided 73 | Else 74 | Obj[NodeName][ItemCount] := XA_XMLToArray(node.childNodes, ItemCount) 75 | } 76 | 77 | Else 78 | Obj.Insert(NodeName, XA_XMLToArray(node.childNodes, NodeName)) 79 | } 80 | } 81 | Return Obj 82 | } 83 | 84 | XA_LoadXML(ByRef data){ 85 | o := ComObjCreate("MSXML2.DOMdocument.6.0") 86 | o.async := false 87 | o.LoadXML(data) 88 | return o 89 | } 90 | 91 | XA_ArrayToXML(theArray, tabCount=1, NodeName="") { 92 | Local tabSpace, extraTabSpace, tag, val, theXML, root 93 | tabCount++ 94 | tabSpace := "" 95 | extraTabSpace := "" 96 | theXML := "" 97 | 98 | if (!IsObject(theArray)) 99 | { 100 | root := theArray 101 | theArray := %theArray% 102 | ; StringReplace, theArray, theArray, %A_Space%&%A_Space%, %A_Space%&%A_Space%, All ; dirty hack 103 | } 104 | 105 | While (A_Index < tabCount) 106 | { 107 | tabSpace .= "`t" 108 | extraTabSpace := tabSpace . "`t" 109 | } 110 | 111 | for tag, val in theArray 112 | { 113 | If (!IsObject(val)) 114 | { 115 | If (XA_InvalidTag(tag)) 116 | theXML .= "`n" . tabSpace . "" . XA_XMLEncode(val) . "" 117 | Else 118 | theXML .= "`n" . tabSpace . "<" . tag . ">" . XA_XMLEncode(val) . "" 119 | } 120 | 121 | Else 122 | { 123 | If (XA_InvalidTag(tag)) 124 | theXML .= "`n" . tabSpace . "" . "`n" . XA_ArrayToXML(val, tabCount, "") . "`n" . tabSpace . "" 125 | Else 126 | theXML .= "`n" . tabSpace . "<" . tag . ">" . "`n" . XA_ArrayToXML(val, tabCount, "") . "`n" . tabSpace . "" 127 | } 128 | } 129 | 130 | theXML := SubStr(theXML, 2) 131 | Return theXML 132 | } 133 | 134 | XA_InvalidTag(Tag) { 135 | Char1 := SubStr(Tag, 1, 1) 136 | Chars3 := SubStr(Tag, 1, 3) 137 | StartChars := "~``!@#$%^&*()_-+={[}]|\:;""'<,>.?/1234567890 `n`r" 138 | Chars := """'<>=/ `n`r" 139 | 140 | Loop, Parse, StartChars 141 | { 142 | If (Char1 = A_LoopField) 143 | Return 1 144 | } 145 | 146 | Loop, Parse, Chars 147 | { 148 | If (InStr(Tag, A_LoopField)) 149 | Return 1 150 | } 151 | 152 | If (Chars3 = "xml") 153 | Return 1 154 | 155 | Return 0 156 | } 157 | 158 | ; XA_XMLEncode references: 159 | ; https://en.wikipedia.org/wiki/XML#Escaping 160 | ; https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined_entities_in_XML 161 | ; added again as original source code posted at forum was lost due to forum upgrade 162 | 163 | XA_XMLEncode(Text) { 164 | StringReplace, Text, Text, &, &, All 165 | StringReplace, Text, Text, <, <, All 166 | StringReplace, Text, Text, >, >, All 167 | StringReplace, Text, Text, ", ", All 168 | StringReplace, Text, Text, ', ', All 169 | Return XA_CleanInvalidChars(Text) ; additional fix see below for reference 170 | } 171 | 172 | XA_CleanInvalidChars(text, replace="") { 173 | re := "[^\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]" 174 | Return RegExReplace(text, re, replace) 175 | 176 | /* 177 | Source: http://stackoverflow.com/questions/730133/invalid-characters-in-xml 178 | public static string CleanInvalidXmlChars(string text) 179 | { 180 | // From xml spec valid chars: 181 | // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] 182 | // any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. 183 | string re = @"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-u10FFFF]"; 184 | return Regex.Replace(text, re, ""); 185 | } 186 | */ 187 | 188 | } 189 | -------------------------------------------------------------------------------- /lib/XYPlorer.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | XYPlorer functions 3 | */ 4 | 5 | XYPlorer_Active() 6 | { 7 | IfWinActive ahk_exe XYPLorer.exe 8 | Return 1 9 | IfWinActive ahk_exe XYPLorerFree.exe 10 | Return 1 11 | } 12 | 13 | XYPlorer_GetSelection() 14 | { 15 | global matchlist 16 | ClipboardSave:=ClipboardAll 17 | Clipboard:="" 18 | Send % MatchList.settings.XYPlorer 19 | Result:=Clipboard 20 | Sleep 100 21 | Clipboard:=ClipboardSave 22 | Return Result 23 | } 24 | -------------------------------------------------------------------------------- /lib/class_lv_rows.ahk: -------------------------------------------------------------------------------- 1 | ; Source: https://gist.github.com/Pulover/5759637 2 | ; Forum : http://www.autohotkey.com/board/topic/94364-class-lv-rows-copy-cut-paste-and-drag-listviews/ 3 | 4 | ;======================================================================================= 5 | ; 6 | ; Class LV_Rows 7 | ; 8 | ; Author: Pulover [Rodolfo U. Batista] 9 | ; rodolfoub@gmail.com 10 | ; 11 | ; Additional functions for ListView controls 12 | ;======================================================================================= 13 | ; 14 | ; This class provides an easy way to add functionalities to ListViews that are not 15 | ; supported by AutoHotkey built-in functions such as Copy, Cut, Paste, Drag and more. 16 | ; 17 | ;======================================================================================= 18 | ; 19 | ; Edit Functions: 20 | ; Copy() 21 | ; Cut() 22 | ; Paste(Row=0) 23 | ; Delete() 24 | ; Move(Up=False) 25 | ; Drag(DragButton="D", AutoScroll=True, ScrollDelay=100, LineThick=2, Color="Black") 26 | ; 27 | ; History Functions: 28 | ; Add() 29 | ; Undo() 30 | ; Redo() 31 | ; 32 | ;======================================================================================= 33 | ; 34 | ; Usage: 35 | ; 36 | ; You can call the function by preceding them with LV_Rows. For example: 37 | ; LV_Rows.Copy() <-- Calls function on active ListView. 38 | ; 39 | ; Or with a handle initialized via New meta-function. For example: 40 | ; MyListHandle := New LV_Rows() <-- Creates a new handle. 41 | ; MyListHandle.Add() <-- Calls function for that Handle. 42 | ; 43 | ; Like AutoHotkey built-in functions, these functions operate on the default gui, 44 | ; and active ListView control. 45 | ; 46 | ; Initializing is required for History functions or in case your ListView has icons. 47 | ; You can also use the same handle for the Edit functions or use different 48 | ; handles for extra copy and paste actions keeping independent data in memory. 49 | ; 50 | ; In order to keep row's icons you need to initialize the class passing the 51 | ; ListView's Hwnd. For example: 52 | ; Gui, Add, ListView, hwndhLV, Columns 53 | ; MyListHandle := New LV_Rows(hLV) 54 | ; 55 | ; You may keep an individual history of each ListView using different handles. 56 | ; 57 | ;======================================================================================= 58 | 59 | Class LV_Rows 60 | { 61 | ;======================================================================================= 62 | ; Meta-Functions By creating a new instance of the class via 63 | ; Handle := New LV_Rows() you can keep different History and 64 | ; Copy / Paste data for individual ListViews. 65 | ; Pass the Hwnd of the Listiview to keep row's icons. 66 | ; 67 | ; Properties: 68 | ; ActiveSlot: Contains the current entry position in the ListView History. 69 | ; HasChanged: The HasChanged property may optionally be used to check if the 70 | ; ListView has been changed. For this you must use a handle 71 | ; for all functions. 72 | ; Every time a function (except Copy) is called it will be set 73 | ; to True. The user may consult Handle.HasChanged to show 74 | ; a save dialog and set it to False after saving. 75 | ;======================================================================================= 76 | __New(Hwnd="") 77 | { 78 | If (Hwnd) 79 | this.LVHwnd := Hwnd 80 | this.Slot := [], this.ActiveSlot := 1 81 | } 82 | 83 | __Call(Func) 84 | { 85 | If (Func <> "Copy") 86 | this.HasChanged := True 87 | } 88 | 89 | __Delete() 90 | { 91 | this.Remove("", Chr(255)) 92 | , this.SetCapacity(0) 93 | , this.base := "" 94 | } 95 | ;======================================================================================= 96 | ; Edit Functions: Edit ListView rows. 97 | ;======================================================================================= 98 | ; Function: LV_Rows.Copy() 99 | ; Description: Copy selected rows to memory. 100 | ; Return: Number of copied rows. 101 | ;======================================================================================= 102 | Copy() 103 | { 104 | this.CopyData := {}, LV_Row := 0 105 | Loop 106 | { 107 | LV_Row := LV_GetNext(LV_Row) 108 | If !LV_Row 109 | break 110 | RowData := this.RowText(LV_Row) 111 | , Row := [RowData*] 112 | , this.CopyData.Insert(Row) 113 | , CopiedLines := A_Index 114 | } 115 | return CopiedLines 116 | } 117 | ;======================================================================================= 118 | ; Function: LV_Rows.Cut() 119 | ; Description: Copy selected rows to memory and delete them. 120 | ; Return: Number of copied rows. 121 | ;======================================================================================= 122 | Cut() 123 | { 124 | this.CopyData := {}, LV_Row := 0 125 | Loop 126 | { 127 | LV_Row := LV_GetNext(LV_Row) 128 | If !LV_Row 129 | break 130 | RowData := this.RowText(LV_Row) 131 | , Row := [RowData*] 132 | , this.CopyData.Insert(Row) 133 | , CopiedLines := A_Index 134 | } 135 | this.Delete() 136 | return CopiedLines 137 | } 138 | ;======================================================================================= 139 | ; Function: LV_Rows.Paste() 140 | ; Description: Paste copied rows at selected position. 141 | ; Parameters: 142 | ; Row: If non-zero pastes memory contents into the specified row. 143 | ; Return: True if memory contains data or False if not. 144 | ;======================================================================================= 145 | Paste(Row=0) 146 | { 147 | If !this.CopyData.MaxIndex() 148 | return False 149 | TargetRow := Row ? Row : LV_GetNext() 150 | If !TargetRow 151 | { 152 | For each, Row in this.CopyData 153 | LV_Add(Row*) 154 | } 155 | Else 156 | { 157 | LV_Row := TargetRow - 1 158 | For each, Row in this.CopyData 159 | LV_Insert(LV_Row+A_Index, Row*) 160 | } 161 | return True 162 | } 163 | ;======================================================================================= 164 | ; Function: LV_Rows.Delete() 165 | ; Description: Delete selected rows. 166 | ; Return: Number of removed rows. 167 | ;======================================================================================= 168 | Delete() 169 | { 170 | If (LV_GetCount("Selected") = 0) 171 | return False 172 | LV_Row := 0 173 | Loop 174 | { 175 | LV_Row := LV_GetNext(LV_Row - 1) 176 | If !LV_Row 177 | break 178 | LV_Delete(LV_Row) 179 | , DeletedLines := A_Index 180 | } 181 | return DeletedLines 182 | } 183 | ;======================================================================================= 184 | ; Function: LV_Rows.Move() 185 | ; Description: Move selected rows down or up. 186 | ; Parameters: 187 | ; Up: If False or omitted moves rows down. If True moves rows up. 188 | ; Return: Number of rows moved. 189 | ;======================================================================================= 190 | Move(Up=False) 191 | { 192 | Selections := [], LV_Row := 0 193 | Critical 194 | If Up 195 | { 196 | Loop 197 | { 198 | LV_Row := LV_GetNext(LV_Row) 199 | If !LV_Row 200 | break 201 | If (LV_Row = 1) 202 | return 203 | Selections.Insert(LV_Row) 204 | } 205 | For each, Row in Selections 206 | { 207 | RowData := this.RowText(Row) 208 | , LV_Insert(Row-1, RowData*) 209 | , LV_Delete(Row+1) 210 | , LV_Modify(Row-1, "Select") 211 | If (A_Index = 1) 212 | LV_Modify(Row-1, "Focus Vis") 213 | } 214 | return Selections.MaxIndex() 215 | } 216 | Else 217 | { 218 | Loop 219 | { 220 | LV_Row := LV_GetNext(LV_Row) 221 | If !LV_Row 222 | break 223 | If (LV_Row = LV_GetCount()) 224 | return 225 | Selections.Insert(1, LV_Row) 226 | } 227 | For each, Row in Selections 228 | { 229 | RowData := this.RowText(Row+1) 230 | , LV_Insert(Row, RowData*) 231 | , LV_Delete(Row+2) 232 | If (A_Index = 1) 233 | LV_Modify(Row+1, "Focus Vis") 234 | } 235 | return Selections.MaxIndex() 236 | } 237 | } 238 | ;======================================================================================= 239 | ; Function: LV_Rows.Drag() 240 | ; Description: Drag-and-Drop selected rows showing a destination bar. 241 | ; Must be called in the ListView G-Label subroutine when 242 | ; A_GuiEvent returns "D" or "d". 243 | ; Parameters: 244 | ; DragButton: If it is a lower case "d" it will be recognized as a 245 | ; Right-Click drag, otherwise will be recognized as a 246 | ; Left-Click drag. You may pass A_GuiEvent as the parameter. 247 | ; AutoScroll: If True or omitted the ListView will automatically scroll 248 | ; up or down when the cursor is above or below the control. 249 | ; ScrollDelay: Delay in miliseconds for AutoScroll. Default is 100ms. 250 | ; LineThick: Thickness of the destination bar in pixels. Default is 2px. 251 | ; Color: Color of destination bar. Defalt is "Black". 252 | ; Return: The destination row number. 253 | ;======================================================================================= 254 | Drag(DragButton="D", AutoScroll=True, ScrollDelay=100, LineThick=2, Color="Black") 255 | { 256 | Static LVIR_LABEL := 0x0002 257 | Static LVM_GETITEMCOUNT := 0x1004 258 | Static LVM_SCROLL := 0x1014 259 | Static LVM_GETTOPINDEX := 0x1027 260 | Static LVM_GETCOUNTPERPAGE := 0x1028 261 | Static LVM_GETSUBITEMRECT := 0x1038 262 | Static LV_currColHeight := 0 263 | 264 | SysGet, SM_CXVSCROLL, 2 265 | 266 | If InStr(DragButton, "d", True) 267 | DragButton := "RButton" 268 | Else 269 | DragButton := "LButton" 270 | 271 | CoordMode, Mouse, Window 272 | MouseGetPos,,, LV_Win, LV_LView, 2 273 | WinGetPos, Win_X, Win_Y, Win_W, Win_H, ahk_id %LV_Win% 274 | ControlGetPos, LV_lx, LV_ly, LV_lw, LV_lh, , ahk_id %LV_LView% 275 | VarSetCapacity(LV_XYstruct, 4 * A_PtrSize, 0) 276 | 277 | While, GetKeyState(DragButton, "P") 278 | { 279 | MouseGetPos, LV_mx, LV_my,, CurrCtrl, 2 280 | LV_mx -= LV_lx, LV_my -= LV_ly 281 | 282 | If (AutoScroll) 283 | { 284 | If (LV_my < 0) 285 | { 286 | SendMessage, LVM_SCROLL, 0, -LV_currColHeight, , ahk_id %LV_LView% 287 | Sleep, %ScrollDelay% 288 | } 289 | If (LV_my > LV_lh) 290 | { 291 | SendMessage, LVM_SCROLL, 0, LV_currColHeight, , ahk_id %LV_LView% 292 | Sleep, %ScrollDelay% 293 | } 294 | } 295 | 296 | If (CurrCtrl <> LV_LView) 297 | { 298 | LV_currRow := "" 299 | Gui, MarkLine:Cancel 300 | continue 301 | } 302 | 303 | SendMessage, LVM_GETITEMCOUNT, 0, 0, , ahk_id %LV_LView% 304 | LV_TotalNumOfRows := ErrorLevel 305 | SendMessage, LVM_GETCOUNTPERPAGE, 0, 0, , ahk_id %LV_LView% 306 | LV_NumOfRows := ErrorLevel 307 | SendMessage, LVM_GETTOPINDEX, 0, 0, , ahk_id %LV_LView% 308 | LV_topIndex := ErrorLevel 309 | , Line_W := (LV_TotalNumOfRows > LV_NumOfRows) ? LV_lw - SM_CXVSCROLL : LV_lw 310 | 311 | Loop, % LV_NumOfRows + 1 312 | { 313 | LV_which := LV_topIndex + A_Index - 1 314 | NumPut(LVIR_LABEL, LV_XYstruct, 0, "UInt") 315 | , NumPut(A_Index - 1, LV_XYstruct, 4, "UInt") 316 | SendMessage, LVM_GETSUBITEMRECT, %LV_which%, &LV_XYstruct, , ahk_id %LV_LView% 317 | LV_RowY := NumGet(LV_XYstruct, 4, "UInt") 318 | , LV_RowY2 := NumGet(LV_XYstruct, 12, "UInt") 319 | , LV_currColHeight := LV_RowY2 - LV_RowY 320 | If(LV_my <= LV_RowY + LV_currColHeight) 321 | { 322 | LV_currRow := LV_which + 1 323 | , LV_currRow0 := LV_which 324 | , Line_Y := Win_Y + LV_ly + LV_RowY 325 | , Line_X := Win_X + LV_lx 326 | If (LV_currRow > (LV_TotalNumOfRows+1)) 327 | { 328 | Gui, MarkLine:Cancel 329 | LV_currRow := "" 330 | } 331 | Break 332 | } 333 | } 334 | 335 | If LV_currRow 336 | { 337 | Gui, MarkLine:Color, %Color% 338 | Gui, MarkLine:+LastFound +AlwaysOnTop +Toolwindow -Caption +HwndLineMark 339 | Gui, MarkLine:Show, W%Line_W% H%LineThick% Y%Line_Y% X%Line_X% NoActivate 340 | } 341 | } 342 | Gui, MarkLine:Cancel 343 | 344 | If LV_currRow 345 | { 346 | DragRows := new LV_Rows(this.LVHwnd) 347 | , Lines := DragRows.Copy() 348 | DragRows.Paste(LV_currRow) 349 | If (LV_GetNext() < LV_currRow) 350 | o := Lines+1, FocusedRow := LV_currRow-1 351 | Else 352 | o := 1, FocusedRow := LV_currRow 353 | DragRows.Delete() 354 | , DragRows := "" 355 | Loop, %Lines% 356 | { 357 | i := A_Index-o 358 | LV_Modify(LV_currRow+i, "Select") 359 | } 360 | LV_Modify(FocusedRow, "Focus") 361 | } 362 | return LV_currRow 363 | } 364 | ;======================================================================================= 365 | ; History Functions: Keep a history of ListView changes and allow Undo and Redo. 366 | ;======================================================================================= 367 | ; Function: Handle.Add() 368 | ; Description: Adds an entry on History. This function requires 369 | ; initializing: MyListHandle := New LV_Rows() 370 | ; Return: The total number of entries in history. 371 | ;======================================================================================= 372 | Add() 373 | { 374 | Row := [] 375 | If (this.ActiveSlot < this.Slot.MaxIndex()) 376 | this.Slot.Remove(this.ActiveSlot+1, this.Slot.MaxIndex()) 377 | Loop, % LV_GetCount() 378 | { 379 | RowData := this.RowText(A_Index) 380 | , Row[A_Index] := [RowData*] 381 | } 382 | this.Slot.Insert(Row) 383 | , this.ActiveSlot := this.Slot.MaxIndex() 384 | return this.Slot.MaxIndex() 385 | } 386 | ;======================================================================================= 387 | ; Function: Handle.Undo() 388 | ; Description: Replaces ListView contents with previous entry state, if any. 389 | ; Return: Current entry position. 390 | ;======================================================================================= 391 | Undo() 392 | { 393 | 394 | If (this.ActiveSlot = 1) 395 | return this.ActiveSlot 396 | this.ActiveSlot -= 1 397 | , this.Load(this.ActiveSlot) 398 | return this.ActiveSlot 399 | } 400 | ;======================================================================================= 401 | ; Function: Handle.Redo() 402 | ; Description: Replaces ListView contents with next entry state, if any. 403 | ; Return: Current entry position. 404 | ;======================================================================================= 405 | Redo() 406 | { 407 | If (this.ActiveSlot = (this.Slot.MaxIndex())) 408 | return this.ActiveSlot 409 | this.ActiveSlot += 1 410 | , this.Load(this.ActiveSlot) 411 | return this.ActiveSlot 412 | } 413 | ;======================================================================================= 414 | ; Internal Functions: These functions are meant for internal use but can also 415 | ; be called if necessary. 416 | ;======================================================================================= 417 | ; Function: Handle.Load() 418 | ; Description: Loads a specified entry in History into ListView. 419 | ; Parameters: 420 | ; Number: Number of entry position to be loaded. 421 | ; Return: True if entry exists, False otherwise. 422 | ;======================================================================================= 423 | Load(Number) 424 | { 425 | If !IsObject(this.Slot[Number]) 426 | return False 427 | 428 | LV_Delete() 429 | For each, Row in this.Slot[Number] 430 | LV_Add(Row*) 431 | return True 432 | } 433 | ;======================================================================================= 434 | ; Function: LV_Rows.RowText() 435 | ; Description: Creates an Array of values from each cell in a specified row. 436 | ; Parameters: 437 | ; Index: Index of the row to get contents from. 438 | ; Return: An Array with text from the cells and the row checked status. 439 | ;======================================================================================= 440 | RowText(Index) 441 | { 442 | Data := [] 443 | , ckd := (LV_GetNext(Index-1, "Checked")=Index) ? 1 : 0 444 | , iIcon := this.GetIconIndex(this.LVHwnd, Index) 445 | , Data.Insert("Icon" iIcon " Check" ckd) 446 | Loop, % LV_GetCount("Col") 447 | { 448 | LV_GetText(Cell, Index, A_Index) 449 | , Data.Insert(Cell) 450 | } 451 | return Data 452 | } 453 | ;======================================================================================= 454 | ; Function: LV_Rows.GetIconIndex() 455 | ; Description: Retrieves the row's icon index. 456 | ; Parameters: 457 | ; Hwnd: Hwnd of the ListView. 458 | ; Row: 1-based Row number. 459 | ; Return: The 1-based icon index from specified row. 460 | ;======================================================================================= 461 | GetIconIndex(Hwnd, Row) 462 | { 463 | Static LVIF_IMAGE := 0x00000002 464 | Static LVM_GETITEMA := 0x1005 465 | Static LVM_GETITEMW := 0x104B 466 | Static LVM_GETITEM := A_IsUnicode ? LVM_GETITEMW : LVM_GETITEMA 467 | 468 | VarSetCapacity(LVITEM, 6 * 4 + (A_PtrSize * 2), 0) 469 | NumPut(LVIF_IMAGE, LVITEM, 0, "UInt") ; mask 470 | NumPut(Row-1, LVITEM, 4, "Int") ; iItem 471 | SendMessage, LVM_GETITEM, 0, &LVITEM,, ahk_id %Hwnd% 472 | return NumGet(LVITEM, 5 * 4 + (A_PtrSize * 2), "Int") + 1 473 | } 474 | } 475 | 476 | -------------------------------------------------------------------------------- /lib/dpi.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | Name : DPI 3 | Purpose : Return scaling factor or calculate position/values for AHK controls (font size, position (x y), width, height) 4 | Version : 0.31 5 | Source : https://github.com/hi5/dpi 6 | AutoHotkey Forum : https://autohotkey.com/boards/viewtopic.php?f=6&t=37913 7 | License : see license.txt (GPL 2.0) 8 | Documentation : See readme.md @ https://github.com/hi5/dpi 9 | 10 | History: 11 | 12 | * v0.31: refactored "process" code, just one line now 13 | * v0.3: - Replaced super global variable ###dpiset with static variable within dpi() to set dpi 14 | - Removed r parameter, always use Round() 15 | - No longer scales the Rows option and others that should be skipped (h-1, *w0, hwnd etc) 16 | * v0.2: public release 17 | * v0.1: first draft 18 | 19 | */ 20 | 21 | DPI(in="",setdpi=1) 22 | { 23 | static dpi:=1 24 | if (setdpi <> 1) 25 | dpi:=setdpi 26 | RegRead, AppliedDPI, HKEY_CURRENT_USER, Control Panel\Desktop\WindowMetrics, AppliedDPI 27 | ; If the AppliedDPI key is not found the default settings are used. 28 | ; 96 is the default value. 29 | if (ErrorLevel=1) OR (AppliedDPI=96) 30 | AppliedDPI:=96 31 | if (dpi <> 1) 32 | AppliedDPI:=dpi 33 | factor:=AppliedDPI/96 34 | if !in 35 | Return factor 36 | 37 | Loop, parse, in, %A_Space%%A_Tab% 38 | { 39 | option:=A_LoopField 40 | if RegExMatch(option,"i)(w0|h0|h-1|xp|yp|xs|ys|xm|ym)$") or RegExMatch(option,"i)(icon|hwnd)") ; these need to be bypassed 41 | out .= option A_Space 42 | else if RegExMatch(option,"i)^\*{0,1}(x|xp|y|yp|w|h|s)[-+]{0,1}\K(\d+)",number) ; should be processed 43 | out .= StrReplace(option,number,Round(number*factor)) A_Space 44 | else ; the rest can be bypassed as well (variable names etc) 45 | out .= option A_Space 46 | } 47 | Return Trim(out) 48 | } 49 | -------------------------------------------------------------------------------- /lib/iob.ahk: -------------------------------------------------------------------------------- 1 | ;[settings] 2 | ;BackgroundHotkey=F4 3 | ;ForegroundHotkey=Esc & F4 4 | ;MaxFiles=30 5 | ;MenuPos=3 6 | ;TCPath=c:\totalcmd\TotalCmd.exe 7 | ;TCStart=1 8 | ;MaxWinWaitSec=2 9 | ;[1] 10 | ;delay=0 11 | ;exe=c:\WINDOWS\notepad.exe 12 | ;ext=txt,xml 13 | ;method=Normal 14 | ;windowmode=1 15 | 16 | iob(Filename="") 17 | { 18 | Global MatchList:=[] 19 | SectionKeys:=iob_getkeys(1) 20 | Loop, parse, SectionKeys, CSV 21 | { 22 | IniRead, OutputVar, %Filename%, Settings, %A_LoopField% 23 | if (OutputVar = "ERROR") 24 | OutputVar:="" 25 | MatchList["Settings",A_LoopField]:=OutputVar 26 | } 27 | SectionKeys:=iob_getkeys(2) 28 | IniRead, OutputVarSectionNames, %Filename% 29 | StringReplace,OutputVarSectionNames,OutputVarSectionNames,Settings,,All 30 | StringReplace,OutputVarSectionNames,OutputVarSectionNames,`n,`,,All 31 | StringReplace,OutputVarSectionNames,OutputVarSectionNames,%A_Space%,,All 32 | Loop, parse,OutputVarSectionNames, CSV 33 | { 34 | Section:=A_LoopField 35 | Loop, parse, SectionKeys, CSV 36 | { 37 | IniRead, OutputVar, %Filename%, %section%, %A_LoopField% 38 | if (OutputVar = "ERROR") 39 | break 40 | MatchList[section,A_LoopField]:=OutputVar 41 | } 42 | } 43 | If (Trim(MatchList.1.Ext,"`n`r`t ") = "") 44 | MatchList.1.Ext:="txt" ; safety as we need at least one extension for the default editor 45 | ; Return MatchList 46 | } 47 | 48 | iob_save(ObjectName,Filename="") { ; Object parameter isn't used but just added to allow same function call as XA_Save 49 | global MatchList 50 | FileCopy, %Filename%, %Filename%.bak, 1 51 | FileDelete, %Filename% 52 | SectionKeys:=iob_getkeys(1) 53 | Loop, parse, SectionKeys, CSV 54 | IniWrite, % MatchList["Settings",A_LoopField], %Filename%, Settings, %A_LoopField% 55 | SectionKeys:=iob_getkeys(2) 56 | Loop 57 | { 58 | Index:=A_Index 59 | If !MatchList.HasKey(Index) 60 | Break 61 | Loop, parse, SectionKeys, CSV 62 | IniWrite, % MatchList[Index,A_LoopField], %Filename%, %Index%, %A_LoopField% 63 | } 64 | } 65 | 66 | iob_getkeys(section) 67 | { 68 | If (Section = 1) 69 | Return "BackgroundHotkey,ForegroundHotkey,MaxFiles,MenuPos,FilteredMenuAutoEdit,MaxWinWaitSec,TCPath,TCIniPath,TCStart,F4MMCloseAll,F4MMClosePID,FilteredHotkey,FullMenu,Explorer,Everything,DoubleCommander,XYPlorer,Lister,FindFiles,QuickView,log,logfile" ; ,EvPath,EVDirTree 70 | If (Section = 2) 71 | Return "Delay,Exe,Ext,Method,Open,Windowmode,StartDir,Parameters,Icon,Name" 72 | } 73 | -------------------------------------------------------------------------------- /lib/log.ahk: -------------------------------------------------------------------------------- 1 | /* 2 | Loging function for debugging purposes, hidden settings (manual editing of settings file) 3 | */ 4 | 5 | Log(logstring,logfile) 6 | { 7 | logfile:=StrReplace(logfile,"%A_ScriptDir%",A_ScriptDir) 8 | if (logfile = "") 9 | logfile:=A_ScriptDir "\logfile.txt" 10 | FileAppend, `n%logstring%, %logfile%, UTF-8-RAW 11 | } -------------------------------------------------------------------------------- /lib/osdtip.ahk: -------------------------------------------------------------------------------- 1 | ; OSDTIP_Pop(MainText, SubText, TimeOut, Options, FontName, Transparency) 2 | ; OSDTIP_Pop("Notification", "Message", -3000) ; #Persistent required 3 | OSDTIP_Pop(P*) { ; OSDTIP_Pop v0.55 by SKAN on D361/D36E @ tiny.cc/osdtip 4 | Local 5 | Static FN:="", ID:=0, PM:="", PS:="" 6 | 7 | If !IsObject(FN) 8 | FN := Func(A_ThisFunc).Bind(A_ThisFunc) 9 | 10 | If (P.Count()=0 || P[1]==A_ThisFunc) { 11 | OnMessage(0x202, FN, 0), OnMessage(0x010, FN, 0) ; WM_LBUTTONUP, WM_CLOSE 12 | SetTimer, %FN%, OFF 13 | DllCall("AnimateWindow", "Ptr",ID, "Int",200, "Int",0x50004) ; AW_VER_POSITIVE | AW_SLIDE 14 | Progress, 10:OFF ; | AW_HIDE 15 | Return ID:=0 16 | } 17 | 18 | MT:=P[1], ST:=P[2], TMR:=P[3], OP:=P[4], FONT:=P[5] ? P[5] : "Segoe UI" 19 | Title := (TMR=0 ? "0x0" : A_ScriptHwnd) . ":" . A_ThisFunc 20 | 21 | If (ID) { 22 | Progress, 10:, % (ST=PS ? "" : PS:=ST), % (MT=PM ? "" : PM:=MT), %Title% 23 | OnMessage(0x202, FN, TMR=0 ? 0 : -1) ; v0.55 24 | SetTimer, %FN%, % Round(TMR)<0 ? TMR : "OFF" 25 | Return ID 26 | } 27 | 28 | If ( InStr(OP,"U2",1) && FileExist(WAV:=A_WinDir . "\Media\Windows Notify.wav") ) 29 | DllCall("winmm\PlaySoundW", "WStr",WAV, "Ptr",0, "Int",0x220013) ; SND_FILENAME | SND_ASYNC 30 | ; | SND_NODEFAULT 31 | DetectHiddenWindows, % ("On", DHW:=A_DetectHiddenWindows) ; | SND_NOSTOP | SND_SYSTEM 32 | SetWinDelay, % (-1, SWD:=A_WinDelay) 33 | DllCall("uxtheme\SetThemeAppProperties", "Int",0) 34 | Progress, 10:C00 ZH1 FM9 FS10 CWF0F0F0 CT101010 %OP% B1 M HIDE,% PS:=ST, % PM:=MT, %Title%, %FONT% 35 | DllCall("uxtheme\SetThemeAppProperties", "Int",7) ; STAP_ALLOW_NONCLIENT 36 | ; | STAP_ALLOW_CONTROLS 37 | WinWait, %Title% ahk_class AutoHotkey2 ; | STAP_ALLOW_WEBCONTENT 38 | WinGetPos, X, Y, W, H 39 | SysGet, M, MonitorWorkArea 40 | WinMove,% "ahk_id" . WinExist(),,% MRight-W,% MBottom-(H:=InStr(OP,"U1",1) ? H : Max(H,100)), W, H 41 | If ( TRN:=Round(P[6]) & 255 ) 42 | WinSet, Transparent, %TRN% 43 | ControlGetPos,,,,H, msctls_progress321 44 | If (H>2) { 45 | ColorMQ:=Round(P[7]), ColorBG:=P[8]!="" ? Round(P[8]) : 0xF0F0F0, SpeedMQ:=Round(P[9]) 46 | Control, ExStyle, -0x20000, msctls_progress321 ; v0.55 WS_EX_STATICEDGE 47 | Control, Style, +0x8, msctls_progress321 ; PBS_MARQUEE 48 | SendMessage, 0x040A, 1, %SpeedMQ%, msctls_progress321 ; PBM_SETMARQUEE 49 | SendMessage, 0x0409, 1, %ColorMQ%, msctls_progress321 ; PBM_SETBARCOLOR 50 | SendMessage, 0x2001, 1, %ColorBG%, msctls_progress321 ; PBM_SETBACKCOLOR 51 | } 52 | DllCall("AnimateWindow", "Ptr",WinExist(), "Int",200, "Int",0x40008) ; AW_VER_NEGATIVE | AW_SLIDE 53 | SetWinDelay, %SWD% 54 | DetectHiddenWindows, %DHW% 55 | If (Round(TMR)<0) 56 | SetTimer, %FN%, %TMR% 57 | OnMessage(0x202, FN, TMR=0 ? 0 : -1), OnMessage(0x010, FN) ; WM_LBUTTONUP, WM_CLOSE 58 | Return ID:=WinExist() 59 | } 60 | -------------------------------------------------------------------------------- /lib/tc.ahk: -------------------------------------------------------------------------------- 1 | ; TC_SendData() using WM_CopyData 2 | ; https://www.ghisler.ch/board/viewtopic.php?p=363391#p363391 3 | 4 | /* 5 | TESTED AND WORKING ON: AHK_L v 1.1.31.01 unicode & ansi version, Win 10 64bit and TC9.22 6 | modified by dindog 7 | ------------------------------------------------------------------------- 8 | TC_SendData("em_FOO" , "EM") ; User Command 9 | TC_SendData("em_APPENDTABS C:\my.tab", "EM") ; User Command with parameters (usercmd.ini as following) 10 | ; [em_APPENDTABS] 11 | ; cmd=APPENDTABS 12 | ; param=%A 13 | TC_SendData("em_CD C:", "EM") ; User Command with parameters (usercmd.ini as following) 14 | ; [em_cd] 15 | ; cmd=cd 16 | ; param=%A 17 | TC_SendData("em_命令 *.exe", "EM") ; User Command with parameters (usercmd.ini as following) test for command name non-ASCII 18 | ; [em_命令] 19 | ; cmd=cd 20 | ; param=%A 21 | 22 | TC_SendData("cmd") ; Ask TC : (cmd one of the following varues:) 23 | ; A = Active Side 24 | 25 | ; LP = Left Path RP = Right Path 26 | ; LC = Left List Count RC = Right List Count 27 | ; LI = Left Caret Index RI = Right Caret Index 28 | ; LN = Left Name Caret RN = Right Name Caret 29 | 30 | ; SP = Source Path TP = Target Path 31 | ; SC = Source List Count TC = Target List Count 32 | ; SI = Source Caret Index TI = Target Caret Index 33 | ; SN = Source Name Caret TN = Target Name Caret 34 | 35 | TC_SendData("C:\tc" "`r" "D:\data", "CD") ; CD Command: (LeftDir - RightDir) 36 | TC_SendData("C:\tc" "`r" , "R") ; CD Command: (LeftDir) and activate Right panel 37 | TC_SendData( "`r" "D:\data", "LT") ; CD Command: ( RightDir) in new tab and activate left panel 38 | 39 | TC_SendData("C:\tc" "`r" "D:\data", "S") ; CD Command: (SourceDir - TargetDir) 40 | TC_SendData("C:\tc" "`r" , "SBT") ; CD Command: (SourceDir) in new background tab 41 | TC_SendData( "`r" "D:\data", "ST") ; CD Command: ( TargetDir) in new background tab 42 | S: Interpret the paths as source/target instead of left/right 43 | T: Open path(s) in new tabs 44 | B: Open tabs in background (do not activate them) 45 | L: Activate the left panel 46 | R: Activate the right panel 47 | A: Do not open archives as directories. Instead, open parent directory and place cursor on it. 48 | TC accepts more then 2 parameters here, so sending e.g. STBL is legitimate. 49 | */ 50 | 51 | TC_SendData(Cmd, CmdType="", msg="", hwnd="") { 52 | Critical ; Define "OnMessage" as STATIC it is registered at Script startup. 53 | STATIC om:=OnMessage(0x4a, "TC_SendData"), TC_ReceiveDataValue:="", TC_DataReceived:="" ; 0x4a is WM_COPYDATA 54 | 55 | IF ((msg=0x4A) AND (hwnd=A_ScriptHwnd)) ; EnSure is trigered by this Script. 56 | EXIT (TC_ReceiveDataValue:=StrGet(NumGet(CmdType + A_PtrSize * 2)), TC_DataReceived:="1") 57 | 58 | VarSetCapacity(CopyDataStruct, A_PtrSize * 3), TC_ReceiveDataValue:=1, TC_DataReceived:="" 59 | if (CmdType="") ; Ask TC 60 | CmdType:=(A_IsUnicode ? "GW" : "GA"), TC_ReceiveDataValue:="" 61 | else if (CmdType="EM") or (CmdType="em") ; em command 62 | CmdType:="EM" 63 | else ; CD command STBALR 64 | DirType:=(CmdType="CD")?"":CmdType, CmdType:="CD" 65 | 66 | ;;;;;;VarSetCapacity need to request at least 5 more byte to allow 4 CD params 67 | VarSetCapacity(cmdA, StrPut(cmd, (A_IsUnicode ?"UTF-8":"CP0")) + (CmdType="CD" ? 5 : 0) * (A_IsUnicode ? 2 : 1), 0) , Len:=StrPut(cmd, &cmdA, (A_IsUnicode ?"UTF-8":"CP0")) 68 | 69 | 70 | 71 | NumPut( Asc(SubStr(CmdType,1,1)) + 256 * Asc(SubStr(CmdType,2,1)), CopyDataStruct,0 ) 72 | NumPut( Len + (CmdType="CD" ? 5 : 0) * (A_IsUnicode ? 2 : 1) , CopyDataStruct, A_PtrSize ) 73 | NumPut( &cmdA , CopyDataStruct, A_PtrSize * 2) 74 | Loop, % strlen(DirType) ;(CmdType=="CD" ? 2 : 0) 75 | { 76 | NumPut(Asc(SubStr(DirType,A_Index,1)), cmdA ,Len+A_Index-1, "Char") 77 | } 78 | SendMessage, 0x4A,%A_ScriptHwnd%, &CopyDataStruct,, ahk_class TTOTAL_CMD 79 | 80 | While (TC_ReceiveDataValue="") { 81 | IfEqual, TC_DataReceived, 1, Break 82 | IfGreaterOrEqual, A_Index, 500, Break 83 | Sleep,10 84 | } 85 | Return TC_ReceiveDataValue 86 | } 87 | 88 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2025 hi5 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # F4MiniMenu - v1.47 2 | 3 | A F4 Menu program for [Total Commander](http://www.ghisler.com/) to open selected file(s) in editor(s). 4 | (and experimental/rudimentary support for Windows Explorer, Double Commander, XYPlorer, and Everything - only [when activated](#other-programs)). 5 | 6 | It is a *standalone* program which runs separatly from Total Commander. See Getting Started. 7 | 8 | ## Features 9 | 10 | * Open selected files in defined Editor(s) - on a first come, first serve basis 11 | * Optional: Show menu with: 12 | a. All Editors (full menu) 13 | b. Matching Editors based on extension (filtered menu) 14 | * Various methods to open selected files: "[regular](#normal)", "[Drag & Drop](#drag-drop)", [Filelist](#filelist), [cmdline](#cmdline) 15 | * Document Templates to create new files for file types other than "text" - [DocumentTemplates README](DocumentTemplates/readme.md) 16 | * Open source - written in [AutoHotkey](https://www.autohotkey.com/) (v1.1) 17 | 18 | ## Discussion 19 | 20 | * [F4MiniMenu TC Forum thread](http://ghisler.ch/board/viewtopic.php?t=35721). 21 | * [GH Issues](https://github.com/hi5/F4MiniMenu/issues) 22 | 23 | # Introduction 24 | 25 | F4 is the shortcut key used in [Total Commander](http://www.ghisler.com/) - a file manager 26 | for Windows - for opening selected files in a pre-defined editor. In TC only one program can 27 | be assigned to F4 making it impossible to define or select other editors for different file 28 | types. Several tools have been made to solve this problem, these include: 29 | 30 | * [ChoiceEditor](http://www.totalcmd.net/plugring/ChoiceEditor.html) 31 | * [Open File shell for TC](http://www.totalcmd.net/plugring/OpenFileTC.html) 32 | * [Total Commander Edit Redirector](http://ghisler.ch/board/viewtopic.php?t=27573) 33 | * [Total Editor](https://www.ghisler.ch/board/viewtopic.php?t=81215) 34 | * and of course [F4Menu](http://ghisler.ch/board/viewtopic.php?t=17003) - TC Forum thread 35 | 36 | While the original F4Menu[1] has quite a few options, this "clone" started out as a minimalistic 37 | program with only the basic functionality: opening multiple file types in various editors. 38 | 39 | There are various methods to open selected files: regular, "[Drag & Drop](#drag--drop)", [Filelist](#filelist) 40 | or by making use of a [cmdline](#cmdline) option. 41 | 42 | There is a helper script to use F4MiniMenu settings as the "internal editor" defined in 43 | Total Commander and use so called **DocumentTemplates** for creating new files. 44 | See [F4TCIE](#helper-script-f4tcieahk). 45 | 46 | There are *two* foreground menus: 47 | 48 | 1. Show all programs in the menu 49 | 2. Show matching programs (filtered): only show those programs which match the extensions 50 | of the selected files. Access the full menu by using the 'full menu' option 51 | that is shown in this filtered menu. The default editor will remain the first menu 52 | entry. If a matching program can not be found, the full menu is shown instead. (See settings) 53 | 54 | Passive mode, F4MiniMenu doesn't have to remain in memory for it to work, see [passive](#passive). 55 | 56 | ## First come, first serve 57 | 58 | __F4MiniMenu__ will open a file in the __first__ editor it finds a match for based on the 59 | __extension__. If there is no match, it will open the file(s) in the default editor. 60 | The default editor is the first editor listed in the [*Configure editors*](#screenshots) 61 | window and in the configuration file (XML or INI) it will be the first entry. 62 | To open the file(s) in another program use the [*Foreground* menu](#screenshots) option. 63 | See screenshot below. 64 | 65 | Add or modify editors via the tray menu or by bringing up the Foreground menu. 66 | `%Commander_Path%` and other variables can be used in the path(s) to the editors and icons. 67 | 68 | ### Tip(s) 69 | 70 | In principle F4Menu (or other tools) and F4MiniMenu can be run side by side as long as 71 | there are no conflicting keyboard shortcuts. In case of the same hotkey setup, F4MiniMenu 72 | will take precedence. Set the F4MiniMenu shortcuts via the tray menu, right click, Settings option. 73 | 74 | In general: be careful opening with opening large numbers of files at once, programs can crash 75 | and your computer could become unstable requiring a reboot. 76 | 77 | Do not edit the `F4MiniMenu.xml` or `F4MiniMenu.ini` settings file while the script is running, any 78 | changes made will be overwritten when the script exits. A backup is made at startup and saved as 79 | `F4MiniMenu.xml.bak` or `F4MiniMenu.ini.bak` 80 | 81 | ### Disclaimer 82 | 83 | Use at your own risk. 84 | 85 | # Getting Started 86 | 87 | Start `F4MiniMenu.ahk` (or `F4MiniMenu-64.exe`, `F4MiniMenu-32.exe`, available in [Releases](https://github.com/hi5/F4MiniMenu/releases)). 88 | 89 | Note that F4MiniMenu is a program that runs on its **own** and sits in the tray menu waiting 90 | for Total Commander windows (and others if set up) to be _Active_ and the defined hotkeys to be 91 | pressed to take action (e.g. _Edit files_, default: F4; or _Show a menu_ default: Esc+F4). 92 | Access the settings and define(d) editors via the tray menu or [foreground menu](https://github.com/hi5/F4MiniMenu#screenshots) - Esc+F4. 93 | 94 | No changes to the TC settings are required, although there is a helper script (program), see [F4TCIE](#helper-script-f4tcieahk), 95 | which does need to be defined as `editor` in the TC Settings for working with files in archives and FTP. 96 | 97 | Once F4MiniMenu is started, the Global settings and new editors with a variety of options (as outlined below) can be changed and added. 98 | 99 | (Additional information in the "Setup" section below.) 100 | 101 | # Settings 102 | 103 | ## Global configuration 104 | 105 | * Menu 106 | - Position of Menu 107 | - Accelerator key for full menu when using the filtered menu 108 | - Show Menu or Edit file directly when using the filtered menu 109 | * Files (Maximum number of files to be opened, will ask for confirmation if more are selected) 110 | * WinWait -- see below 111 | * Total Commander 112 | - TC Start (Start Total Commander when F4MM is started, or not) 113 | - TC Path, TC INI Path (for F4Edit settings, see "Use elsewhere in TC") 114 | - Close F4MM options (Exit F4MM when Total Commander closes) 115 | * Hotkeys (Note: when using F4MM with other programs it may be that the hotkeys do not work as expected, especially for programs running as Administrator) 116 | - Background (open files directly, do not show a menu) 117 | - Foreground menu (select program (from all programs) to open all selected files with) 118 | - Filtered menu (select program (filtered programs based on matching extensions) to open all selected files with) 119 | * Other programs (1) 120 | - Explorer, Double Commander, XYPlorer, Everything. 121 | * Use elsewhere in TC 122 | - Lister(2), Find Files, QuickView(3) 123 | 124 | (1) Support for other programs may stop or change at any time when new versions of those programs are being used. 125 | (1a) In Everything >v1.5+ F4 is assigned to "Focus Next Selected", F4MM will overrule this functionality - select another shortcut (either in F4MM or Everything) is this is not desired behaviour. (Settings in Everything may change during the programs development, still Alpha Feb. 2025) 126 | 127 | (2) If **Lister** setting is active _and_ `F4Edit>1` in wincmd.ini: _close Lister window_ - See `F4Edit=` options in TC help file on how to handle F4 in lister via wincmd.ini (Introduced in TC v11.03). 128 | 129 | (3) **QuickView** is experimental: 130 | `[x]` when checked, it will try to open the file that is currently open in the QuickView panel, _even_ if multiple files are selected in the active TC panel and the focus is NOT on the QuickView panel it self. The foreground and filtered menus can be opened in the QuickView panel, but here also only the one "viewed" file will be opened. 131 | `[ ]` when unchecked all selected files will be opened even when QuickView is being used. 132 | 133 | __WinWait__ Set the maximum time in seconds to wait for the selected program window to appear before applying the selected Window Mode (Normal, Maximized, Minimized -- see Editor configuration). This should also prevent any unexpected "waiting" in case a program launch failed (crash, very slow program start etc). 134 | As soon as the window appears it will continue to apply the Window mode and no longer wait. 135 | It may not be possible to edit (open) a new document during this defined waiting period. 136 | 137 | ## Editor configuration 138 | 139 | The following options can be set for each editor: 140 | 141 | * Path to Program executable. See Path variables. 142 | * Extensions as a comma separated list 143 | * Parameters to pass on -- if any, see Parameters/Options. 144 | * Start directory (if any) 145 | * Method (normal, drag & drop, filelist, cmdline) -- see Methods below 146 | * Window Mode (Normal (often last used window size and position), Maximized, Minimized) 147 | * Icon to use in the menu as alternative to program's icon (if any) 148 | * Name to use in the menu as alternative to the program.exe (if any) 149 | * Drag & Drop delay in millisecond (time to wait before sending drag & drop command so program can start) 150 | * Open delay in milliseconds (time to wait before opening the first file so program can start) 151 | 152 | ## Path variables 153 | 154 | All path variables should be wrapped in `%` signs, examples: 155 | 156 | * `%Commander_Path%\tools\lister.exe` 157 | * `%WinDir%\write.exe` 158 | * `%A_ScriptDir%\..\..\Portable\CudaText\cudatext.exe` 159 | 160 | TC Environment variable: 161 | 162 | * Commander_Path 163 | 164 | AutoHotkey path variables: 165 | 166 | * A_ScriptDir 167 | * A_ComputerName 168 | * A_UserName 169 | * A_WinDir 170 | * A_ProgramFiles 171 | * A_AppData 172 | * A_AppDataCommon 173 | * A_Desktop 174 | * A_DesktopCommon 175 | * A_StartMenu 176 | * A_StartMenuCommon 177 | * A_Programs 178 | * A_ProgramsCommon 179 | * A_Startup 180 | * A_StartupCommon 181 | * A_MyDocuments 182 | 183 | Environment path variables: 184 | 185 | * ComSpec 186 | * WinDir 187 | * ProgramFiles 188 | * ProgramFiles(x86) 189 | * ProgramW6432 190 | 191 | From the [AutoHotkey documentation](https://www.autohotkey.com/docs/v1/Variables.htm#os): 192 | 193 | The Program Files directory (e.g. `C:\Program Files` or `C:\Program Files (x86)`). This is usually the same as the `ProgramFiles` environment variable. 194 | 195 | On 64-bit systems (and not 32-bit systems), the following applies: 196 | 197 | * If the executable (EXE) that is running the script is 32-bit, `A_ProgramFiles` returns the path of the "Program Files (x86)" directory. 198 | * For 32-bit processes, the `ProgramW6432` environment variable contains the path of the 64-bit Program Files directory. On Windows 7 and later, it is also set for 64-bit processes. 199 | * The `ProgramFiles(x86)` environment variable contains the path of the 32-bit Program Files directory. 200 | 201 | # Methods 202 | 203 | There are four methods to start a program and open the selected file(s). 204 | 205 | ## Normal 206 | 207 | This works in many cases and is similar to opening a file in TC by pressing enter or double click (or traditional F4). 208 | When multiple files are selected and the program(s) needs to be started first, a delay per editor can be set before 209 | attemping to open the second and other files: Delay for Open. A similar delay can be set for Drag & Drop. Normal is the default method. 210 | 211 | ## Drag & Drop 212 | 213 | When the program is already running F4MM attempts to Drag & Drop the selected files into the application. 214 | If the program is not running, it is started using the normal method for the first file, then subsquent 215 | files are Drag & Dropped. In order to give the application some time to start, before D&D the second and 216 | other files a delay can be set per editor - Delay for Drag & Drop. A simlar delay can be set for Normal. 217 | 218 | Many programs support Drag & Drop, but not all programs will respond well to the Drag & Drop 219 | method used in this script. If it does not seem to work with a particular program, try 220 | the Normal or cmdline method(s). 221 | 222 | ## Filelist 223 | 224 | Some programs can open files which are listed in a (temporary) file. In Total Commander 225 | there is something similar in the _Button bar_ and in the _Start Menu_ where a file list -- 226 | the `%L` parameter -- can be used to create a list with the names of the selected files and 227 | directories, one file per line. __F4MiniMenu__ can do the same. A temporary file named 228 | `$$f4mtmplist$$.m3u` is created which is passed on to the target program. 229 | 230 | *Example Filelist usage:* 231 | 232 | Program: C:\Program Files\XnView\xnview.exe 233 | Parameters: -filelist 234 | Method: 3 - Filelist 235 | 236 | Result: Selected files will be opened in the XnView browser. 237 | 238 | Program: C:\Program Files\IDMComp\UltraEdit\uedit64.exe 239 | Parameters: /f 240 | Method: 3 - Filelist 241 | 242 | Result: Selected files will be opened in UltraEdit. /f is the command line parameter required for UltraEdit. 243 | 244 | ## cmdline 245 | 246 | To pass the selected files to the program on the command line `"program.exe" "file1" "file2" "etc"`. 247 | Paths to the program and files are quoted automatically. 248 | 249 | *Examples cmdline usage:* 250 | 251 | Program: C:\Program Files\Meld\Meld.exe 252 | Method: 4 - cmdline 253 | 254 | Result: Selected files will be opened in Meld (diff program) [Discussion](https://github.com/hi5/F4MiniMenu/issues/14) 255 | 256 | Program: c:\tools\mp3wrap\mp3wrap.exe 257 | Parameters: ?output.mp3 258 | Startdir: %p 259 | Method: 4 - cmdline 260 | 261 | Result: Selected MP3 files will be merged into one larger MP3 file asking the user for a filename 262 | (output.mp3 would be default) 263 | 264 | Program: c:\Portable\vscodium\VSCodium.exe 265 | Parameters: -filelist 266 | Method: 3 - Filelist 267 | 268 | Result: Selected files will be opened in VSCodium (works the same for Microsoft Visual Studio Code) 269 | 270 | *Notes:* 271 | 272 | * The reason for the .m3u extension is simple: it enables playlist support for WinAmp: Select 273 | multiple music files and press the hotkey to play the selected files. If the temporary file 274 | didn't have the .m3u extension WinAmp wouldn't recognize it as a playlist. 275 | * The temporary file `$$f4mtmplist$$.m3u` is __not__ deleted directly after use to avoid 276 | problems with slow programs. It is deleted when __F4MiniMenu__ starts or closes. 277 | 278 | ## Parameters/Options 279 | 280 | (The TC file manager has two file panels side by side referred to as Source and Target) 281 | 282 | |Parameter|Meaning| 283 | |---------|-------| 284 | |`%P` |insert the source path into the command line, including a backslash \ at the end.| 285 | |`%T` |insert the current target path, including a backslash \ at the end. (TC only, see notes)| 286 | |`%O` |places the current filename without extension into the command line.| 287 | |`%E` |places the current extension (without leading period) into the command line.| 288 | |`?` |as the first parameter causes a Dialog box to be displayed before starting the program, containing the parameters that follow. This allows the parameters to be changed before starting the program or prevent the programs execution.| 289 | |`%N` |places the filename under the cursor into the command line.| 290 | |`%M` |places the current filename in the target directory into the command line.| 291 | |`%$DATE:placeholders%`|See TC help, "Environment variables". Valid placeholders: y,Y,M,D,h,H,i1,i,m,s.| 292 | |**F4MM specific options:**|-------| 293 | |`%f41` |placeholder to alter position of filenames on the command line. (see notes and example below)| 294 | |`%$DATE:placeholders\|Value\|TimeUnits%`|if _Value_ and _TimeUnits_ are present, these parameters allow for "Date & Time Math" to add or substract TimeUnits. TimeUnits can be either `Seconds`, `Minutes`, `Hours`, or `Days`. See TimeUnits of the https://www.autohotkey.com/docs/v1/lib/EnvAdd.htm command.| 295 | 296 | Notes: 297 | 298 | 1. More _%f4_ fields may be added in the future. 299 | 2. %T for other file managers %T will use the same value as %P 300 | 301 | *Example: %f41* 302 | 303 | F4MiniMenu starts programs as follows: 304 | 305 | _ProgramName.exe Parameters File(s) Startdir_ 306 | 307 | But for some programs the _parameter(s)_ - the additional command(s) that need to be passed 308 | on to the program - have the come _AFTER_ the _File(s)_. So by using %f41 as a placeholder 309 | in the parameters field it will instruct F4MiniMenu where to place the files on the 310 | "command line" 311 | 312 | Program: pdftk.exe 313 | Parameters: %f41 burst 314 | 315 | So the program now starts as _pdftk.exe file.pdf burst_ (instead of _pdftk.exe burst file.pdf_) 316 | 317 | *Example: %$DATE:placeholders|Value|TimeUnits%* 318 | 319 | `%$DATE:Y-M-D|7|Days%` -> A week from now e.g. add 7 Days ahead. -7 would be last week. 320 | 321 | # Helper script: F4TCIE.ahk 322 | 323 | Use F4TCIE for editing files in: 324 | 325 | * an Archived file (e.g. ZIP panel) 326 | * FTP connection 327 | * Create new file (Shift+F4) 328 | 329 | Rename the script or exe to to end with an "i" to an INI setup, e.g. `F4TCIEi.ahk` or `F4TCIEi.exe`. 330 | (see 'XML or INI') 331 | 332 | ## Setup F4TCIE 333 | 334 | When F4MiniMenu sees the selected files are in an archive or in an FTP panel, 335 | it uses the default Total Commander Edit command. It will only use the first 336 | file if multiple files have been selected in the archive or FTP panel. 337 | 338 | To configure Total Commander to use F4TCIE.ahk: 339 | 340 | TC, Configuration, Edit/View, Editor (xml): 341 | drive:\path-to\F4TCIE.ahk "%1" 342 | 343 | TC, Configuration, Edit/View, Editor (ini): 344 | drive:\path-to\F4TCIEi.ahk "%1" 345 | 346 | Note: if both AutoHotkey v1.1 and v2 are installed an error message may be shown (from the AutoHotkey launcher). 347 | In that case include the full path of the AutoHotkey v1.1 executable before the drive:\path-to\F4TCIE.ahk like so: 348 | 349 | TC, Configuration, Edit/View, Editor: 350 | c:\program files\autohotkey\autohotkey.exe drive:\path-to\F4TCIE.ahk "%1" 351 | 352 | Tip: To use %PROCESSOR_ARCHITECTURE% 353 | 354 | Rename 355 | 356 | F4TCIE-64i.exe -> F4TCIE-amd64i.exe 357 | F4TCIE-32i.exe -> F4TCIE-x86i.exe 358 | 359 | then use 360 | 361 | drive:\path-to\F4TCIE-%PROCESSOR_ARCHITECTURE%.exe "%1" 362 | 363 | If for some reason the configuration can not be opened, an attempt is made to start the editor 364 | for the file type associated in Windows (so for txt -> notepad, for bmp,jpg -> MS Paint etc). 365 | When there is no editor for the file type found `notepad.exe` is started. 366 | 367 | Reference: see also [#13](https://github.com/hi5/F4MiniMenu/issues/13) 368 | 369 | # DocumentTemplates 370 | 371 | F4TCIE can also make use of DocumentTemplates when creating New files in 372 | Total Commander using the shift+f4 shortcut. 373 | 374 | More information can be found in the [DocumentTemplates README](DocumentTemplates/readme.md) 375 | 376 | # Setup 377 | 378 | ## Requirements 379 | 380 | * AutoHotkey 1.1+ (Ansi or Unicode) 381 | * Total Commander (or some other file managers) 382 | 383 | ## Install 384 | 385 | ### Script 386 | 387 | Download the source as a ZIP from GitHub here 388 | and unpack. To start it simply run `F4MiniMenu.ahk`. Setup F4MiniMenu using the tray menu 389 | options for *Settings* and *Configure editors*. 390 | 391 | Once the shortcuts have been setup access *Settings* and *Configure editors* via the Foreground 392 | menu options by pressing the shortcut (press Esc+F4 by default). 393 | See screenshots below. 394 | 395 | ### Executable 396 | 397 | 1. Compile the script to a standalone executable using [AHK2Exe](https://autohotkey.com/download/). 398 | [Documentation](https://autohotkey.com/docs/Scripts.htm#ahk2exe) 399 | 2. Or see https://github.com/hi5/F4MiniMenu/releases (32 & 64 bit versions of both F4MiniMenu and F4TCIE) 400 | 401 | ## XML or INI - There are two versions: 402 | 403 | 1. F4MiniMenu.ahk (and F4TCIE.ahk) use(s) XML to store its settings (F4MiniMenu.xml) 404 | 2. To store settings in the INI format (F4MiniMenu.ini) simply rename the (compiled) script(s) so it ends with an i (letter i) 405 | so rename or copy F4MiniMenu.ahk to F4MiniMenui.ahk (and F4TCIE.ahk to F4TCIEi.ahk). 406 | 407 | ## Closing F4MiniMenu 408 | 409 | Use tray menu, exit. 410 | 411 | Automatically close F4MiniMenu using the following options (available via Settings): 412 | 413 | 1. Close F4MM when all copies of TC close: this waits until all running copies of Total Commander are closed, then exit F4MiniMenu. 414 | 2. Close F4MM when TC closes started by F4MM: If (a new) Total Commander was started via F4MiniMenu, wait until that specific Total Commander instance closes, then exit F4MiniMenu. 415 | 416 | # Passive (use in button, start menu, user cmd) 417 | 418 | **Important** Do not use passive mode when F4MiniMenu is already running. 419 | 420 | First parameter must be the file list which contains the selected files in Total Commander or Double Commander (refer to file manager documentation for further information). 421 | 422 | Optional parameters are /P1, /P2, /M1, and /M2 423 | 424 | Examples: 425 | 426 | ``` 427 | Command: F4MiniMenu.ahk 428 | Parameters: %L 429 | 430 | Command: F4MiniMenui.ahk 431 | Parameters: %L /P1 /M1 432 | 433 | Command: F4MiniMenu.exe 434 | Parameters: %L /P2 /M2 435 | ``` 436 | 437 | |Parameter|Meaning| 438 | |---------|-------| 439 | |%L | List file in the TEMP directory with the names of the selected files to be processed by F4MiniMenu (by file manager) | 440 | |/P1 | Menu position at Mouse cursor (useful to have it show at button bar location) | 441 | |/P2 | Menu position Centered in window | 442 | |/M1 | Full menu | 443 | |/M2 | Filtered menu | 444 | |/ED | Open Editors, ignore all other options | 445 | |/SET | Open Settings, ignore all other options | 446 | 447 | ## Other programs 448 | 449 | ### File managers 450 | 451 | The foreground and background menu should work with Explorer, Double Commander, XYPlorer, and Everything. 452 | 453 | Not supported: 454 | 455 | * Starting and Closing of these file managers and/or F4MiniMenu 456 | * DocumentTemplates 457 | * Positioning of the menu - defaults to "Centered in window" 458 | 459 | Each file manager has to be (de)activated in the settings. 460 | 461 | To enable: 462 | 463 | * for Explorer and Everything: tick the checkbox (on) 464 | * for Double Commander and XYPlorer set the hotkey that will copy the full path names to the clipboard, e.g. the equivalent of the `cm_CopyFullNamesToClip` TC command (Double Commander default: Ctrl+Shift+c, XYPlorer default: Ctrl+p) 465 | * save the settings (OK) - F4MiniMenu should reload automatically and now work with the activated file managers. 466 | 467 | To disable: 468 | 469 | * for Explorer and Everything: tick the checkbox (off) 470 | * for Double Commander and XYPlorer delete the hotkey(s) (press DEL) 471 | * save the settings (OK) 472 | 473 | As support for these other file managers is not thoroughly tested, unexpected behaviour may occur. 474 | 475 | ## Screenshots 476 | 477 | __Foreground menu__ 478 | 479 | ![Foreground menu](https://raw.github.com/hi5/F4MiniMenu/master/img/f4-foreground-menu.png) 480 | 481 | __Confirm maximum__ 482 | 483 | ![Confirm maximum](https://raw.github.com/hi5/F4MiniMenu/master/img/f4-confirm-maximum.png) 484 | 485 | __General program settings__ 486 | 487 | ![General program settings](https://raw.github.com/hi5/F4MiniMenu/master/img/f4-general-settings.png) 488 | 489 | __Configure editors__ 490 | 491 | ![General program settings](https://raw.github.com/hi5/F4MiniMenu/master/img/f4-configure-editors.png) 492 | 493 | __Editor configuration__ 494 | 495 | ![Editor configuration](https://raw.github.com/hi5/F4MiniMenu/master/img/f4-editor-setttings.png) 496 | 497 | ## TODO - Known issues 498 | 499 | 1. TOFIX: If the order of the editors is changed first and then a new one is added, the order is set back to the initial order. 500 | 501 | 2. INFO: Two options for delay: 502 | 2.1 Drag & Drop delay gives program to start up before trying to drop the files - you may need to apply trail and error. 503 | 2.2 Open delay, pauses X ms to open first file. 504 | 505 | ## Credits 506 | 507 | ### Used AHK Functions & Libraries 508 | 509 | * [Class LV_Rows](http://www.autohotkey.com/board/topic/94364-class-lv-rows-copy-cut-paste-and-drag-listviews/) by [Pulover](https://github.com/Pulover/) - as of v0.6 510 | * [XA Save / Load Arrays to/from XML Functions](https://github.com/hi5/XA) 511 | * [DropFilesA - SKAN](http://www.autohotkey.com/board/topic/41467-make-ahk-drop-files-into-other-applications/#entry258810) including Unicode version [nimda](http://www.autohotkey.com/board/topic/79145-help-converting-ahk-ahk-l/#entry502676) 512 | * [OSDTIP_Pop() - SKAN](https://www.autohotkey.com/boards/viewtopic.php?t=76881#p333577) 513 | * [TC_SendData() - dindog and others](https://www.ghisler.ch/board/viewtopic.php?p=363391#p363391) - using WM_CopyData 514 | * [AutoXYWH() - toralf and tmplinshi](https://www.autohotkey.com/boards/viewtopic.php?t=1079) 515 | 516 | ## Changelog 517 | 518 | * See [changelog.md](changelog.md) 519 | 520 | ### Notes 521 | 522 | [1] Based on original idea from F4Menu by Shao Shanny - Backup links for the program can be found on the [Total Commander forum](http://ghisler.ch/board/viewtopic.php?t=17003) 523 | 524 | -------------------------------------------------------------------------------- /res/f4.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hi5/F4MiniMenu/34d131ef7b47bef92dd4e120032674ac249ce5b3/res/f4.ico --------------------------------------------------------------------------------