/* ********** MISC HACKS ********** */ /* ============= Switches etc ============ */ A_HotkeyInterval := 1000 A_MaxHotkeysPerInterval := 6 A_MaxThreads := 5 ; Processlasso reports that normally the program uses 2 threads. A_MaxThreadsPerhotkey := 1 #MaxThreadsPerHotkey 1 #SingleInstance Force #Warn Persistent ListLines False DetectHiddenText "Off" DetectHiddenWindows "Off" SetWinDelay 0 processSetPriority 'B' ; This sets default priority for new threads. /* ======= Globals ======= */ debug := true key := { turnOn: { altC_winClose: true, ctrlSpace_search: false, ; ^ Can clash with Kpirinha maximise: true, printSnip: false, ; The stupid 'snip' app will merely paste the screenshot to the clipboard unless global 'notification' settings are setup in a particular way. terminal: true }, turnOff: { magnify: true, metro: false, superM: false, WinSpace: true }, remap: { superD_to_superM: true, ; Will do something only if key.turnOff.superM is false. ; Note also that seemingly Fences's claim to yield an improved Win-D ; is false and does not work whatever the values set here. superF_to_firefox: true } } ; NB: In order to shop the damn Amazon KindleForPC stealing ctrl-alt-K, the user must do the following: find the app in the taskbar, right click, and clear the shortcut field. ; 'aria' files are cruft from Office and from OneDrive. misc := { adobeUpdate_kill: { do: true }, ariaDelete: { do: true, intervalMs: 360000 }, kopia: { do: true, checks: { intervalMs: 280, total: 30 }, hide: { delayInitalMs: 2200, do: false } }, phoneLink: { do: false, checks: { intervalMs: 285, total: 40 }, delayInitalMs: 3000, }, screenshots_clearOld: { dir: "R:\Screenshots", do: true, checkIntervalMinutes: 10, maxFileAgeInMinutes: 60 } } path := { editor: "C:\Program Files\Sublime Text\sublime_text.exe", firefox: "C:\Program Files\Mozilla firefox\firefox.exe", script: { dir: "", extension: "ahk", full: "" }, sprite: { dir: "", file: "", leaf: "trayicon.ico" } } /* =========================================================== Libraries Cannot use a variable (save an inbuilt one) with '#include'. Cannot #include _conditionally_. ============================================================ */ #include C:\Scripts\autohotkey\libraries\Debug.ahk /* ========= Functions ========= */ /* ---------- Menu stuff ---------- */ menu_setup() { A_TrayMenu.Delete ; Menu, tray, NoStandard A_TrayMenu.add('Edit script', menu_action_edit) A_TrayMenu.add ; Creates a separator line A_TrayMenu.add("Exit", menu_exit) traySetIcon(path.sprite.file) } menu_action_edit(*) { processSetPriority 'N' run path.editor . " " . path.script_full processSetPriority 'L' } /* ------- Misc ------- */ getActiveExplorerPath() { local explorerHwnd, window critical "On" explorerHwnd := WinActive("ahk_class CabinetWClass") if(explorerHwnd==0) explorerHwnd := winExist("ahk_class CabinetWClass") if explorerHwnd { for window in ComObject("Shell.Application").Windows{ try { if (window && window.hwnd && window.hwnd==explorerHwnd) { critical "Off" return window.Document.Folder.Self.Path } } } } critical "Off" return "ERROR" } /* -------------- Hotkey actions -------------- */ action_hotkey_toggleMax(*) { local active_id, minMax if debug dbg_msg(A_ThisFunc, "action_hotkey_toggleMax triggered") active_id := WinGetID("A") if not active_id return minMax := WinGetMinMax("ahk_id" active_id) if minMax = 1 { ; Window is maximized winRestore("ahk_id" active_id) } else { winMaximize("ahk_id" active_id) } } action_hotkey_toggleMin(*) { local active_id, minMax active_id := WinGetID("A") if not active_id return minMax := WinGetMinMax("ahk_id" active_id) if minMax = 1 { ; Window is maximized winRestore("ahk_id" active_id) } else { WinMinimize("ahk_id" active_id) } } ; Need Windows Terminal. ; Adapted from: ; https://github.com/shanselman/WindowsTerminalHere/issues/4; ; https://github.com/shanselman/WindowsTerminalHere/issues/4 action_hotkey_terminal(*) { local explorerPath, explorerPathQuoted critical "On" processSetPriority 'N' ; Need not do 'critical, Off' later. ; For, critical is per thread & this function is a thread because a hotkey runs it. explorerPath := getActiveExplorerPath() if ( explorerPath == "ERROR" or !explorerPath or !FileExist(explorerPath)) { processSetPriority 'L' critical "Off" sleep 100 return } explorerPathQuoted := '"' . explorerPath . '"' run "wt.exe -d" explorerPathQuoted /* To stop this procedure firing too often, use: A_HotkeyInterval := 1000 A_MaxHotKeysPerInterval := 1 MaxThreadsPerhotkey := 1 But also a sleep, below - for, the effect of A_MaxHotkeysPerInterval is, for some reason, to solicit a user decision. */ processSetPriority 'L' critical "Off" sleep 975 } action_hotkey_run_firefox(*) { run path.firefox } action_hotkey_send_superM(*) { send "#m" } action_hotkey_send_altF4(*) { send "!{F4}" processSetPriority 'L' sleep 200 } action_hotkey_send_search(*) { send "#s" processSetPriority 'L' sleep 100 } action_hotkey_snip(*) { run "explorer ms-screenclip:" processSetPriority 'L' sleep 300 } action_hotkey_nowt(*) { ; Blank } /* -------------- Other actions -------------- */ action_kopia_timed() { static ticksAtStart := A_TickCount if ( A_TickCount - ticksAtStart < misc.kopia.hide.delayInitalMs ) return static kopiaChecksLeft := misc.kopia.checks.total if winExist("KopiaUI ahk_class Chrome_WidgetWin_1") { setTimer , 0 ; Seems that when close the window, another opens. So . . loop 3 { winClose sleep 1100 if ( ! winExist("KopiaUI ahk_class Chrome_WidgetWin_1") ) { break } } return } ; ELSE kopiaChecksLeft-- if kopiaChecksLeft == 0 setTimer , 0 ; disable the timer } action_kopia_init() { setTimer action_kopia_timed, misc.kopia.checks.intervalMs } action_phoneLink_timed() { static ticksAtStart := A_TickCount if A_TickCount - ticksAtStart < misc.phoneLink.delayInitalMs return static phoneLinkChecksLeft := misc.phoneLink.checks.total ; It seems PhoneLink used to use a window of type ApplicationFrameWindow and time_now uses a WinUIDesktopWin32WindowClass window. if ( winExist("Phone Link ahk_class WinUIDesktopWin32WindowClass") or winExist("Phone Link ahk_class ApplicationFrameWindow") ) { ; OLD CODE, which minimised the window ; minMax := WinGetMinMax() ; if ( minMax > -1 ) { ; ; We have found a non-minimized instance of the window. ; WinMinimize ; setTimer , 0 ; disable the timer ; return ; } ; CLOSE THE WINDOW, DISABLE TIMER, & RETURN winClose setTimer , 0 return } ; ELSE phoneLinkChecksLeft-- if phoneLinkChecksLeft == 0 setTimer , 0 ; disable the timer } action_phoneLink_init() { setTimer action_phoneLink_timed, misc.phoneLink.checks.intervalMs } action_aria_timed() { local dirForTmp, filePattern ; local msg try { dirForTmp := EnvGet("TMP") filePattern := dirForTmp . "\aria-debug*.log" loop Files filePattern { fileDelete A_LoopFileFullPath } } catch Error as Failed { ; do nothing } ; We do not delete the timer; we want the checks to be regular. } action_aria_init() { setTimer action_aria_timed, misc.ariaDelete.intervalMs } action_adobeUpdate_kill() { processClose "armsvc.exe" } action_screenshots_clearOld() { intervalMilliseconds := misc.screenshots_clearOld.checkIntervalMinutes * 60000 setTimer action_screenshots_timed, intervalMilliseconds } action_screenshots_timed() { if not DirExist(misc.screenshots_clearOld.dir) return local time_file_becomesOverdue, time_file_overdue_minutes, time_file_overdue_seconds, time_now local txt, txt_file_wasMod local element, i local filesForDeletion := Array() ; Loop through the screenshots directory, making a list of files that were last modified > MaxTime ago ; but skipping any hidden files. time_now := A_Now Loop Files, misc.screenshots_clearOld.dir "\*.*" { if A_LoopFileAttrib ~= "[HRS]" continue time_file_becomesOverdue := DateAdd(A_LoopFileTimeModified, misc.screenshots_clearOld.maxFileAgeInMinutes, "Minutes") time_file_overdue_seconds := DateDiff(time_file_becomesOverdue, time_now, "Seconds") ; The result is a positive number if arg2 (time_now) is later than arg1 (time_file_becomesOverdue). if time_file_overdue_seconds > 0 { filesForDeletion.Push A_LoopFileFullPath if debug { time_file_overdue_minutes := time_file_overdue_seconds // 60 txt_file_wasMod := FormatTime(A_LoopFileTimeModified) txt := "Will delete <" . A_LoopFileName . ">: it was last modified " . txt_file_wasMod . "; the threshold is " . misc.screenshots_clearOld.maxFileAgeInMinutes . " minutes; the file is overdue by " . time_file_overdue_seconds . " seconds / " . time_file_overdue_minutes . " minutes." dbg_msg(A_ThisFunc, txt) } } } ; Go through the list we created, deleting the corresponding files. for _, element in filesForDeletion FileDelete element } /* ------- Exiting ------- */ exitProgram() { A_IconHidden := true ; remove tray icon - do this 'cos can get left behind by OS exitApp } /* ------------ Menu actions ------------ */ menu_exit(*) { exitProgram() } /* ----------- Set hotkeys ----------- A note on KEYS # = (left?) Super/Win ! = alt ^ = control + = shift $ = passed key to the OS after we've done with it. Space = space */ hotkeys_set() { if key.turnOn.printSnip hotkey "$PrintScreen", action_hotkey_snip if key.turnOff.superM hotkey "#M", action_hotkey_nowt ; Super-M shows desktop. But too easy to hit this by accident. else if key.remap.superD_to_superM hotkey "#D", action_hotkey_send_superM if key.turnOff.metro { /* Win+Tab - Shows Metro apps switcher Win+Z - Shows / hides App bar at Start Screen to show all apps. Win+ (Win-shift), - From Start Screen peeks at the Desktop. Ctrl+F1 - Minimizes / maximizes ribbon in Windows Explorer. Ctrl+Tab – Launches 'All Apps list' on the Start Screen. */ hotkey "$#C", action_hotkey_nowt ; Win-C shows the Charms bar (or, time_now, Cortana.) ; BUT the shortcut still operates! hotkey "$#F", action_hotkey_nowt ; Launches Feedback Hub hotkey "$#H", action_hotkey_nowt ; Win-H opens the 'share' thing - and stuffs the mouse hotkey "$#I", action_hotkey_nowt ; Shows Settings panel. This attempt at disabling seems not to work. hotkey "$#K", action_hotkey_nowt ; Launches Devices charm hotkey "$#L", action_hotkey_nowt ; Lock Your Pc and Return to Logon Screen ; hotkey "$#Q", action_hotkey_nowt ; Launches Search hotkey "$#W", action_hotkey_nowt ; Launches Settings search page hotkey "$#Z", action_hotkey_nowt ; Displays App Bar hotkey "$#Enter", action_hotkey_nowt ; Launches Narrator hotkey "$#^Enter", action_hotkey_nowt ; Snap Metro App to the Left hotkey "$#Enter", action_hotkey_nowt ; Win-enter = turns on bloody 'narrator' that is very hard (but use CAPS_LOCK-ESCAPE) to remove. /* Hotkeys that do not work using this method, nor with the HOTKEY-AT-END approach: - hotkey "$+LWin, action_hotkey_nowt ; Win-shift = toggle Metro. - hotkey "$+RWin, action_hotkey_nowt ; Win-shift = toggle Metro. NB: *OpenShell* can disable SHIFT-WIN! (See under ClassicShell's 'Controls' tab.) But not Shift-Win-? */ } if key.turnOff.magnify { hotkey "$#+", action_hotkey_nowt hotkey "$#-", action_hotkey_nowt } if key.turnOn.altC_winClose hotkey "$!c", action_hotkey_send_altF4 if key.turnOn.terminal hotkey "$^!t", action_hotkey_terminal if key.turnOn.ctrlSpace_search hotkey "$^Space", action_hotkey_send_search if key.turnOn.maximise { hotkey "!^Up", action_hotkey_toggleMax hotkey "!^Down", action_hotkey_toggleMin } if key.remap.superF_to_firefox hotkey "#f", action_hotkey_run_firefox ; if key.turnOff.WinSpace { ; hotkey "#Space", action_hotkey_nowt ; } ; See also the procedure globalHotKeys. } /* -------------- Initialisation -------------- */ init() { global path path.script.dir := A_ScriptDir , path.script_full := A_ScriptFullPath , path.sprite.dir := path.script.dir . "\Icons" , path.sprite.file := path.sprite.dir . "\" . path.sprite.leaf , pathScriptAnyExtension := SubStr(path.script_full, -3, 3) if (pathScriptAnyExtension != path.script.extension) { path.script_full := SubStr(path.script_full, 1, -3) . path.script.extension } menu_setup() } /* ------------------ Principal routines ------------------- */ central() { hotkeys_set if misc.ariaDelete.do action_aria_init if misc.kopia.hide.do action_kopia_init if misc.phoneLink.do action_phoneLink_init if misc.adobeUpdate_kill.do action_adobeUpdate_kill if misc.screenshots_clearOld action_screenshots_clearOld } main() { processSetPriority 'N' init() central processSetPriority 'L' } /* AUTOEXECUTE */ ; dbg_msg("Main", "A_AhkVersion", A_AhkVersion) main() ; EOF