Hey that is really great!
There was one other quandary... that concept you made for a hotkey to move the scrollbar, ... that concept does not seem to work here off the bat (though the smooth scrolling works via normal mouse grab & move... just not the hotkey function below)
It was from here:
http://www.autohotkey.com/forum/post-153675.html#153675
I looked it over carefully, but didn't see anything obvious, liken to the changes needed for this GUI to work with smooth momentum scrolling normally

Can you see what is wrong?
EDIT 1: If I am not mistaken, it looks like it is the HWND that is not being picked up somehow when the Kicktoolbar function is being called. I tried a few things, but it seems to have its own ID (as Static1), and generates a different HWND address when using the Kicktoolbar function, which is strange
EDIT 2: BUT HEY, to my surprise (!) when I combined the two scripts together, the thing malfunctions (the insides go wacky). When I ran them separately, it worked just fine (minus the hotkey(s) which are assigned to SCROLLMOMEMTUM, ... but I don't know how this could be conflicting
Code:
#NoEnv
; CONFIGURATION
;
UPDATE_RATE = 10 ; milliseconds
SENSITIVITY = 0.5
INERTIA = 0.95
;
; WIN32 DEFINES
;
; SetWinEventHook Flags
WINEVENT_OUTOFCONTEXT = 0x0000
; Events
EVENT_SYSTEM_SCROLLINGSTART = 0x0012
EVENT_SYSTEM_SCROLLINGEND = 0x0013
; Scrollbar Constants
SB_HORZ = 0
SB_VERT = 1
GuiClose:
ExitApp
UpdateScrollBars(GuiNum, GuiWidth, GuiHeight)
{
Global THIS_IS_SCROLL_TOKEN_LIT
static SIF_RANGE=0x1, SIF_PAGE=0x2, SIF_DISABLENOSCROLL=0x8, SB_HORZ=0, SB_VERT=1
Gui, %GuiNum%:Default
Gui, +LastFound
; Calculate scrolling area.
Left := Top := 9999
Right := Bottom := 0
WinGet, ControlList, ControlList
Loop, Parse, ControlList, `n
{
GuiControlGet, c, Pos, %A_LoopField%
if (cX < Left)
Left := cX
if (cY < Top)
Top := cY
if (cX + cW > Right)
Right := cX + cW
if (cY + cH > Bottom)
Bottom := cY + cH
}
Left -= 8
Top -= 8
Right += 8
Bottom += 8
ScrollWidth := Right-Left
ScrollHeight := Bottom-Top
; Initialize SCROLLINFO.
VarSetCapacity(si, 28, 0)
NumPut(28, si) ; cbSize
NumPut(SIF_RANGE | SIF_PAGE, si, 4) ; fMask
; Update horizontal scroll bar.
NumPut(ScrollWidth, si, 12) ; nMax
NumPut(GuiWidth, si, 16) ; nPage
DllCall("SetScrollInfo", "uint", WinExist(), "uint", SB_HORZ, "uint", &si, "int", 1)
THIS_IS_SCROLL_TOKEN_LIT:=WinExist()
; Update vertical scroll bar.
; NumPut(SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL, si, 4) ; fMask
NumPut(ScrollHeight, si, 12) ; nMax
NumPut(GuiHeight, si, 16) ; nPage
DllCall("SetScrollInfo", "uint", WinExist(), "uint", SB_VERT, "uint", &si, "int", 1)
if (Left < 0 && Right < GuiWidth)
x := Abs(Left) > GuiWidth-Right ? GuiWidth-Right : Abs(Left)
if (Top < 0 && Bottom < GuiHeight)
y := Abs(Top) > GuiHeight-Bottom ? GuiHeight-Bottom : Abs(Top)
if (x || y)
DllCall("ScrollWindow", "uint", WinExist(), "int", x, "int", y, "uint", 0, "uint", 0)
}
OnScroll(wParam, lParam, msg, hwnd)
{
static SIF_ALL=0x17, SCROLL_STEP=10
bar := msg=0x115 ; SB_HORZ=0, SB_VERT=1
VarSetCapacity(si, 28, 0)
NumPut(28, si) ; cbSize
NumPut(SIF_ALL, si, 4) ; fMask
if !DllCall("GetScrollInfo", "uint", hwnd, "int", bar, "uint", &si)
return
VarSetCapacity(rect, 16)
DllCall("GetClientRect", "uint", hwnd, "uint", &rect)
new_pos := NumGet(si, 20) ; nPos
action := wParam & 0xFFFF
if action = 0 ; SB_LINEUP
new_pos -= SCROLL_STEP
else if action = 1 ; SB_LINEDOWN
new_pos += SCROLL_STEP
else if action = 2 ; SB_PAGEUP
new_pos -= NumGet(rect, 12, "int") - SCROLL_STEP
else if action = 3 ; SB_PAGEDOWN
new_pos += NumGet(rect, 12, "int") - SCROLL_STEP
else if (action = 5 || action = 4) ; SB_THUMBTRACK
new_pos := wParam>>16 ; nTrackPos
else if action = 6 ; SB_TOP
new_pos := NumGet(si, 8, "int") ; nMin
else if action = 7 ; SB_BOTTOM
new_pos := NumGet(si, 12, "int") ; nMax
else
return
min := NumGet(si, 8, "int") ; nMin
max := NumGet(si, 12, "int") - NumGet(si, 16) ; nMax-nPage
new_pos := new_pos > max ? max : new_pos
new_pos := new_pos < min ? min : new_pos
old_pos := NumGet(si, 20, "int") ; nPos
x := y := 0
if bar = 0 ; SB_HORZ
x := old_pos-new_pos
else
y := old_pos-new_pos
; Scroll contents of window and invalidate uncovered area.
DllCall("ScrollWindow", "uint", hwnd, "int", x, "int", y, "uint", 0, "uint", 0)
; Update scroll bar.
NumPut(new_pos, si, 20, "int") ; nPos
DllCall("SetScrollInfo", "uint", hwnd, "int", bar, "uint", &si, "int", 1)
}
WheelUp::
WheelDown::
+WheelUp::
+WheelDown::
Up::
Down::
; SB_LINEDOWN=1, SB_LINEUP=0, WM_HSCROLL=0x114, WM_VSCROLL=0x115
OnScroll(InStr(A_ThisHotkey,"Down") ? 1 : 0, 0, GetKeyState("Shift") ? 0x114 : 0x115, WinExist())
return
CleanupAndExit:
; May not be necessary; but for good measure...
if hScrollHook
DllCall("UnhookWinEvent", "uint", hScrollHook)
ExitApp
ContinueScroll:
Scroll_Speed *= INERTIA
; Continue until
; the scroll bar slows to a stop,
; the window is closed,
; or something else moves the scroll bar.
if (Abs(Scroll_Speed)>0.01
&& GetAbstractScrollInfo(Scroll_Container, Scroll_Type, Scroll_Pos_Int)
&& Scroll_Pos_Int = Last_Pos)
{
; Apply momentum.
Scroll_Pos += Scroll_Speed
; Check if it hit the end.
if (Scroll_Pos < Scroll_Min)
Scroll_Pos := Scroll_Min
if (Scroll_Pos > Scroll_Max)
Scroll_Pos := Scroll_Max
; If it has come to a stop, stop the timer.
if (Scroll_Pos = Last_Pos) {
SetTimer, ContinueScroll, Off
return
}
; Move scroll bar.
if SetAbstractScrollPos(Scroll_Container, Scroll_Type, Round(Scroll_Pos))
{ ; Update position (to detect if something else moves the bar.)
GetAbstractScrollInfo(Scroll_Container, Scroll_Type, Last_Pos)
return
}
}
SetTimer, ContinueScroll, Off
gosub ReleaseScrollContainerIfNecessary
return
TrackScrollBar:
; Update scroll position.
if GetAbstractScrollInfo(Scroll_Container, Scroll_Type, Scroll_Pos)
{ ; Recalculate velocity.
Scroll_Speed := Scroll_Speed*SpeedA + (Scroll_Pos-Last_Pos)*SENSITIVITY
Last_Pos := Scroll_Pos
}
else
{ ; Error: maybe the window closed?
SetTimer, TrackScrollBar, Off
gosub ReleaseScrollContainerIfNecessary
}
return
ReleaseScrollContainerIfNecessary:
if Scroll_Type in scrollbarHThumb,scrollbarVThumb
COM_Release(Scroll_Container)
Scroll_Container = 0
return
[Moderator's note: Edited code to enable word-wrap in several places.]