Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- This is a productivity enhancer plus some quality-of-life features that takes care of tedious tasks for you, saving time for what matters. Click on the tray icon to view hotkey info.
- You'll find an embedded INI at the bottom of this script. However, you have to follow these two steps before you can run this script:
- Download and unzip archive in `Lib` folder: https://github.com/thqby/winrt.ahk
- Download raw file into `Lib` folder: https://github.com/Descolada/UIA-v2/blob/main/Lib/UIA.ahk
- ********** EIGHT-HOTKEY REMOTE **********
- Multi- and single-function hotkeys.
- TIP: change the `Run` setting to `Maximize` in the properties wnd of the Paint shortcut (b/c the snip feature can open Paint in a small wnd, which will be remembered by the OS).
- And go to `Settings > System > Focus assist` to turn off all `Automatic rules`, so that TrayTip notification banners can also be shown on the desktop wnd for example.
- Pause = MEDIA CONTROL
- Quick-press to play/pause, double-press to play next & triple-press to play previous.
- Win+G = GOD MODE
- Quick-press to trigger god mode (a destination runs depending on the active/existing context wnd). Double-press to use active context wnd for selectable destination folder.
- Long-press to use active context wnd for existing folder wnd (necessary for special folders). Triple-press to use active context wnd for typeable non-folder destination.
- Win+R = SMART RUN
- Quick-press to open Run dialog with preferred input & double-press or long-press to configure preferred input.
- Win+C = CALC/CTRL
- Quick-press to open Calculator & double-press or long-press to display control list of active wnd in realtime.
- Win+S = SNIP
- Start snip to clipboard (editable through Paint once you click the TrayTip that disappears after 10 min).
- PrtScn = SCREENSHOT+
- Quick-press to use native fn, double-press to save to desktop as well & long-press to merely save a clipboard image to desktop (does nothing if the clipboard has none).
- XButton* = MOUSE MENU
- Pressed down to show two-option menu & release to select.
- MButton = CONCEAL CARET
- Toggle caret in Notepad, VS Code or Visual Studio.
- ********** AUTOMATION FEATURES **********
- Open a network stream in VLC once you click `Copy Stream URL` in uTorrent.
- Assist the Chrome extension `Tabs Outliner` by making sure it has finished saving before getting closed.
- Auto-run Outlook minimized, this will allow you to see the unread emails badge for emails that you receive afterwards (so you might still want to check in the app at computer startup).
- And also make the close btn minimize Outlook instead, and make each button work wherever you click on them (Outlook normally doesn't respond to clicks at the first line of pixels).
- TIP: you can swap the badge file for another here: %LocalAppData%\Microsoft\Olk\cache
- Upgrade VLC by opening videos of specific folder(s) with aspect ratio 16:9, changing default settings just once; to enable and fix features, and to prevent repetition and annoyances.
- Showing a close btn in fullscreen when your cursor reaches the top-right corner and making the fullscreen controller immovable, centered at the bottom.
- TIP: you can restore the old settings by replacing this file: %AppData%\vlc\vlcrc, with the backup: %Temp%\vlcrc
- Activate the `Unsaved Changes` dialog when showed and parent wnd first (most importantly the dialog might otherwise not appear when you click the close btn via the preview wnd).
- Unhide taskbar in specific fullscreen window(s) and allow the cursor to move taskbar icons after the LButton has been pressed down for atleast 500 ms (to avoid moving them by mistake).
- Auto-close the annoying WinRAR and Software Ideas Modeler notifications.
- Unfocus the minimized uTorrent window at startup to prevent key presses from affecting it by accident.
- TIP: move script to: %UserProfile%\Downloads\AutoHotkey, after that go to `Task Scheduler > Action > Import Task...` and then use the XML file (the task makes this feature faster).
- Scroll namespace to top when nearby on VS edit control show event.
- ********** WINDOWS' BUILT-IN HOTKEYS **********
- Some native hotkeys that you should know about.
- Win+D = Show desktop.
- Win+; = Emoji menu (e.g. you could insert a checkmark into a txt file).
- MButton = Cursor on URL opens website in new tab, cursor on app in taskbar opens new instance & cursor on scrollable area of website activates auto-scroll.
- Alt+F4 = When on desktop it'll show the shutdown menu.
- Ctrl+F = Open find wnd (any text that you select beforehand gets inserted into the Find wnd automatically).
- F3 = Quickly find and select text that was previously entered in the find wnd but without having to open the Find wnd again.
- Win+Alt+B = Toggle HDR (this feature has been made reliable with a custom hotkey).
- */
- #Requires AutoHotkey 2.1-alpha.9 ; For _menu.Show(,, 0), struct, fn definition expression and `property ??`
- #SingleInstance Off
- A_DetectHiddenWindows := true
- ; To make hotkeys work when an admin window is active
- if (!InStr(A_AhkPath, "_UIA.exe"))
- {
- if (!WinExist(A_ScriptFullPath " ahk_exe AutoHotkey64_UIA.exe"))
- Run("*UIAccess " A_ScriptFullPath)
- ExitApp()
- }
- else if (WinGetList(A_ScriptFullPath " ahk_exe AutoHotkey64_UIA.exe").Length > 1)
- ExitApp()
- A_DetectHiddenWindows := false
- #Include <winrt.ahk-main\windows>
- #Include <UIA>
- Initialize()
- ; PowerShell HDR toggle pipe writer (replaces the Windows' built-in HDR toggle hotkey of Game Bar on demand, to make it reliable)
- #!b::
- {
- if (!RegRead("HKEY_CURRENT_USER\System\GameConfigStore", "GameDVR_Enabled")) ; Detects disabled Game Bar because it shouldn't toggle it with both Game Bar and WindowsDisplayManager
- Run("PowerShell.exe -Command `"" "
- (
- $pipeClient = New-Object System.IO.Pipes.NamedPipeClientStream('.', '\\.\pipe\HdrTogglePipe', [System.IO.Pipes.PipeDirection]::Out)
- $pipeWriter = New-Object System.IO.StreamWriter($pipeClient)
- $pipeClient.Connect()
- $pipeWriter.WriteLine($true)
- $pipeWriter.Flush()
- )" "`"",, "Hide")
- KeyWait("LWin") ; Prevents the Win+Alt+B hotkey from triggering again while it's still pressed down
- }
- *Pause::HandleHotkeyActivation(() => Send("{Media_Play_Pause}"), () => Send("{Media_Next}"), () => Send("{Media_Prev}"))
- ; This hotkey variant uses I1 so that it won't get triggered by I1 WinExist hotkey variants (AHK does not let WinActive hotkey variants get priority by default, so they take care of that)
- #InputLevel 1
- #g::HandleGodModeHotkeyActivation(() => ShellNavigate("shell:::{ED7BA470-8E54-465E-825C-99712043E01C}"))
- #InputLevel 0 ; Resets back to default
- #r::
- {
- pressStartTime := A_TickCount
- loop
- {
- Sleep(10)
- ; Win+R Quick-Press & Double-Press. Opens the run dialog or the configuration dialog for preferred input
- if (!GetKeyState("#", "P") && !GetKeyState("r", "P"))
- {
- HandleHotkeyActivation(StartSmartRun, ConfigurePreferredSmartRunInput)
- return
- }
- ; Win+R Long-Press. Opens the configuration dialog for preferred input
- if (A_TickCount - pressStartTime > 750)
- {
- ConfigurePreferredSmartRunInput()
- KeyWait("LWin") ; Prevents the Win+R hotkey from triggering again while it's still pressed down
- return
- }
- }
- StartSmartRun()
- {
- Run("shell:::{2559a1f3-21d7-11d4-bdaf-00c04f60b9f0}")
- WinWaitActive("Run ahk_class #32770")
- if (preferredSmartRunInputSection := IniRead(iniPath, "PreferredSmartRunInput"))
- ControlSetText(preferredSmartRunInputSection, "Edit1"), Send("+{End}")
- }
- ConfigurePreferredSmartRunInput()
- {
- preferredInput := InputBox("Enter the preferred input to show by default in the Run dialog. "
- "Use %LocalAppData%โit's the one most people tend to use.`n`n"
- "Pro Tip: QuickAssist for remote assistance (built into Windows).", "Preferred Input - Smart Run", "w397 h174", "%LocalAppData%")
- if (preferredInput.Result = "OK")
- {
- IniDelete(iniPath, "PreferredSmartRunInput")
- IniWriteExistingContextWindows(preferredInput.Value, "PreferredSmartRunInput") ; Writes it below the godmode sections
- }
- }
- }
- #c::
- {
- pressStartTime := A_TickCount
- loop
- {
- Sleep(10)
- ; Win+C Quick-Press & Double-Press. Opens calculator or toggles the realtime control list
- if (!GetKeyState("#", "P") && !GetKeyState("c", "P"))
- {
- HandleHotkeyActivation(() => Run("Calc"), ToggleRealtimeControlList)
- return
- }
- ; Win+C Long-Press. This toggles the realtime control list
- if (A_TickCount - pressStartTime > 750)
- {
- ToggleRealtimeControlList()
- KeyWait("LWin") ; Prevents the Win+C hotkey from triggering again while it's still pressed down
- return
- }
- }
- ToggleRealtimeControlList()
- {
- static shouldShowRealtimeControlList := false
- SetTimer(WatchActiveWindow, (shouldShowRealtimeControlList := !shouldShowRealtimeControlList) ? 200 : 0)
- if (!shouldShowRealtimeControlList)
- ToolTip()
- WatchActiveWindow()
- {
- if (isToolTipPrtScnShown)
- return
- try
- {
- focusedHwnd := ControlGetFocus("A")
- focusedClassNN := ControlGetClassNN(focusedHwnd)
- controlList := "๐๐ผ๐ป๐๐ฟ๐ผ๐น ๐๐ถ๐๐ ๐ข๐ณ ๐๐ฐ๐๐ถ๐๐ฒ ๐ช๐ถ๐ป๐ฑ๐ผ๐: " WinGetProcessName("A")
- . "`n๐๐ผ๐ฐ๐๐๐ฒ๐ฑ ๐๐ผ๐ป๐๐ฟ๐ผ๐น: {๐ต๐ช๐ป๐ฑ: " focusedHwnd ", ๐๐น๐ฎ๐๐๐ก๐ก: `"" focusedClassNN "`"}"
- . "`nโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ`n"
- for (classNN in WinGetControls("A"))
- controlList .= classNN "`n"
- if (controlList = "")
- ToolTip("The active window has no controls.", toolTipAxes*)
- else
- ToolTip(ControlList, toolTipAxes*)
- }
- catch (TargetError)
- ToolTip("No visible window is active.", toolTipAxes*)
- }
- }
- }
- #s::
- {
- static winEventHook := 0, clipImage
- OnClipboardChange(HandleClipChanged)
- Run("ms-screenclip:")
- WinWait("ahk_exe ScreenClippingHost.exe")
- WinWaitClose("ahk_exe ScreenClippingHost.exe")
- OnClipboardChange(HandleClipChanged, 0)
- if (!winEventHook)
- winEventHook := HookEvent(EVENT_OBJECT_NAMECHANGE, HandleNameChangedSnipWinEvent)
- ; This (re)sets the timer to 10 minutes
- SetTimer(DismissSnipNotification, -600000)
- HandleClipChanged(*) => clipImage := ClipboardAll()
- HandleNameChangedSnipWinEvent(hWinEventHook, event, hWnd, *)
- {
- try
- if (WinGetTitle(hWnd) = "Snip & Sketch" && WinGetClass(hWnd) = "ApplicationFrameWindow")
- {
- DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
- winEventHook := 0
- WinSetTransparent(0, hWnd)
- clipPrevious := ClipboardAll()
- A_Clipboard := clipImage
- WinWait(hWnd)
- if (!DllCall("IsClipboardFormatAvailable", "UInt", CF_BITMAP := 2)) ; Detects clipboard without image
- {
- Send("^c") ; Copies the image from Snip & Sketch in case the image didn't get saved in the clipboard
- fallbackCopyActionStartTime := A_TickCount
- ; Waits until the clipboard has the image or times out after 2 seconds
- while (!DllCall("IsClipboardFormatAvailable", "UInt", CF_BITMAP := 2))
- {
- if (A_TickCount - fallbackCopyActionStartTime > 2000)
- {
- WinSetTransparent("Off")
- TrayTip("This fallback timed out. Resolve!", "UNABLE TO COPY SNIP", 0x12)
- SetTimer(HideTrayTip, -4000)
- return
- }
- Sleep(10)
- }
- }
- WinClose()
- ; Save clipboard image to temp folder to see its width and height (overwrites any that might've been saved in the past)
- RunWait("PowerShell.exe -Command `"$img = get-clipboard -format image; $img.save('" A_Temp "\latestSnip.jpg')`"",, "Hide")
- imageSize := GetImageSize(A_Temp "\latestSnip.jpg")
- ; The extra space is for the paint toolset ofcourse
- rawPaintWinWidth := imageSize.Width + 27
- rawPaintWinHeight := imageSize.Height + 192
- ; Initializing the paint wnd size (without the minimum, it will hide the paint toolset and without the maximum, it will go beyond the screen boundaries)
- paintWinWidth := (rawPaintWinWidth >= 379 ? (rawPaintWinWidth <= A_ScreenWidth ? rawPaintWinWidth : A_ScreenWidth) : 379)
- paintWinHeight := (rawPaintWinHeight >= 251 ? (rawPaintWinHeight <= A_ScreenHeight ? rawPaintWinHeight : A_ScreenHeight) : 251)
- Run("mspaint.exe",, "Min", &paintPid)
- WinWait("ahk_pid " paintPid)
- WinSetTransparent(0)
- Send("{Ctrl down}")
- Sleep(250)
- if (paintWinWidth = A_ScreenWidth && paintWinHeight = A_ScreenHeight)
- {
- WinMaximize() ; Some images are so big that Paint needs to be shown in a maximized state
- PasteImageAndRemoveRemainingWhiteSpace()
- }
- else
- {
- WinActivate()
- PasteImageAndRemoveRemainingWhiteSpace()
- WinRestore() ; Unmaximize if it's maximized
- WinMove((A_ScreenWidth / 2) - (paintWinWidth / 2), (A_ScreenHeight / 2) - (paintWinHeight / 2), paintWinWidth, paintWinHeight) ; Moves to center w/ new size
- }
- WinSetTransparent("Off")
- Sleep(250)
- Send("{Shift up}{Ctrl up}")
- A_Clipboard := clipPrevious
- }
- }
- ; Make sure that Ctrl is down before using this fn, and release Shift and Ctrl after (using 250 ms delays might make it reliable)
- PasteImageAndRemoveRemainingWhiteSpace()
- {
- ControlSend("v") ; Pastes the image from clipboard
- Sleep(250)
- Send("{Shift down}")
- Sleep(250)
- WinActivate()
- ControlSend("x") ; Removes any white space that might remain (crops the image)
- }
- GetImageSize(imagePath)
- {
- static shellObj := ComObject("Shell.Application")
- SplitPath(imagePath, &fileName, &fileDir)
- folderObj := shellObj.Namespace(fileDir)
- if (!folderItemObj := folderObj.ParseName(fileName))
- throw ValueError("The image path does not contain a (valid) file", -1, imagePath)
- sizeArray := StrSplit(folderItemObj.ExtendedProperty("Dimensions"), " x ")
- ; Ad hoc object which allows you to see its properties with IntelliSense, usable w/ dot notation (image size w/o invisible characters)
- return {Width: LTrim(sizeArray[1], Chr(8234)), Height: RTrim(sizeArray[2], Chr(8236))}
- }
- ; This gets rid of the snip notification and its `winEventHook`, if it still exists
- DismissSnipNotification(*)
- {
- if (winEventHook)
- {
- Windows.UI.Notifications.ToastNotificationManager.History.Clear("Microsoft.ScreenSketch_8wekyb3d8bbwe!App")
- DllCall("UnhookWinEvent", "Ptr", winEventHook)
- winEventHook := 0
- }
- }
- }
- *PrintScreen::
- {
- static latestScreenshotTime := 0
- pressStartTime := A_TickCount
- loop
- {
- Sleep(10)
- if (!GetKeyState("PrintScreen", "P"))
- {
- ; PrtScn Quick-Press. This takes a new screenshot
- if (A_TickCount - latestScreenshotTime > 500)
- {
- Send("{Blind}{PrintScreen}") ; Blind mode allows the native Win+PrtScn hotkey to save it in the `Screenshots` folder
- latestScreenshotTime := A_TickCount
- return
- }
- ; PrtScn Double-Press. This saves the screenshot of the first press to the desktop
- break
- }
- ; PrtScn Long-Press. This saves any image that is currently in the clipboard to the desktop
- if (A_TickCount - pressStartTime > 750)
- {
- if (DllCall("IsClipboardFormatAvailable", "UInt", CF_BITMAP := 2)) ; Detects a clipboard image
- break
- ToolTip("No clipboard image detected.", toolTipAxes*)
- global isToolTipPrtScnShown := true
- KeyWait("PrintScreen") ; Prevents the PrtScn hotkey from triggering again while it's still pressed down and for tooltip dismissal
- Tooltip()
- global isToolTipPrtScnShown := false
- return
- }
- }
- RunWait("PowerShell.exe -Command `"$img = get-clipboard -format image; $img.save('" A_Desktop "\" A_Now ".jpg')`"",, "Hide")
- TrayTip("CLIPBOARD IMAGE SAVED TO DESKTOP",, 0x10)
- SetTimer(HideTrayTip, -4000)
- KeyWait("PrintScreen") ; Prevents the PrtScn hotkey from triggering again while it's still pressed down
- }
- XButton1::
- XButton2::
- {
- mouseEventHook.Start()
- SystemCursor("Hide")
- _menu := Menu()
- _menu.Add("Open Google", OpenGoogle)
- _menu.Add() ; seperator line
- _menu.Add("Open Maps", OpenMaps)
- _menu.Show(,, 0)
- WinWait("ahk_class #32768 ahk_exe " A_AhkPath,, 5)
- ControlSend("{Down}") ; Highlights the first menu item
- MouseGetPos(, &startCursorY)
- MFS_HILITE := 0x00000080
- latestEventYNonZeroIncrease := 0 ; Upcoming changes will be non-zero
- latestEventYNonZeroChangeAmount := 0 ; Change(s) to the first unique value are unreliable hence skipping that value
- loop
- {
- Sleep(50)
- if (!mouseEventHook.ProcHandle)
- {
- try ControlSend("{Enter}")
- return
- }
- try
- {
- latestEventYIncreaseToProcess := startCursorY - latestMouseEvent.Y
- if (latestEventYIncreaseToProcess = 0)
- continue
- if (latestEventYIncreaseToProcess != latestEventYNonZeroIncrease)
- {
- latestEventYNonZeroIncrease := latestEventYIncreaseToProcess
- if (latestEventYNonZeroChangeAmount++ = 0)
- continue
- menuOption1 := GetMenuItemInfo(0)
- menuOption2 := GetMenuItemInfo(2) ; Seperator line is index 1
- if (menuOption1.FState & MFS_HILITE)
- {
- if (latestEventYNonZeroIncrease < 0)
- ControlSend("{Down}")
- }
- else if (menuOption2.FState & MFS_HILITE)
- {
- if (latestEventYNonZeroIncrease > 0)
- ControlSend("{Up}")
- }
- }
- }
- }
- GetMenuItemInfo(index)
- {
- menuItem := MenuItemInfo()
- menuItem.FMask := 0x00000001 ; MIIM_STATE
- DllCall("GetMenuItemInfo", "Ptr", _menu.Handle, "UInt", index, "Int", true, "Ptr", menuItem)
- return menuItem
- }
- }
- XButton1 up::
- XButton2 up::mouseEventHook.Stop()
- #HotIf (WinActive("ahk_exe notepad.exe"))
- MButton::WinActivate("ahk_class Progman")
- #HotIf (WinActive("Visual Studio Code - Welcome ahk_exe chrome.exe"))
- MButton::Send("{Alt}")
- #HotIf (WinActive("Microsoft Visual Studio ahk_exe devenv.exe"))
- MButton::
- {
- if ((focusedElement.Selection ?? false) && UIA.CompareElements(focusedElement.Latest, UIA.GetFocusedElement()))
- {
- ; Moves caret back to where it was
- try focusedElement.Selection.Select()
- focusedElement.Latest := unset
- focusedElement.Selection := unset
- }
- else
- {
- ; Moves caret to the start of the Edit control
- focusedElement.Latest := UIA.GetFocusedElement()
- focusedElement.Selection := focusedElement.Latest.SelectionRange
- documentRange := focusedElement.Latest.DocumentRange
- documentRange.MoveEndpointByUnit(UIA.TextPatternRangeEndpoint.End, UIA.TextUnit.Document, -1)
- documentRange.Select()
- }
- }
- ; Necessary to make A_ThisHotkey become one of these when pressed (HandleVisualStudioTextSelectionChangedEvent requires this)
- ~LButton::
- ~RButton::return
- #HotIf (WinActive("ahk_exe uTorrent.exe"))
- ~RButton::
- {
- static status := 0
- if (!status)
- OnClipboardChange(HandleClipChanged, status := 1)
- HandleClipChanged(*)
- {
- if (WinActive("ahk_exe uTorrent.exe"))
- {
- HookEvent(EVENT_OBJECT_CREATE, HandleCreatedVlcEvent)
- Send("+{F10}p{Enter}{Tab}"), Run(A_ProgramFiles "\VideoLAN\VLC\vlc.exe --fullscreen --aspect-ratio=16:9 " A_Clipboard)
- }
- OnClipboardChange(HandleClipChanged, status := 0)
- HandleCreatedVlcEvent(hWinEventHook, event, hWnd, *)
- {
- static isBeingShownAfterTorrentStartsUnforced := false, WS_EX_LAYERED := 0x00080000
- try
- if (WinGetTitle(hWnd) = "VLC" && !isBeingShownAfterTorrentStartsUnforced)
- {
- isBeingShownAfterTorrentStartsUnforced := true
- try WinSetTransparent(0, hWnd)
- try WinSetEnabled(false, "ahk_exe uTorrent.exe")
- HotIf(MouseIsOverUTorrent)
- Hotkey("LButton", ShowNetworkStreamMenu, "On")
- Hotkey("RButton", ShowNetworkStreamMenu, "On")
- DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
- Sleep(-1) ; Discards queued events that might remain
- WinExist(hWnd)
- ; Waiting until VLC is full screen
- try
- loop
- if (!isBeingShownAfterTorrentStartsUnforced)
- return
- else if (WinGetExStyle() = WS_EX_LAYERED)
- break
- Hotkey("LButton", "Off")
- Hotkey("RButton", "Off")
- try WinSetEnabled(true, "ahk_exe uTorrent.exe")
- try WinActivate("ahk_exe uTorrent.exe")
- try Send((ListViewGetContent("Count Focused", "SysListView322", WinExist("ahk_exe uTorrent.exe")) = 1 ? "{Down}{Up}" : "{Up}{Down}") "+{F10}s")
- try WinActivate(hWnd)
- try WinSetTransparent("Off", hWnd)
- isBeingShownAfterTorrentStartsUnforced := false
- }
- MouseIsOverUTorrent(*) => MouseIsOver("ahk_exe uTorrent.exe")
- ; This makes it possible to abort the network stream when the download speed is too low
- ShowNetworkStreamMenu(*)
- {
- _menu := Menu()
- _menu.Add("Abort Network Stream", AbortNetworkStream)
- _menu.Show()
- AbortNetworkStream(*)
- {
- HotIf(MouseIsOverUTorrent)
- Hotkey("LButton", "Off")
- Hotkey("RButton", "Off")
- WinClose("ahk_exe vlc.exe")
- WinSetEnabled(true, "ahk_exe uTorrent.exe")
- WinActivate("ahk_exe uTorrent.exe")
- isBeingShownAfterTorrentStartsUnforced := false
- }
- }
- }
- }
- }
- #HotIf (A_TitleMatchMode := 3, MouseIsOver("Tabs Outliner ahk_exe chrome.exe")) ; TitleMatchMode 3 = exact title match (changes only the mode of the thread made for this specific #HotIf)
- LButton::
- {
- static latestClickTime := 0
- WinGetClientPos(&tabsOutlinerX, &tabsOutlinerY, &tabsOutlinerWidth,, "Tabs Outliner ahk_exe chrome.exe")
- MouseGetPos(&cursorX, &cursorY)
- if (cursorX > tabsOutlinerX + tabsOutlinerWidth - 47 && cursorY < tabsOutlinerY + 31 && A_TickCount - latestClickTime < 3200) ; Detects close btn click w/ save likely in progress
- Sleep(3200 - (A_TickCount - latestClickTime)), WinClose("Tabs Outliner ahk_exe chrome.exe") ; Delays closing the wnd long enough for any save to finish
- else
- Send("{LButton down}"), KeyWait("LButton"), Send("{LButton up}"), latestClickTime := A_TickCount
- }
- #HotIf (WinActive("E-mail ahk_class Olk Host"))
- LButton::
- {
- WinGetClientPos(&outlookX,, &outlookWidth)
- MouseGetPos(&cursorX)
- if (MouseIsOverOutlookButton()) ; Detects minimize-, restore- or close btn click
- {
- ; Fixes an unresponsive click area (at the very top of the buttons) and prevents accidentally closing when you meant to minimize it
- if (cursorX < outlookX + outlookWidth - 96 || cursorX > outlookX + outlookWidth - 49) ; Detects minimize- or close btn click
- WinMinimize()
- else if (WinGetMinMax() = 1) ; Detects maximized wnd with restore btn click
- WinRestore()
- else ; Detects restored down wnd with maximize btn click
- WinMaximize()
- }
- else
- Send("{LButton down}"), KeyWait("LButton"), Send("{LButton up}")
- MouseIsOverOutlookButton()
- {
- try return (MouseGetPos(,, &winId, &control), WinExist("E-mail ahk_class Olk Host ahk_id " winId) && (control = "WebViewCaptionButton1" || control = "WebViewCaptionButtonDepr1"))
- return false
- }
- }
- #HotIf (WinActive("ahk_exe vlc.exe"))
- LButton::
- {
- static fullscreenState := 2
- DllCall("Shell32\SHQueryUserNotificationState", "UInt*", &monitorState := 0)
- if (monitorState != fullscreenState || monitorState = fullscreenState && WinExist("ahk_class Qt5QWindowToolTipSaveBits"))
- Send("{LButton down}"), KeyWait("LButton"), Send("{LButton up}")
- else
- Send("{LButton}")
- }
- #HotIf (MouseIsOver("ahk_class Shell_TrayWnd"))
- *LButton::
- {
- BlockInput("MouseMove")
- if (KeyWait("LButton", "T0.5"))
- Send("{LButton}"), BlockInput("MouseMoveOff")
- else
- Send("{LButton down}"), BlockInput("MouseMoveOff"), KeyWait("LButton"), Send("{LButton up}")
- }
- ;********** LIBRARY **********
- Initialize()
- {
- TraySetIcon("netshell.dll", 151, true)
- A_IconTip := "Time Saver"
- A_CoordModeToolTip := "Screen" ; For the tooltip shown when the tray icon is clicked and also for the realtime controls tooltip
- A_CoordModeMouse := "Screen" ; For the XButton hotkeys, and the LButton hotkey of the tabs outliner assist feature
- A_WinDelay := -1 ; For the snip feature, HandleNameChangedThunderbirdEvent, HandleNameChangedTabsOutlinerEvent and the two different HandleCreatedVlcEvent functions
- A_KeyDelay := -1 ; For the XButton hotkeys (ControlSend) and for Send b/c it reverts to the Event SendMode when another AHK script installs a native low-level keyboard/mouse hook
- A_KeyDuration := 1 ; For the XButton hotkeys
- EVENT_SYSTEM_FOREGROUND := 0x0003
- global EVENT_OBJECT_CREATE := 0x8000
- global EVENT_OBJECT_SHOW := 0x8002
- EVENT_OBJECT_REORDER := 0x8004
- global EVENT_OBJECT_NAMECHANGE := 0x800C
- global toolTipAxes := [A_ScreenWidth * 0.75, A_ScreenHeight]
- global isToolTipPrtScnShown := false
- global dialog := {ShouldProcessInput: true} ; Ad hoc object, usable w/ dot notation (no need for class)
- global latestMouseEvent := {Y: unset} ; Ad hoc object, usable w/ dot notation (no need for class)
- global mouseEventHook := PointerDeviceHook("Move|LButton Down", HandleMouseEvent(eventInfo)
- {
- latestMouseEvent.Y := eventInfo.Pt.Y ; This mouse movement will be used to highlight a menu item
- return true ; Blocks both interfering mouse actions
- })
- global focusedElement := {Latest: unset, Selection: unset} ; Ad hoc object, usable w/ dot notation (no need for class)
- global iniPath := A_ScriptFullPath
- global godmodeActiveContextWindow := {HasTriggered: false}
- ; Makes tray icon merely show hotkey info on click
- A_TrayMenu.Delete()
- OnMessage(0x404, HandleTrayIconClick) ; 0x404 = WM_USER msg number (which can be found w/ Microsoft Spy++)
- ; Win+G opens Game Bar by default in Windows, so this will disable it (press Win and type `Game Bar settings` to enable it again)
- if (RegRead("HKEY_CURRENT_USER\System\GameConfigStore", "GameDVR_Enabled"))
- {
- RegWrite(0, "REG_DWORD", "HKEY_CURRENT_USER\System\GameConfigStore", "GameDVR_Enabled")
- RegWrite(0, "REG_DWORD", "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\GameDVR", "AppCaptureEnabled")
- }
- ; PowerShell load command for HDR toggle pipe reader and status toast
- hdrTogglePowershellLoadCommand := "
- (
- try { $pipeServer = New-Object System.IO.Pipes.NamedPipeServerStream('\\.\pipe\HdrTogglePipe') }
- catch { exit } # HDR toggle Powershell process exists already
- $pipeReader = New-Object System.IO.StreamReader($pipeServer)
- Import-Module WindowsDisplayManager
- $primaryDisplay = GetPrimaryDisplay
- $toastHdrStatusScriptBlock = [System.Management.Automation.ScriptBlock]::Create(
- {
- param($hdrStatus)
- $toastText01 = [Windows.UI.Notifications.ToastTemplateType, Windows.UI.Notifications, ContentType = WindowsRuntime]::ToastText01
- $templateHdr = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]::GetTemplateContent($toastText01)
- $templateHdr.SelectSingleNode('//text[@id=1]').InnerText = $hdrStatus
- $toastNotifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel')
- $toastNotifier.Show(($toastHdrStatus = [Windows.UI.Notifications.ToastNotification]::new($templateHdr)))
- Start-Sleep -Seconds 4
- $toastNotifier.Hide($toastHdrStatus)
- })
- while ($true)
- {
- $pipeServer.WaitForConnection()
- [void]$pipeReader.ReadLine()
- if ($primaryDisplay.HdrInfo.HdrEnabled)
- {
- $primaryDisplay.DisableHdr()
- Start-Job -ScriptBlock $toastHdrStatusScriptBlock -ArgumentList 'HDR DISABLED'
- }
- else
- {
- $primaryDisplay.EnableHdr()
- Start-Job -ScriptBlock $toastHdrStatusScriptBlock -ArgumentList 'HDR ENABLED'
- }
- $pipeServer.Disconnect()
- }
- )"
- ; This silently installs the WindowsDisplayManager module one-time and loads the reliable PowerShell HDR toggle, for use with an on-demand hotkey (because Game Bar is unreliable)
- try RegRead("HKEY_CURRENT_USER\SOFTWARE\Parzival\TimeSaver", "OneTimeWindowsDisplayManagerInstalled") ; Allows the catch scope to execute if the value name doesn't exist
- catch
- {
- RegWrite(1, "REG_DWORD", "HKEY_CURRENT_USER\SOFTWARE\Parzival\TimeSaver", "OneTimeWindowsDisplayManagerInstalled")
- Run("PowerShell.exe -NoExit -ExecutionPolicy Bypass -Command `"" "
- (
- Install-PackageProvider -Name NuGet -Scope CurrentUser -Force # Necessary for the line below
- Install-Module -Name WindowsDisplayManager -Scope CurrentUser -Force -AllowClobber`n
- )" hdrTogglePowershellLoadCommand "`"",, "Hide")
- }
- else
- Run("PowerShell.exe -NoExit -ExecutionPolicy Bypass -Command `"" hdrTogglePowershellLoadCommand "`"",, "Hide")
- ; Create [ActiveContextWindows] hotkeys with the INI. This gets done first so that these WinActive hotkey variants trigger instead of any WinExist ones that are created below and any
- ; that are created later when the user has added new one(s). If there are any WinExist hotkey variants that'd have triggered. Therefore, it won't matter whether I0 or I1 is used here,
- ; WinExist hotkey variants won't get to trigger these and obviously can't skip them either then
- if (section := IniRead(iniPath, "ActiveContextWindows"))
- {
- linesSplit := StrSplit(section, "`n")
- for (iteratedLine in linesSplit)
- ((iteratedCommandData) => (
- HotIf((*) => WinActive(iteratedCommandData[1])),
- Hotkey("#g", (*) => HandleGodModeHotkeyActivation(() => ShellNavigate(iteratedCommandData[2])))
- ))(StrSplit(iteratedLine, "="))
- }
- ; Create [ExistingContextWindowPriority*] hotkeys with the INI. These use I1 to trigger any I0 WinActive hotkey variant instead that is created later when the user has added new one(s).
- ; If there are any of those WinActive hotkey variant(s) that'd trigger, otherwise it'd just execute its own God Mode action
- try
- loop
- ((iteratedCommandData) => (
- HotIf((*) => WinExist(iteratedCommandData[1])),
- Hotkey("#g", (*) => (
- Send("#g"), Sleep(100), (godmodeActiveContextWindow.HasTriggered ? Exit() : HandleGodModeHotkeyActivation(() => ShellNavigate(iteratedCommandData[2])))
- ), "I1")
- ))(StrSplit(IniRead(iniPath, "ExistingContextWindowPriority" A_Index), "="))
- if (FileExist(A_ProgramFiles "\VideoLAN\VLC\vlc.exe"))
- {
- ; Resets fullscreen controller to the bottom center to avoid becoming stuck at the wrong position, b/c it's made immovable by a hotkey variant
- IniWrite("", A_AppData "\vlc\vlc-qt-interface.ini", "FullScreen", "pos")
- try RegRead("HKEY_CURRENT_USER\SOFTWARE\Parzival\TimeSaver", "OneTimeVlcSettingChangesExecuted") ; Allows the catch scope to execute if the value name doesn't exist
- catch
- {
- RegWrite(1, "REG_DWORD", "HKEY_CURRENT_USER\SOFTWARE\Parzival\TimeSaver", "OneTimeVlcSettingChangesExecuted")
- FileCopy(A_AppData "\vlc\vlcrc", A_Temp, true) ; Backing up old settings (the other INI may contain the useful extended settings btn on the fs controller, no backup necessary)
- changedVlcSettingsTrayTip := ""
- try IniRead(A_AppData "\vlc\vlc-qt-interface.ini", "MainWindow", "FSCtoolbar") ; Allows the catch scope to execute if the key doesn't exist
- catch
- {
- IniWrite("`"0-2;64;3;1;4;64;37;64;38;64;8;65;9-4;35-4;34;`"", A_AppData "\vlc\vlc-qt-interface.ini", "MainWindow", "FSCtoolbar")
- changedVlcSettingsTrayTip := "FscExtendedSettingsButton"
- }
- for (iteratedObj in
- [
- {Section: "core", Key: "fullscreen" , Value: 1 , OccurredChange: "Fullscreen"},
- {Section: "core", Key: "custom-aspect-ratios", Value: "17:10" , OccurredChange: "CustomAspectRatios"},
- {Section: "core", Key: "stereo-mode" , Value: 1 , OccurredChange: "Stereo"},
- {Section: "core", Key: "volume-save" , Value: 0 , OccurredChange: "VolumeSaveOff"},
- {Section: "core", Key: "osd" , Value: 0 , OccurredChange: "OsdOff"},
- {Section: "core", Key: "spu" , Value: 0 , OccurredChange: "SubtitlesOff"},
- {Section: "core", Key: "vout" , Value: "direct3d9", OccurredChange: "HdrSubtitlesFix"},
- {Section: "qt" , Key: "qt-updates-notif" , Value: 0 , OccurredChange: "UpdatesNotifierOff"},
- {Section: "qt" , Key: "qt-system-tray" , Value: 0 , OccurredChange: "SystemTrayIconOff"}
- ])
- try
- {
- IniRead(A_AppData "\vlc\vlcrc", iteratedObj.Section, "#" iteratedObj.Key) ; Allows the rest to execute if the commented-out default key exists
- IniWrite("`n" iteratedObj.Key "=" iteratedObj.Value, A_AppData "\vlc\vlcrc", iteratedObj.Section, "#" iteratedObj.Key)
- IniDelete(A_AppData "\vlc\vlcrc", iteratedObj.Section, "#" iteratedObj.Key)
- changedVlcSettingsTrayTip .= ", " iteratedObj.OccurredChange
- }
- ; Mentioning one-time setting changes in a persistent VLC notification
- tnm := Windows.UI.Notifications.ToastNotificationManager
- toastXml := tnm.GetTemplateContent("ToastText02")
- toastXml.GetElementsByTagName("text").GetAt(0).InnerText := "New default settings make features usable, and prevent repetition and annoyances"
- toastXml.GetElementsByTagName("text").GetAt(1).InnerText := changedVlcSettingsTrayTip
- tnm.CreateToastNotifier("{6D809377-6AF0-444B-8957-A3773F02200E}\VideoLAN\VLC\vlc.exe").Show(Windows.UI.Notifications.ToastNotification(toastXml))
- }
- }
- ; It'll simulate native non-fullscreen taskbar functionality in the specific fullscreen windows that you set here. Unforcefully allowing the taskbar to be shown when the cursor reaches
- ; the deactivated taskbar line (it won't activate the taskbar, so the taskbar retains its slide animation). Useful for non-video fullscreen windows
- if (fullscreenWindowsUnhideTaskbarSection := IniRead(iniPath, "FullscreenWindowsUnhideTaskbar"))
- {
- linesSplit := StrSplit(StrSplit(fullscreenWindowsUnhideTaskbarSection, "`n*/")[1], "`n")
- for (iteratedLine in linesSplit)
- GroupAdd("FullscreenWindows", iteratedLine)
- }
- tbl := CreateTaskbarList()
- outlookWinEventHook := HookEvent(EVENT_OBJECT_CREATE, HandleCreatedOutlookEvent)
- HookEvent(EVENT_OBJECT_CREATE, HandleCreatedVlcEvent)
- HookEvent(EVENT_OBJECT_REORDER, HandleReorderedVlcEvent)
- HookEvent(EVENT_SYSTEM_FOREGROUND, HandleActivatedWindowVlcEvent)
- HookEvent(EVENT_SYSTEM_FOREGROUND, HandleChangedFullscreenWinEvent)
- HookEvent(EVENT_OBJECT_SHOW, HandleChangedFullscreenWinEvent)
- HookEvent(EVENT_OBJECT_SHOW, HandleShowedUnsavedChangesDialogEvent)
- HookEvent(EVENT_OBJECT_SHOW, HandleShowedNotificationEvent)
- fullscreenVlcCloseButtonMouseEventHook := PointerDeviceHook("Move|LButton Down", HandleFullscreenVlcCloseButtonMouseEvent, true)
- for (iteratedApp in ComObject("Shell.Application").NameSpace("shell:Appsfolder").Items)
- if (iteratedApp.Name = "ยตTorrent")
- SetTimer(UnfocusUTorrent, -1)
- if (ProcessExist("olk.exe")) ; Prevents opening multiple Outlook instances when Time Saver reloads (also no need to auto-run it minimized if the user had already opened it)
- DllCall("UnhookWinEvent", "Ptr", outlookWinEventHook)
- else
- {
- A_DetectHiddenWindows := true
- ; This will wait on `Minimized Tabs Outliner.ahk` to have detected Tabs Outliner, if that script is being used as well (allows that script to keep a lower timeout and finish faster)
- if (WinExist("Minimized Tabs Outliner.ahk"))
- {
- GroupAdd("TabsOutliner", "_crx_eggkanocgddhmamlbiijnphhppkpkmkl")
- GroupAdd("TabsOutliner", "Tabs Outliner ahk_exe chrome.exe")
- WinWait("ahk_group TabsOutliner",, 30)
- }
- A_DetectHiddenWindows := false
- Run("olk.exe",, "Max") ; Runs Outlook
- }
- ManageVisualStudioEventHandlers() ; Has a loop, so keep this at the bottom
- HandleTrayIconClick(wParam, lParam, *)
- {
- static WM_LBUTTONUP := 0x0202, WM_RBUTTONUP := 0x0205
- if (lParam = WM_LBUTTONUP || lParam = WM_RBUTTONUP)
- {
- ToolTip("๐๐ข๐ง๐๐๐ฌ ๐๐ก๐๐ข`n"
- "โโโโโโโโโโโโโโโโโโโโโโโโโโ`n"
- "๐ฃ๐ฎ๐๐๐ฒ = MEDIA CONTROL`n"
- "๐ช๐ถ๐ป+๐ = GOD MODE`n"
- "๐ช๐ถ๐ป+๐ฅ = SMART RUN`n"
- "๐ช๐ถ๐ป+๐ = CALC/CTRL`n"
- "๐ช๐ถ๐ป+๐ฆ = SNIP`n"
- "๐ฃ๐ฟ๐๐ฆ๐ฐ๐ป = SCREENSHOT+`n"
- "๐ซ๐๐๐๐๐ผ๐ป* = MOUSE MENU`n"
- "๐ ๐๐๐๐๐ผ๐ป = CONCEAL CARET")
- ; This removes the tooltip whether modifiers are used or not, and allows hotkey variants to remain functional without them preventing the tooltip removal
- (mouseEventHook := PointerDeviceHook("LButton Down|RButton Down", HandleMouseEvent)).Start()
- HandleMouseEvent(*) => (ToolTip(), mouseEventHook.Stop())
- }
- }
- CreateTaskbarList()
- {
- iid_ITaskbarList := "{56FDF342-FD6D-11d0-958A-006097C9A090}" ; Interface id (iid)
- clsid_TaskbarList := "{56FDF344-FD6D-11d0-958A-006097C9A090}" ; Class id (clsid)
- tbl := ComObject(clsid_TaskbarList, iid_ITaskbarList) ; Creates the TaskbarList object
- loop (10)
- {
- try ComCall(3, tbl) ; Calls tbl.HrInit(), which initializes the TaskbarList object
- catch
- Sleep(50)
- else
- break
- }
- return tbl
- }
- HandleCreatedOutlookEvent(hWinEventHook, event, hWnd, *)
- {
- static outlookIsBeingLoaded := false
- ; Most windowing functions that are given a pure HWND will also work while it's hidden (dunno if it matters here but still)
- try shouldExecute := WinGetClass(hWnd) = "Olk Host" && !outlookIsBeingLoaded
- if (shouldExecute ?? false)
- {
- outlookIsBeingLoaded := true
- WinSetTransparent(0, hWnd)
- ComCall(5, tbl, "Ptr", hWnd) ; Calls tbl.DeleteTab(winId), which deletes a tab from the TaskbarList
- DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
- WinWait("- Outlook ahk_exe olk.exe") ; Minimum delay for the minimize to work
- Sleep(2500) ; Extra delay to make sure that outlook has fully loaded before minimizing it and then outlook won't have to load once the user activates it
- WinMinimize(hWnd)
- WinSetTransparent("Off", hWnd)
- ComCall(4, tbl, "Ptr", hWnd) ; Calls tbl.AddTab(winId), which adds a tab to the TaskbarList
- }
- }
- HandleCreatedVlcEvent(hWinEventHook, event, hWnd, *)
- {
- static isAttemptingToChangeAspectRatio := false
- try
- if (!isAttemptingToChangeAspectRatio && WinGetProcessName(hWnd) = "vlc.exe" && WinGetClass(hWnd) = "Qt5QWindowIcon" && WinGetTitle(hWnd) != "Building font cache")
- {
- isAttemptingToChangeAspectRatio := true
- Sleep(400) ; Discards queued events that might remain, and allows VLC to both update its INI and fully load (necessary for the INI fn below to change VLC's aspect ratio)
- if (DetermineIsPlayingFromAspectRatioVideosContextFolder())
- Send("a")
- isAttemptingToChangeAspectRatio := false
- }
- DetermineIsPlayingFromAspectRatioVideosContextFolder()
- {
- playedMedia := IniRead(A_AppData "\vlc\vlc-qt-interface.ini", "RecentsMRL", "list")
- ; This detects a network stream from Popcorn Time to VLC (the uTorrent feature won't trigger a match, it uses the --aspect-ratio flag instead which is 100% reliable)
- if (playedMedia ~= "^http://127.0.0.1:") ; The ^ requires the match to be at the start
- return true
- ; https://www.autohotkey.com/docs/alpha/misc/RegEx-QuickRef.htm (Regular Expressions [RegEx] - Quick Reference)
- loop parse (StrReplace(IniRead(A_ScriptFullPath, "AspectRatioVideosContextFolders"), " ", "%20")), "`n"
- if (playedMedia ~= "^file:///" A_LoopField) ; The ^ requires the match to be at the start
- return true
- return false
- }
- }
- ; Toggles custom VLC close btn feature when VLC becomes active/inactive
- HandleActivatedWindowVlcEvent(*)
- {
- static isManagingCustomCloseButton := false
- if (WinActive("ahk_exe vlc.exe"))
- {
- if (!IsSet(fullscreenVlcCloseButtonGui) && !isManagingCustomCloseButton)
- {
- ; Loading custom fadeable close btn for in fullscreen VLC (which is almost identical to its native close btn)
- isManagingCustomCloseButton := true
- global fullscreenVlcCloseButtonGui := Gui("+AlwaysOnTop -Caption")
- fullscreenVlcCloseButtonGui.BackColor := "E81123"
- fullscreenVlcCloseButtonGui.SetFont("s11", "Comic Sans MS")
- fullscreenVlcCloseButtonGui.AddText("x16 y0 cWhite Center", "X") ; Skipped .OnEvent("Click", ..) b/c it requires `x0 y0 w47`
- WinSetTransparent(0, fullscreenVlcCloseButtonGui)
- WinSetExStyle("+0x08000000L", fullscreenVlcCloseButtonGui) ; Adds WS_EX_NOACTIVATE
- fullscreenVlcCloseButtonGui.Show("x" A_ScreenWidth - 47 " y0 w45 h21 NoActivate")
- global fullscreenVlcCloseButtonFadeState := "FadedOut"
- fullscreenVlcCloseButtonMouseEventHook.Start()
- isManagingCustomCloseButton := false
- }
- }
- else if (IsSet(fullscreenVlcCloseButtonGui) && !isManagingCustomCloseButton)
- {
- isManagingCustomCloseButton := true
- fullscreenVlcCloseButtonMouseEventHook.Stop()
- WinClose(fullscreenVlcCloseButtonGui)
- global fullscreenVlcCloseButtonGui := unset
- isManagingCustomCloseButton := false
- }
- }
- ; Hides custom VLC close btn when the user goes out of fullscreen while it's visible
- HandleReorderedVlcEvent(*)
- {
- static fullscreenState := 2
- if (WinActive("ahk_exe vlc.exe"))
- {
- DllCall("Shell32\SHQueryUserNotificationState", "UInt*", &monitorState := 0)
- if (monitorState != fullscreenState && IsSet(fullscreenVlcCloseButtonFadeState) && fullscreenVlcCloseButtonFadeState = "FadedIn")
- {
- try WinSetTransparent(0, fullscreenVlcCloseButtonGui)
- global fullscreenVlcCloseButtonFadeState := "FadedOut"
- }
- }
- }
- HandleFullscreenVlcCloseButtonMouseEvent(eventInfo)
- {
- static fullscreenState := 2, latestButtonUsageTime := 0
- DllCall("Shell32\SHQueryUserNotificationState", "UInt*", &monitorState := 0)
- ; Click is instant and desktop is fullscreen, so this MouseEvent handler shouldn't execute after the click closed VLC, before the WinEvent is handled (hence the 2nd condition)
- if (monitorState != fullscreenState || !WinActive("ahk_exe vlc.exe"))
- return
- if (eventInfo.Pt.X > A_ScreenWidth - 48 && eventInfo.Pt.Y < 21) ; Hovering the close btn
- {
- if (eventInfo.Action = "Move")
- {
- if (fullscreenVlcCloseButtonFadeState = "FadedOut")
- {
- global fullscreenVlcCloseButtonFadeState := "Fading"
- ; Using a timer allows the fade-in to finish while the close btn waits for release in the click state
- SetTimer(FadeInVlcCloseButton()
- {
- static opacity := 0
- try
- {
- if ((opacity += 25) >= 255)
- {
- WinSetTransparent("Off", fullscreenVlcCloseButtonGui), SetTimer(, 0), opacity := 0
- global fullscreenVlcCloseButtonFadeState := "FadedIn"
- }
- else
- WinSetTransparent(opacity, fullscreenVlcCloseButtonGui)
- }
- catch
- SetTimer(, 0), opacity := 0
- }, 10)
- }
- }
- else if (latestButtonUsageTime != eventInfo.KeyUsageTime) ; And when LButton is being pressed down
- {
- latestButtonUsageTime := eventInfo.KeyUsageTime
- fullscreenVlcCloseButtonGui.BackColor := "F1707A"
- fullscreenVlcCloseButtonMouseEventHook.Stop()
- KeyWait("LButton")
- try WinClose("ahk_class Qt5QWindowIcon ahk_exe vlc.exe")
- global fullscreenVlcCloseButtonFadeState := "FadedOut"
- }
- }
- else if (eventInfo.Action = "Move" && fullscreenVlcCloseButtonFadeState = "FadedIn")
- {
- global fullscreenVlcCloseButtonFadeState := "Fading"
- loop (255)
- WinSetTransparent(255 - A_Index, fullscreenVlcCloseButtonGui), A_Index += 25, Sleep(10)
- WinSetTransparent(0, fullscreenVlcCloseButtonGui)
- global fullscreenVlcCloseButtonFadeState := "FadedOut"
- }
- }
- HandleShowedUnsavedChangesDialogEvent(hWinEventHook, event, hWnd, *)
- {
- if (WinExist("ahk_class #32770 ahk_id " hWnd))
- {
- try WinActivate(DllCall("GetParent", "UInt", hWnd))
- try WinActivate()
- }
- }
- HandleChangedFullscreenWinEvent(hWinEventHook, event, hWnd, *)
- {
- static fullscreenState := 2
- if (WinExist("ahk_group FullscreenWindows ahk_id " hWnd))
- {
- startTime := A_TickCount
- ; Repeats atleast 30 times to unmark as early as possible at an unknown repetition (the exact moment can't be determined, that would've been the only other way)
- while (A_TickCount - startTime < 500)
- {
- DllCall("Shell32\SHQueryUserNotificationState", "UInt*", &monitorState := 0)
- if (monitorState != fullscreenState)
- continue
- MarkFullscreenWindow(hWnd, false)
- DllCall("Sleep", "UInt", 10) ; This DllCall workaround prevents queued events from being handled in the meantime
- if (A_TickCount - startTime > 300)
- return
- }
- }
- ; https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist2-markfullscreenwindow
- MarkFullscreenWindow(hWnd := WinExist("A"), fullscreenStatusToSet := true)
- {
- static tbl2 := CreateTaskbarList2()
- ComCall(8, tbl2, "Ptr", hWnd, "Int", fullscreenStatusToSet)
- CreateTaskbarList2()
- {
- iid_ITaskbarList2 := "{602D4995-B13A-429B-A66E-1935E44F4317}" ; Interface id (iid)
- return ComObjQuery(tbl, iid_ITaskbarList2) ; Queries the TaskbarList object to get the TaskbarList2 object
- }
- }
- }
- HandleShowedNotificationEvent(hWinEventHook, event, hWnd, *)
- {
- ; One WinRAR wnd has the title used below (permanently ofcourse) and has `ahk_class #32770`, while the other WinRAR wnd has the class used below and has temporary title `WinRAR`.
- ; The Software Ideas Modeler wnd has no unique title nor class at any point but it does have a control with the text used below
- try
- if
- (
- WinGetTitle(hWnd) = "Please purchase WinRAR license" || (WinGetClass(hWnd) = "RarReminder" && WinGetProcessName(hWnd) = "WinRAR.exe") ||
- ControlGetText("WindowsForms10.STATIC.app.0.2bf8098_r8_ad12", hWnd) = "Thank you for using Software Ideas Modeler!"
- )
- WinSetTransparent(0, hWnd), WinClose(hWnd)
- }
- ; With Alt+Esc you can cycle open windows, but uTorrent gets that focus automatically at startup so this will unfocus it (e.g. prevents <Enter> from activating it)
- UnfocusUTorrent()
- {
- static WS_CAPTION := 0xC00000 ; title bar
- if (!WinActive("ahk_exe uTorrent.exe"))
- {
- SetTimer(, -1)
- return
- }
- for (iteratedId in WinGetList())
- if (WinExist(iteratedId) && !WinActive() && WinGetMinMax() != -1 && (WinGetClass() = "Progman" ? true : WinGetStyle() & WS_CAPTION) && WinGetTitle() != "")
- break
- WinActivate()
- }
- ManageVisualStudioEventHandlers()
- {
- static textSelectionChangedEventHandler := UIA.CreateAutomationEventHandler(HandleVisualStudioTextSelectionChangedEvent)
- , structureChangedEventHandler := UIA.CreateStructureChangedEventHandler(HandleVisualStudioStructureChangedEvent)
- , cacheRequest := UIA.CreateCacheRequest(["Type", "ClassName"],, UIA.TreeScope.Element)
- loop
- {
- WinWaitActive("Microsoft Visual Studio ahk_exe devenv.exe")
- loop
- {
- try
- {
- visualStudioElement := UIA.ElementFromHandle("Microsoft Visual Studio ahk_exe devenv.exe")
- break
- }
- catch
- Sleep(100)
- }
- UIA.AddAutomationEventHandler(textSelectionChangedEventHandler, visualStudioElement, UIA.Event.Text_TextSelectionChanged)
- UIA.AddStructureChangedEventHandler(structureChangedEventHandler, visualStudioElement,, cacheRequest)
- WinWaitNotActive() ; To make it work with multiple VS windows, it'll remove the event handlers on deactivate, and event handlers are natively removed on close
- try UIA.RemoveAutomationEventHandler(UIA.Event.Text_TextSelectionChanged, visualStudioElement, textSelectionChangedEventHandler)
- UIA.RemoveStructureChangedEventHandler(structureChangedEventHandler, visualStudioElement)
- }
- ; Reset caret hide state on relevant text selection
- HandleVisualStudioTextSelectionChangedEvent(element, *)
- {
- try (A_ThisHotkey != "MButton" && UIA.CompareElements(focusedElement.Latest, element)) ? (focusedElement.Latest := unset, focusedElement.Selection := unset) : Exit()
- }
- ; Auto-scroll namespace on relevant structure change
- HandleVisualStudioStructureChangedEvent(sender, changeType, *)
- {
- ; Only StructureChangeType_ChildAdded is allowed to continue
- if (changeType != 0)
- return
- if (sender.CachedType != UIA.Type.Pane || sender.CachedClassName != "ViewPresenter")
- return
- for (iteratedEditControl in sender.FindElements({Type: "Edit"}))
- {
- try namespaceTextRange := iteratedEditControl.DocumentRange.FindText("namespace")
- ; The bounding rectangles obj exists only in the returned array when the text range is near the top, but also has properties (X, Y, W, H) that you can technically use
- if (IsSet(namespaceTextRange) && namespaceTextRange.GetBoundingRectangles().Length = 1)
- namespaceTextRange.ScrollIntoView(1)
- }
- }
- }
- }
- HandleGodModeHotkeyActivation(shellNavigateFnObj)
- {
- static isActive := false
- ; Keeps other godmode hotkey variants from running while there's already one active and also won't execute if the user has turned Game Bar back on, because it uses the same hotkey
- if (isActive && RegRead("HKEY_CURRENT_USER\System\GameConfigStore", "GameDVR_Enabled"))
- return
- isActive := true
- pressStartTime := A_TickCount
- ; Holding Win+G pressed down for 2sec will attempt to add the active context window along with a File Explorer window to the INI
- loop
- {
- Sleep(10)
- if (!GetKeyState("#", "P") && !GetKeyState("g", "P"))
- break
- if (A_TickCount - pressStartTime > 2000)
- {
- detectedFolderPath := DetermineAnyShellFolderWinExist(&locationName)
- if (detectedFolderPath = "")
- MsgBox("To save a special File Explorer window such as the Control Panel or the Recycle Bin as the Win+G destination folder; "
- "first activate it, then the Win+G context window and lastly keep Win+G pressed for 2 seconds. "
- "For special destinations that are not inside File Explorer, then use the (advanced) input box by pressing the Win+G hotkey three times."
- , "No Open Folder Detected! - God Mode", 0x40000)
- else
- {
- IniWriteSectionOfChoice(WinGetProcessName("A"), detectedFolderPath)
- TrayTip("Destination:`t" locationName, "GOD MODE CONTEXT WND ADDED TO INI", 0x10)
- SetTimer(HideTrayTip, -4000)
- KeyWait("LWin") ; Prevents the godmode hotkey variant from triggering again while it's still pressed down
- isActive := false
- }
- return
- }
- }
- HandleHotkeyActivation(shellNavigateFnObj, DoublePressAction, TriplePressAction)
- isActive := false
- ; This lets you select a destination folder
- DoublePressAction()
- {
- dialog.ShouldProcessInput := true
- HotIf(MouseIsOverCancelButton)
- Hotkey("~*LButton", (*) => dialog.ShouldProcessInput := false, "On")
- HookEvent(EVENT_OBJECT_SHOW, HandleShowedDialogEvent)
- selectedFolder := FileSelect("D", "shell:MyComputerFolder\", "Select folder as destination to be reached with Win+G and context window")
- Hotkey("~*LButton", "Off")
- if (dialog.ShouldProcessInput)
- {
- if (selectedFolder = "")
- MsgBox("To save a special File Explorer window such as the Control Panel or the Recycle Bin as the Win+G destination folder; "
- "first activate it, then the Win+G context window and lastly keep Win+G pressed for 2 seconds. "
- "For special destinations that are not inside File Explorer, then use the (advanced) input box by pressing the Win+G hotkey three times."
- , "No Folder Selection Detected! - God Mode", 0x40000)
- else
- IniWriteSectionOfChoice(WinGetProcessName("A"), selectedFolder)
- }
- ; Disables dialog close button and makes window stay always-on-top (the user should use the cancel button instead b/c it won't show a msg when there is no folder selected)
- HandleShowedDialogEvent(hWinEventHook, event, hWnd, *)
- {
- try
- if (WinGetClass(hWnd) = "#32770")
- {
- DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
- DllCall("EnableMenuItem", "Ptr", DllCall("GetSystemMenu", "UInt", hWnd, "Int", 0), "UInt", SC_CLOSE := 0xF060, "UInt", MF_GRAYED := 0x00000001)
- WinSetAlwaysOnTop(true, hWnd)
- }
- }
- MouseIsOverCancelButton(*)
- {
- try return (MouseGetPos(,, &winId, &control), WinExist("ahk_class #32770 ahk_id " winId) && control = "Button2")
- return false
- }
- }
- ; Advanced: input box for special destination (e.g. https://youtube.com to open YouTube in your browser or shell folder shortcuts such as shell:AppsFolder)
- TriplePressAction()
- {
- static _gui
- if (IsSet(_gui))
- _gui.Show()
- else
- {
- _gui := Gui("+AlwaysOnTop -SysMenu", "Advanced Dialog - God Mode")
- _gui.BackColor := "White"
- _gui.AddText(, "`nEnter destination to be reached with Win+G and context window`n")
- _gui.AddEdit("vDestination w340 h23")
- _gui.AddButton("default w88 h26 x170 y107", "OK").OnEvent("Click", ProcessUserInput)
- _gui.AddButton("w88 h26 x+7 y107", "Cancel").OnEvent("Click", (*) => _gui.Hide())
- _gui.AddProgress("w360 h61 x0 y89 cF0F0F0", 100)
- _gui.AddButton("w88 h26 x170 y107", "OK") ; Gray bg btn overlay
- _gui.AddButton("w88 h26 x+7 y107", "Cancel") ; Gray bg btn overlay
- _gui.Show("w360 h150")
- }
- ProcessUserInput(*)
- {
- if ((destination := _gui.Submit().Destination) != "")
- IniWriteSectionOfChoice(WinGetProcessName("A"), destination)
- }
- }
- IniWriteSectionOfChoice(contextWindow, destination)
- {
- HookEvent(EVENT_OBJECT_CREATE, HandleCreatedDialogEvent)
- shouldAddToSectionExistingContextWindowPriorityN := MsgBox("The following context window will be used:`t" contextWindow
- "`n`nClick `"Exist`" if the context window has to exist before it may trigger on hotkey press. It will then have the next available priority, "
- "so when there is more than one of these context windows existing, whichever has the highest priority gets triggered. Otherwise click "
- "`"Active`" if the context window has to be active", "Context Window Condition - God Mode", 0x40004)
- if (shouldAddToSectionExistingContextWindowPriorityN = "Yes")
- {
- IniWriteExistingContextWindows("ahk_exe " contextWindow "=" destination)
- HotIf((*) => WinExist("ahk_exe " contextWindow))
- Hotkey("#g", (*) => (Send("#g"), Sleep(100), (godmodeActiveContextWindow.HasTriggered ? Exit() : HandleGodModeHotkeyActivation(() => ShellNavigate(destination)))), "I1")
- }
- else
- {
- IniWrite(destination, iniPath, "ActiveContextWindows", "ahk_exe " contextWindow)
- HotIf((*) => WinActive("ahk_exe " contextWindow))
- Hotkey("#g", (*) => (
- HandleGodModeHotkeyActivation(() => ShellNavigate(destination)),
- godmodeActiveContextWindow.HasTriggered := true,
- SetTimer(() => godmodeActiveContextWindow.HasTriggered := false, -100)
- ))
- }
- HandleCreatedDialogEvent(hWinEventHook, event, hWnd, *)
- {
- try
- if (WinGetClass(hWnd) = "#32770")
- {
- DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
- ControlSetText("Exist", "Button1", hWnd)
- ControlSetText("Active", "Button2", hWnd)
- }
- }
- }
- }
- HideTrayTip()
- {
- TrayTip() ; Attempt to hide it the normal way
- if (SubStr(A_OSVersion, 1, 3) = "10.")
- A_IconHidden := true, Sleep(200), A_IconHidden := false
- }
- ; Detects single, double, and triple-presses of a hotkey. This allows a hotkey to perform a different operation depending on how many times you press it (convenient encapsulation only)
- HandleHotkeyActivation(onePressActionFnObj, doublePressActionFnObj, triplePressActionFnObj?)
- {
- static quickPressCount := 0, _executeMultiFunctionHotkeyAction
- maxPressCount := IsSet(triplePressActionFnObj) ? 3 : 2
- if (quickPressCount + 1 < maxPressCount)
- ++quickPressCount
- else
- {
- quickPressCount := maxPressCount
- return
- }
- if (!IsSet(_executeMultiFunctionHotkeyAction))
- _executeMultiFunctionHotkeyAction := ExecuteMultiFunctionHotkeyAction ; Allows timer updates
- SetTimer(_executeMultiFunctionHotkeyAction, -500)
- ExecuteMultiFunctionHotkeyAction()
- {
- switch (quickPressCount)
- {
- case 1: onePressActionFnObj()
- case 2: doublePressActionFnObj()
- case 3: triplePressActionFnObj()
- }
- quickPressCount := 0
- _executeMultiFunctionHotkeyAction := unset
- }
- }
- ; This writes a new section below [ExistingContextWindows] or the latest [ExistingContextWindowPriorityN] if there are any (the new section can be part of godmode but custom too!)
- IniWriteExistingContextWindows(pairs, section?)
- {
- loop
- {
- try IniRead(iniPath, "ExistingContextWindowPriority" A_Index) ; Allows the catch scope to execute if the key doesn't exist
- catch
- {
- if (!IsSet(section))
- section := "[ExistingContextWindowPriority" A_Index "]"
- IniWrite("`n" section "`n" pairs, iniPath, A_Index = 1 ? "ExistingContextWindows" : "ExistingContextWindowPriority" A_Index - 1, "[TemporarySection]")
- IniDelete(iniPath, "TemporarySection")
- break
- }
- }
- }
- ShellNavigate(path)
- {
- static shellObj := ComObject("Shell.Application")
- if
- (
- InStr(path, "chrome.exe") &&
- !ProcessExist("chrome.exe") &&
- (hasTabsOutlinerExtension := DirExist(EnvGet("LocalAppData") "\Google\Chrome\User Data\Default\Extensions\eggkanocgddhmamlbiijnphhppkpkmkl"))
- )
- HookEvent(EVENT_OBJECT_NAMECHANGE, HandleNameChangedTabsOutlinerEvent)
- ; Shows search field after it runs an AHK site (the initial delay is in case such a chrome window exists already, to affect the new tab when it has fully loaded after the 2nd delay)
- if (InStr(path, "autohotkey.com"))
- {
- Run(path)
- Sleep(500)
- if (WinWaitActive("AutoHotkey v2",, 15))
- Sleep(500), Send("!s")
- return
- }
- ; The first scope can change the active explorer window location (prevents unnecessarily opening another explorer window), but it can run all kinds of stuff just like the Run command
- if ((activeWinId := WinActive("ahk_class CabinetWClass")) || (activeWinId := WinActive("ahk_class ExploreWClass")))
- {
- for (iteratedWindow in shellObj.Windows)
- if ((activeWindow := iteratedWindow).hWnd = activeWinId)
- break
- ; Adding the shell: prefix to CLSIDs that do not have it already (to make them compatible with the Navigate2 fn)
- if (SubStr(path, 1, 3) = "::{")
- path := "shell:" path
- activeWindow.Navigate2(path)
- }
- else
- Run(path)
- }
- DetermineAnyShellFolderWinExist(&locationName?)
- {
- static shellObj := ComObject("Shell.Application")
- if ((latestActiveWinId := WinExist("ahk_class CabinetWClass")) || (latestActiveWinId := WinExist("ahk_class ExploreWClass")))
- {
- for (iteratedWindow in shellObj.Windows)
- if ((latestActiveWindow := iteratedWindow).hWnd = latestActiveWinId)
- break
- locationName := latestActiveWindow.LocationName
- return latestActiveWindow.Document.Folder.Self.Path
- }
- }
- ; Argument can be Show, Hide, Toggle or Reload
- SystemCursor(cmd)
- {
- static visible := true, c := Map()
- static sys_cursors := [32512, 32513, 32514, 32515, 32516, 32642, 32643, 32644, 32645, 32646, 32648, 32649, 32650]
- if (cmd = "Reload" || !c.Count) ; Reload when requested or at first call
- {
- for (i, id in sys_cursors)
- {
- h_cursor := DllCall("LoadCursor", "Ptr", 0, "Ptr", id)
- h_default := DllCall("CopyImage", "Ptr", h_cursor, "UInt", 2, "Int", 0, "Int", 0, "UInt", 0)
- h_blank := DllCall("CreateCursor", "Ptr", 0, "Int", 0, "Int", 0, "Int", 32, "Int", 32, "Ptr", Buffer(32 * 4, 0xFF), "Ptr", Buffer(32 * 4, 0))
- c[id] := {Default: h_default, Blank: h_blank}
- }
- }
- switch (cmd)
- {
- case "Show": visible := true
- case "Hide": visible := false
- case "Toggle": visible := !visible
- default: return
- }
- for (id, handles in c)
- {
- h_cursor := DllCall("CopyImage", "Ptr", visible ? handles.Default : handles.Blank, "UInt", 2, "Int", 0, "Int", 0, "UInt", 0)
- DllCall("SetSystemCursor", "Ptr", h_cursor, "UInt", id)
- }
- }
- class MenuItemInfo
- {
- CbSize: u32 := ObjGetDataSize(this), FMask: u32, FType: u32, FState: u32, WID: u32, HSubMenu: iptr, HbmpChecked: iptr, HbmpUnchecked: iptr, DwItemData: uptr, DwTypeData: iptr
- Cch: u32, HbmpItem: iptr
- }
- class Point
- {
- X: i32, Y: i32
- }
- /*
- Example usage: (pointerDeviceEventHook := PointerDeviceHook("Move|LButton Down|LButton Up", HandlePointerDeviceEvent)).Start()
- /** @param {PointerDeviceHook.EventInfo} eventInfo Pointer device event info */`
- HandlePointerDeviceEvent(eventInfo)
- {
- ToolTip(Format("
- (
- x{1}, y{2}
- EventAction : {3}
- EventKey : {4}
- KeyUsageCount : {5}
- KeyUsageTime : {6}
- PressDuration : {7}
- IsPenAction : {8}
- )", eventInfo.Pt.X, eventInfo.Pt.Y, eventInfo.Action, eventInfo.Key, eventInfo.KeyUsageCount, eventInfo.KeyUsageTime, eventInfo.KeyPressDuration, eventInfo.IsPenAction))
- }
- */
- class PointerDeviceHook
- {
- class InternalEventInfo
- {
- Pt: Point
- MouseData: i32 ; Necessary cast to `Int`
- Flags: u32
- Time: u32
- ExtraInfo: uptr
- }
- class EventInfo
- {
- Pt => this._IsPtAdaptive ? PointerDeviceHook.EventInfo.LatestPt : this._Pt
- /** @prop {string} Action The event action */
- Action => this._IsActionAdaptive ? (PointerDeviceHook.EventInfo.LatestAction ?? this._Action) : this._Action
- /** @prop {string} Key The event key */
- Key => PointerDeviceHook.EventInfo.IsKeyPressedDown ? PointerDeviceHook.EventInfo.RetainedKey : this._Key
- /** @prop {integer} KeyUsageCount Count how many times a key gets pressed in a short time (`KeyUsageCountTimeThreshold`) */
- KeyUsageCount => PointerDeviceHook.EventInfo.IsKeyPressedDown ? PointerDeviceHook.EventInfo.RetainedKeyUsageCount : this._KeyUsageCount
- /** @prop {string} KeyUsageTime The time when the event key was pressed, scrolled, or used for a pen action */
- KeyUsageTime => PointerDeviceHook.EventInfo.IsKeyPressedDown ? PointerDeviceHook.EventInfo.RetainedKeyUsageTime : this._KeyUsageTime
- /** @prop {integer} KeyPressDuration The time elapsed since this key was pressed */
- KeyPressDuration => (this.KeyUsageTime ? A_TickCount - this.KeyUsageTime : 0)
- /** @prop {integer} IsPenAction Whether or not the event is caused by a pen pointer device (not detected when using drawing tablet) */
- IsPenAction => PointerDeviceHook.EventInfo.IsKeyPressedDown ? PointerDeviceHook.EventInfo.RetainedIsPenAction : this._IsPenAction
- /** @prop {boolean} IsKeyPressedDown The hook does not repeatedly trigger the down event while a key is pressed down, so those `onEvent` callbacks use timer & keeps relevant info */
- static IsKeyPressedDown := false
- static __New() => this.LatestPt := Point()
- __New() => this._Pt := Point()
- }
- /** @prop {Map} MsgList A list of message codes and actions (the commented wheel actions can also be used in the `PointerDeviceHook` constructor) */
- MsgList := Map(
- 512, "Move",
- 513, "LButton Down",
- 514, "LButton Up",
- 516, "RButton Down",
- 517, "RButton Up",
- 519, "MButton Down",
- 520, "MButton Up",
- 523, "XButton{:d} Down",
- 524, "XButton{:d} Up")
- ;โโ, "WheelUp"
- ;โโ, "WheelDown"
- /** @prop {integer} ProcHandle SetWindowsHookEx */
- ProcHandle := 0
- /** @prop {Map} PriorKeyObjects The map logs the time of when keys were previously pressed, as well as the count (both saved inside an object which is associated with a key) */
- PriorKeyObjects := Map()
- /** @prop {integer} KeyUsageCountTimeThreshold The time in which the usage of the event key gets counted, or reset when the time threshold is reached (milliseconds) */
- KeyUsageCountTimeThreshold := 500
- /**
- * @param {string} [action="All"] Move, LButton Down, MButton Up, etc (the `MsgList` property shows all of them)
- * @param {(hookObj) => Integer} onEvent This callback gets called on the event (to block mouse actions the callback must return true w/ default value `shouldMaintainResponsiveness`)
- * @param {integer} [shouldMaintainResponsiveness=false] Default is False, causing it to call `onEvent` in this thread in favor of mouse-action-blocking capability (consider using timer
- * in `onEvent`). Specify True to call it in a different thread if the `onEvent` code causes considerable mouse lag, as a result the Proc becomes incapable of blocking mouse actions
- * @param {integer} [criticalMode=0] Default is Disabled Mode. A (positive) Enabled Mode value is the message check interval. Specifying -1 turns on Critical but disables message checks
- */
- __New(action := "All", onEvent := (*) => 0, shouldMaintainResponsiveness := false, criticalMode := 0)
- {
- static WM_LBUTTONDOWN := 0x0201, WM_LBUTTONUP := 0x0202, WM_RBUTTONDOWN := 0x0204, WM_RBUTTONUP := 0x0205, WM_MBUTTONDOWN := 0x0207, WM_MBUTTONUP := 0x0208, WM_MOUSEWHEEL := 0x020A
- , WM_XBUTTONDOWN := 0x020B, WM_XBUTTONUP := 0x020C, LLMHF_INJECTED := 0x00000001, MI_WP_SIGNATURE := 0xFF515700, SIGNATURE_MASK := 0xFFFFFF00
- ; This callback gets executed when a pointer-device hook event occurs. The fast mode should be used only when it is known exactly which thread(s) this callback will be called from
- this.InternalCallback := CallbackCreate(PointerDeviceProc, (criticalMode && criticalMode != "Off") ? "F" : unset, 3)
- PointerDeviceProc(nCode, wParam, lParam)
- {
- if (criticalMode = -1 || criticalMode)
- Critical(criticalMode)
- internalEventInfo := StructFromPtr(PointerDeviceHook.InternalEventInfo, lParam)
- eventInfo := PointerDeviceHook.EventInfo()
- ; `internalEventInfo.MouseData` contains a reserved low-order word, which we don't need, and the high-order word is the leftmost 16 bits (bitshift removes the rest).
- ; `PointerDeviceHook.EventInfo.IsKeyPressedDown` is mainly set at this point so that the up event will also stop the repeated down event timer when the up action isn't hooked
- switch (wParam)
- {
- case WM_MOUSEWHEEL: eventInfo._Action := (internalEventInfo.MouseData >> 16) > 0 ? "WheelUp" : "WheelDown", PointerDeviceHook.EventInfo.IsKeyPressedDown := false
- case WM_XBUTTONDOWN: eventInfo._Action := Format(this.MsgList[wParam], internalEventInfo.MouseData >> 16), PointerDeviceHook.EventInfo.IsKeyPressedDown := true
- case WM_XBUTTONUP: eventInfo._Action := Format(this.MsgList[wParam], internalEventInfo.MouseData >> 16), PointerDeviceHook.EventInfo.IsKeyPressedDown := false
- case WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN: eventInfo._Action := this.MsgList[wParam], PointerDeviceHook.EventInfo.IsKeyPressedDown := true
- case WM_LBUTTONUP, WM_RBUTTONUP, WM_MBUTTONUP: eventInfo._Action := this.MsgList[wParam], PointerDeviceHook.EventInfo.IsKeyPressedDown := false
- default: eventInfo._Action := this.MsgList.Has(wParam) ? this.MsgList[wParam] : 0
- }
- if (nCode < 0 || (action != "All" && !InStr(action, eventInfo._Action)))
- return CallNextHookEx(nCode, wParam, lParam)
- eventInfo._IsPtAdaptive := eventInfo._IsActionAdaptive := false
- eventInfo._KeyUsageTime := eventInfo._KeyUsageCount := eventInfo._Key := 0
- eventInfo._Pt.X := internalEventInfo.Pt.X
- eventInfo._Pt.Y := internalEventInfo.Pt.Y
- if (eventInfo._Action && eventInfo._Action != "Move")
- {
- if (!this.PriorKeyObjects.Has(eventInfo._Action))
- this.PriorKeyObjects[eventInfo._Action] := {Time: internalEventInfo.Time, Count: 0}
- priorKey := this.PriorKeyObjects[eventInfo._Action]
- eventInfo._Key := eventInfo._Action
- eventInfo._KeyUsageCount := priorKey.Count += internalEventInfo.Time - priorKey.Time < this.KeyUsageCountTimeThreshold ? 1 : -priorKey.Count + 1 ; Resets to 1 if false
- eventInfo._KeyUsageTime := priorKey.Time := internalEventInfo.Time
- eventInfo._IsPenAction := DetermineIsPenAction(internalEventInfo.ExtraInfo)
- if (PointerDeviceHook.EventInfo.IsKeyPressedDown)
- {
- keyDownEventInfo := eventInfo.Clone()
- keyDownEventInfo._IsPtAdaptive := keyDownEventInfo._IsActionAdaptive := true
- PointerDeviceHook.EventInfo.LatestPt.X := eventInfo._Pt.X
- PointerDeviceHook.EventInfo.LatestPt.Y := eventInfo._Pt.Y
- PointerDeviceHook.EventInfo.LatestAction := unset
- PointerDeviceHook.EventInfo.RetainedKey := eventInfo._Key
- PointerDeviceHook.EventInfo.RetainedKeyUsageCount := eventInfo._KeyUsageCount
- PointerDeviceHook.EventInfo.RetainedKeyUsageTime := internalEventInfo.Time
- PointerDeviceHook.EventInfo.RetainedIsPenAction := eventInfo._IsPenAction
- SetTimer(() => (this.ProcHandle && PointerDeviceHook.EventInfo.IsKeyPressedDown ? onEvent(keyDownEventInfo) : SetTimer(, 0)), 50)
- }
- }
- else if (PointerDeviceHook.EventInfo.IsKeyPressedDown)
- {
- PointerDeviceHook.EventInfo.LatestPt.X := eventInfo._Pt.X
- PointerDeviceHook.EventInfo.LatestPt.Y := eventInfo._Pt.Y
- PointerDeviceHook.EventInfo.LatestAction := eventInfo._Action
- }
- else
- eventInfo._IsPenAction := DetermineIsPenAction(internalEventInfo.ExtraInfo)
- if (shouldMaintainResponsiveness)
- {
- SetTimer(() => onEvent(eventInfo), -1)
- return CallNextHookEx(nCode, wParam, lParam)
- }
- else
- return onEvent(eventInfo) && !(internalEventInfo.Flags & LLMHF_INJECTED) ? true : CallNextHookEx(nCode, wParam, lParam)
- }
- DetermineIsPenAction(extraInfo) => ((extraInfo & SIGNATURE_MASK) = MI_WP_SIGNATURE)
- CallNextHookEx(nCode, wParam, lParam) => DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "UPtr", wParam, "Ptr", lParam)
- }
- /** Warning: Take caution when blocking mouse actions, you should not call this inside a mouse hotkey prefixed w/ the (~) tilde symbol (to make `Stop` unblock mouse actions properly) */
- Start()
- {
- if (!this.ProcHandle)
- this.ProcHandle := DllCall("SetWindowsHookEx", "Int", WH_MOUSE_LL := 14, "Ptr", this.InternalCallback, "Ptr", GetModuleHandle(), "UInt", 0)
- GetModuleHandle() => DllCall("GetModuleHandle", "UInt", 0, "Ptr")
- }
- Stop()
- {
- if (this.ProcHandle && DllCall("UnhookWindowsHookEx", "Ptr", this.ProcHandle))
- this.ProcHandle := 0
- }
- __Delete() => (this.InternalCallback && (this.Stop(), CallbackFree(this.InternalCallback), this.InternalCallback := 0))
- }
- OpenGoogle(*)
- {
- SystemCursor("Show")
- if (FileExist(A_ProgramFiles "\Google\Chrome\Application\chrome.exe"))
- {
- if (ProcessExist("chrome.exe") || !(hasTabsOutlinerExtension := DirExist(EnvGet("LocalAppData") "\Google\Chrome\User Data\Default\Extensions\eggkanocgddhmamlbiijnphhppkpkmkl")))
- Run("chrome.exe https://www.google.com/ --start-maximized --disable-features=GlobalMediaControls")
- else
- {
- HookEvent(EVENT_OBJECT_NAMECHANGE, HandleNameChangedTabsOutlinerEvent)
- Run("chrome.exe https://www.google.com/ --start-maximized --disable-features=GlobalMediaControls")
- }
- }
- else
- Run("https://www.google.com/")
- }
- HandleNameChangedTabsOutlinerEvent(hWinEventHook, event, hWnd, *)
- {
- static isBeingClosed := false
- try
- if (WinGetTitle(hWnd) = "_crx_eggkanocgddhmamlbiijnphhppkpkmkl" && !isBeingClosed)
- {
- isBeingClosed := true
- try WinSetTransparent(0, hWnd) ; Gets rid of the close animation
- try WinClose(hWnd)
- DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
- Sleep(-1) ; Discards queued events that might remain
- isBeingClosed := false
- }
- }
- OpenMaps(*)
- {
- SystemCursor("Show")
- Run("shell:AppsFolder\Microsoft.WindowsMaps_8wekyb3d8bbwe!app")
- if (!WinWaitActive("Maps ahk_class ApplicationFrameWindow",, 3))
- return
- Sleep(300)
- Send("^y{Ctrl down}")
- loop (50)
- Sleep(50), Send("{Home}")
- Send("{Ctrl up}")
- }
- MouseIsOver(winTitle, winText?, excludeTitle?, excludeText?) => (MouseGetPos(,, &winId), WinExist(winTitle " ahk_id " winId, winText?, excludeTitle?, excludeText?))
- HookEvent(event, fnObj, pid := 0) => DllCall("SetWinEventHook", "UInt", event, "UInt", event, "Ptr", 0, "Ptr", CallbackCreate(fnObj), "UInt", pid, "UInt", 0, "UInt", 0)
- /* EXAMPLE
- [_ActiveContextWindows]
- ahk_exe Taskmgr.exe=services.msc
- [_ExistingContextWindows]
- [_ExistingContextWindowPriority1]
- VOXEL WAR ahk_exe Unity.exe=shell:Profile\Documents\Unity projects\VOXEL WAR\Assets
- [_ExistingContextWindowPriority2]
- VOXEL WAR ahk_exe devenv.exe=shell:Profile\Documents\Unity projects\VOXEL WAR\Assets\Scripts
- [_ExistingContextWindowPriority3]
- ahk_exe Unity.exe=shell:Profile\Documents\Unity projects
- [_ExistingContextWindowPriority4]
- ahk_exe devenv.exe=shell:Profile\Documents\Unity projects
- [_ExistingContextWindowPriority5]
- ahk_exe notepad.exe=chrome.exe https://www.autohotkey.com/docs/alpha/ChangeLog.htm --start-maximized --disable-features=GlobalMediaControls
- [_ExistingContextWindowPriority6]
- Workspace - Visual Studio Code ahk_exe chrome.exe=chrome.exe https://www.autohotkey.com/docs/alpha/ChangeLog.htm --start-maximized --disable-features=GlobalMediaControls
- [_PreferredSmartRunInput]
- %LocalAppData%
- [_AspectRatioVideosContextFolders]
- C:/Users/loren/Downloads/Films
- C:/Users/loren/AppData/Local/Temp/Popcorn Time
- X:/
- D:/Films
- E:/Opslag
- [_FullscreenWindowsUnhideTaskbar]
- Sourcetree ahk_exe SourceTree.exe
- Software Ideas Modeler ahk_exe SoftwareIdeasModeler.exe
- Popcorn-Time ahk_exe Popcorn-Time.exe
- Epic Games Launcher ahk_exe EpicGamesLauncher.exe
- GeForce Experience ahk_exe NVIDIA GeForce Experience.exe
- */
- /* Edit these variables yourself if necessary (e.g. to make it more specific you can add the ahk_class, and for the opposite effect you can replace the ahk_exe with an ahk_class or title)
- [ActiveContextWindows]
- [ExistingContextWindows]
- [PreferredSmartRunInput]
- [AspectRatioVideosContextFolders]
- [FullscreenWindowsUnhideTaskbar]
- */
Comments
-
- [TEST ALL THIS GODMODE STUFF AGAIN IF I'M STILL GONNA USE IT, MIGHT ALL BE RESOLVED NOW THAT I HAVE CHANGED SOME STUFF]
- using godmode works but using double-press/long-press/triple-press to set something doesn't seem to load the new hotkey that has been added to the INI, only when I restart the script
- - tested with both [active] & [existing], they both have the issue
- also godmode overwrites the [active] if one of the context wnd entry exists already but with [existing] it just adds it below instead of overwriting, not sure if that's rly a problem tho
- keeping godmode hotkey pressed down for twice as long repeats its function twice, so it opens two INI save windows, consistently with the active context wnd only ([existing] is mostly fine)
- - but letting go after the normal time and then pressing it down again, that won't open a second INI save window.. can't even use the quick-press with an INI save wnd open (strange)
- keeping godmode hotkey pressed down for the normal time opens one INI save window and also triggers a quick-press to open a destination of the active context wnd only ([existing] is fine)
- - but letting go after the normal time and then a quick-press triggers [existing], not [active], and doing a long-press instead of quick-press now 'suddenly' does open a 2nd save window o.o
-
- this has code to fix the recycle bin, it randomly resets which columns are shown and the sorting:
- https://www.autohotkey.com/boards/viewtopic.php?f=6&t=33129
-
- bit offtopic but w/e, "Context Menu New AutoHotkey Script.reg":
- Windows Registry Editor Version 5.00
- ; I removed it, so this will add it back
- [HKEY_CLASSES_ROOT\.ahk\ShellNew]
- "Command"="\"C:\\Program Files\\AutoHotkey\\UX\\AutoHotkeyUX.exe\" \"C:\\Program Files\\AutoHotkey\\UX\\ui-newscript.ahk\" \"%1\""
- ; I copied the template from %ProgramFiles%\AutoHotkey\UX\Templates to %SystemRoot%\ShellNew, took out the "v" of "v2.0" inside the script, removed the multi-line comment and renamed it.
- ; So this will remove the value "FileName"="CustomTemplate.ahk"
- [HKEY_CLASSES_ROOT\.ahk\ShellNew]
- "FileName"=-
-
- ; These are merely so that they get buffered if the OS were to lag, which might cause the `SetVlcVideoOutputForRelevantFeatureFix` fn to be taking too long to finish (then VLC opens without the setting change, although I highly doubt that this will ever happen.. my tests revealed that the fn finishes before the `LButton up` after selection)
- #HotIf (WinActive("ahk_group FileExplorer"))
- LButton::Send("{LButton down}"), KeyWait("LButton"), Send("{LButton up}")
- Enter::Send("{Enter}"), KeyWait("Enter")
- GroupAdd("FileExplorer", "ahk_class Progman")
- GroupAdd("FileExplorer", "ahk_class WorkerW")
- GroupAdd("FileExplorer", "ahk_class CabinetWClass")
- GroupAdd("FileExplorer", "ahk_class ExploreWClass")
-
- the following can be used instead of ControlSend("{Enter}") in the XButton* hotkeys of the latest Time Saver version, but I decided not to use it (it's the only way to close the menu properly, b/c using WinClose/WinHide too fast makes it impossible to create menus): ControlSend("{Esc}")
-
- ; this has not been tested, but might work (I'm trying an even better way for now, activating WorkerW and then GroupActivate to go back)
- #HotIf (WinActive("ahk_exe notepad.exe") || WinActive("- Visual Studio Code ahk_class Chrome_WidgetWin_1"))
- ;MButton::WinActivate("ahk_class Progman")
- MButton::
- {
- A_ControlDelay := -1 ; Changes only the control delay of the thread made for this specific hotkey
- global lastActiveWnd := WinExist("A")
- WinActivate("ahk_class Progman")
- ControlClick("x0 y0", "ahk_class Progman",,,, "Pos")
- HookEvent(EVENT_SYSTEM_FOREGROUND, HandleActivatedWindowTextEditorEvent)
- HandleActivatedWindowTextEditorEvent(hWinEventHook, event, hWnd, *)
- {
- try
- if (!WinGetClass(hWnd) = "Progman" || !WinGetClass(hWnd) = "WorkerW")
- {
- DllCall("UnhookWinEvent", "Ptr", hWinEventHook)
- global lastActiveWnd := unset
- }
- }
- }
- ;#HotIf (WinActive("ahk_class WorkerW"))
- #HotIf (WinActive("ahk_class Progman"))
- MButton::try WinActivate(lastActiveWnd)
Add Comment
Please, Sign In to add comment