Skip to content

Instantly share code, notes, and snippets.

@LeoDJ
Last active February 1, 2019 15:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LeoDJ/b2b5a796a312c84eff6635f6fb89afa9 to your computer and use it in GitHub Desktop.
Save LeoDJ/b2b5a796a312c84eff6635f6fb89afa9 to your computer and use it in GitHub Desktop.
AHK middle mouse scroll everywhere
; Description: Scroll Explorer on middle mouse button drag
; Permalink: https://autohotkey.com/boards/viewtopic.php?t=43715
; Author: aph
; Version: 0.4.1
; Modified by: LeoDJ
; changelog:
; 0.4.1: - fixed Firefox getting stuck
; 0.4.0: - implemented much better exponential scrolling behaviour
; - tried to handle sticky scrolling better, but sometimes AHK does not see the KeyUp event, even when polled
; 0.3.0: - implement other scrolling behaviour, but still not perfect
; 0.2.1: - allow scrolling in any application
; TODO:
; - fix bug when firefox is inactive and is middle-clicked, nothing becomes clickable anymore, until Ctrl-Alt-Del
$*MButton::
MouseGetPos, CursorX, CursorY, Window, ClassNN
WinGetTitle, Title, ahk_id %Window%
WinGetClass, ahk_class, ahk_id %Window%
WinGet ahk_exe, ProcessName, ahk_id %Window%
WinGet ahk_PID, PID, ahk_id %Window%
WinGetText, VisibleText, ahk_id %Window%
MouseGetPos, CursorX_ended, CursorY_ended, Window_ended, ClassNN_ended
WinGetClass, ahk_class_ended, ahk_id %Window_ended%
WinGet ahk_exe_ended, ProcessName, ahk_id %Window_ended%
AllowedApp := True or ahk_exe = "explorer.exe" or ahk_exe = "mmc.exe" or ahk_exe = "systempropertiesadvanced.exe" or ahk_exe = "filezilla.exe" or ahk_exe = "7zFM.exe"
AllowedText := InStr(VisibleText, "Tree View") or InStr(VisibleText, "FolderView")
LimitedApp := ahk_exe = "cmd.exe"
DisabledApp := ahk_class_ended = "Shell_TrayWnd" or ahk_class_ended = "WorkerW" or ahk_exe = "firefox.exe" or Title = "3D Viewer"
if (AllowedText >= 1)
AllowedText = 1
If (DisabledApp) {
SendInput, {MButton Down}
Return
}
Else If (!AllowedApp and !LimitedApp and !AllowedText) {
SendInput, {MButton Down}
Return
}
Else {
If (AllowedApp) {
; SendInput, {MButton}
}
MiddleScroll := 1
SetSystemCursor("SIZEALL")
DeadZone = 5 ; How far the middle mouse wheel has to be dragged before scrolling is triggered
Sensitivity := 5 ; inverse, higher = less sensitive
ExpoBase := 1.1
OrigTimer := 500 ; How quickly the file list scrolls
MouseGetPos, X1, Y1, , c, 2
PollInterval := 50
SetTimer, MBScroll, %PollInterval%
LastScroll := A_TickCount
LastStickyCheck := A_TickCount
Timer := 0
ScrollTicks := 0
MBScroll:
MouseGetPos, X2, Y2
Distance := Abs(Y2-Y1)
If (Distance >= DeadZone) {
Timer := OrigTimer / (ExpoBase ** (Distance / Sensitivity - DeadZone))
If (Timer < 0) {
Timer := 0
}
If (A_TickCount - LastScroll >= Timer) {
SendInput, % "{Blind}{Wheel" (Y2 > Y1 ? "Down" : "Up") " " Rounded "}"
LastScroll := A_TickCount
ScrollTicks++
}
; fix sticky scrolling, can't check often, because else GetKeyState gets stuck as well
If (A_TickCount - LastStickyCheck >= 50) {
LastStickyCheck := A_TickCount
If (!GetKeyState("MButton", "P")) {
; OutputDebug, "Was stuck, stop scrolling"
; SetTimer, MBScroll, off
Gosub MBScrollDone
Return
}
}
waitTime := Timer < PollInterval ? Timer : PollInterval
SetTimer, MBScroll, %waitTime%
; debug := GetKeyState("MButton", "P")
; OutputDebug, %debug%
}
Return
MBScrollDone:
DllCall("SystemParametersInfo", UInt, 0x69, UInt, 3, UInt, 0, UInt, 0) ; Set back to 3 lines scrolled
SetTimer, MBScroll, off
SetSystemCursor()
MiddleScroll := 0
If (ScrollTicks == 0) {
SendInput {MButton}
}
SetSystemCursor(Cursor="") {
SystemCursors := "32512IDC_ARROW|32513IDC_IBEAM|32514IDC_WAIT|32515IDC_CROSS|32516IDC_UPARROW|32642IDC_SIZENWSE|32643IDC_SIZENESW|32644IDC_SIZEWE|32645IDC_SIZENS|32646IDC_SIZEALL|32648IDC_NO|32649IDC_HAND|32650IDC_APPSTARTING|32651IDC_HELP"
If (Cursor = "")
Return DllCall("SystemParametersInfo", "UInt", 0x57, "UInt", 0, "UInt", 0, "UInt", 0)
If (StrLen(SystemCursors) = 221)
Loop, Parse, SystemCursors, |
StringReplace, SystemCursors, SystemCursors, %A_LoopField%, % DllCall("LoadCursor", "UInt", 0, "Int", SubStr(A_LoopField, 1, 5)) A_LoopField
If !(Cursor := SubStr(SystemCursors, InStr(SystemCursors "|", "IDC_" Cursor "|") - 5 - p := (StrLen(SystemCursors) - 221) / 14, 5))
MsgBox, 262160, %A_ScriptName% - %A_ThisFunc%(): Error, Invalid cursor name!
Else
Loop, Parse, SystemCursors, |
DllCall("SetSystemCursor", "UInt", DllCall("CopyIcon", "UInt", Cursor), "Int", SubStr(A_LoopField, 6, p))
}
Return
$*MButton Up::
If (DisabledApp or LimitedApp) {
SendInput {MButton Up}
}
Else {
Gosub MBScrollDone
}
Return
}
Return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment