1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
;; Plan 9-like scrollbar for Windows XP ---------------------------------------
;; The following rules apply:
;; * Press/hold left mouse button to scroll down.
;; * Press/hold right mouse button to scroll up.
;; * The closer to the top of the scrollbar, the slower the speed.
;; * The closer to the bottom of the scrollbar, the faster the speed.
;; The scrolling is achieved by simulating the mouse wheel.
;; Windows without mousewheel support do not work.
;; To use the scrollbar normally, hold any modifier key while clicking the
;; mouse. Ctrl works well, as Ctrl-clicking a scrollbar does nothing special.
;; -> init
GroupAdd, ScrollbarExceptions, ahk_class Shell_TrayWnd
GroupAdd, ScrollbarExceptions, ahk_class #32768
;; -> body
#If (ScrollbarClip or WinActive("ahk_class MozillaWindowClass")) and (ScrollbarCurrent := CurrentScrollbar())
LButton::
MouseGetPos,, my
s := ScrollbarCurrent
r := ceil((my - s.a) / (s.b - s.a) * 10)
ScrollbarAmount := r
if (WinActive("ahk_class PuTTY"))
ScrollbarDown = ^{PgDn}
else
ScrollbarDown = {WheelDown}
ScrollbarNew := true
if (not ScrollbarScrolling)
SetTimer, ScrollbarScroll, 0
return
RButton::
MouseGetPos,, my
s := ScrollbarCurrent
r := ceil((my - s.a) / (s.b - s.a) * 10)
ScrollbarAmount := -r
if (WinActive("ahk_class PuTTY"))
ScrollbarUp = ^{PgUp}
else
ScrollbarUp = {WheelUp}
ScrollbarNew := true
if (not ScrollbarScrolling)
SetTimer, ScrollbarScroll, 0
return
#If
<^>!§::SendInput, {Text}§
§::
global ScrollbarClip
DllCall("ClipCursor", "Ptr", &0)
WinGetPos, x,, w,, A
MouseGetPos, mx, my
s := CurrentScrollbar(w - 12, my)
ScrollbarClip := !ScrollbarClip
if (not ScrollbarClip or not s)
return
WinGetPos, x, y
VarSetCapacity(r, 12, 0)
NumPut(x + s.aa + 6, &r + 0)
NumPut(y + s.a + 1, &r + 4)
NumPut(x + s.bb + 6, &r + 8)
NumPut(y + s.b, &r + 12)
DllCall("ClipCursor", "UInt", &R)
r = ""
return
;; -> library
ScrollbarScroll:
SetTimer, ScrollbarScroll, Off
ScrollbarScrolling := true
ScrollbarNew := false
i := 0
j := abs(ScrollbarAmount)
while (i < j or GetKeyState(ScrollbarAmount > 0 ? "LButton" : "RButton", "P"))
{
i += 1
if (ScrollbarNew)
{
i := 0
j := abs(ScrollbarAmount)
ScrollbarNew := false
}
MouseGetPos,, my
s := ScrollbarCurrent
if (my < s.a)
r := 1
else
r := ceil((my - s.a) / (s.b - s.a) * 10)
ScrollbarAmount := ScrollbarAmount > 0 ? r : -r
if (ScrollbarAmount > 0)
SendInput, %ScrollbarDown%
else
SendInput, %ScrollbarUp%
Sleep, % 100 / abs(ScrollbarAmount)
if (not (i < j or GetKeyState(ScrollbarAmount > 0 ? "LButton" : "RButton", "P")))
break
if (i = j)
Sleep, 150
}
ScrollbarScrolling := false
return
CurrentScrollbar(mx = "", my = "")
{
static size := 17
static GA_ROOT := 2
old := A_BatchLines
SetBatchLines, -1
goto begin
end:
SetBatchLines, % A_BatchLines
return false
begin:
;; Because this function is run whenever the left mouse button is pressed, it
;; is important to return false as early as possible.
CoordMode, Mouse, Window
if (mx = "" and my = "")
MouseGetPos, mx, my, hwnd
if (mx = "" and my != "")
MouseGetPos,, my, hwnd
if (mx != "" and my = "")
MouseGetPos, mx,, hwnd
if (mx != "" and my != "")
MouseGetPos,,, hwnd
WinGet, id, id, ahk_id %hwnd% ahk_group ScrollbarExceptions
if (hwnd = id)
goto end
if (not ScrollbarScrolling and hwnd != WinActive("A"))
goto end
tmp := A_CoordModePixel
CoordMode, Pixel, Window
ImageSearch,, wy, % mx - size, % my - size, % mx + size, % my + size, whitesection.bmp
ImageSearch,, by, % mx - size, % my - size, % mx + size, % my + size, *50 bluesection.bmp
if (wy = "" and by = "")
goto end
WinGetPos,,,, h, A
quit := false
if (my > h / 2)
{
gosub ScrollbarFindDownBelow
if (quit)
goto end
gosub ScrollbarFindUpAbove
if (quit)
goto end
} else {
gosub ScrollbarFindUpAbove
if (quit)
goto end
gosub ScrollbarFindDownBelow
if (quit)
goto end
}
goto ScrollbarFindRest
ScrollbarFindUpAbove:
y := 20
Loop
{
ImageSearch, uax, uay, % mx - size, % my - y, % mx + size, % my, arrowup.bmp
y += 20
} until (uay != "" or my - y <= 0)
if (uay = "")
{
CoordMode, Pixel, % tmp
quit := true
}
return
ScrollbarFindDownBelow:
ImageSearch, dbx, dby, % mx - size, % my, % mx + size, % h, arrowdown.bmp
if (dby = "")
{
CoordMode, Pixel, % tmp
quit := true
}
return
ScrollbarFindRest:
y := 20
; Find down arrow above
Loop
{
ImageSearch, dax, day, % mx - size, 0, % mx + size, % h, arrowdown.bmp ; above
y += 20
} until (day != "" or my - y <= 0)
; Find up arrow below
ImageSearch, ubx, uby, % mx - size, % my, % mx + size, % h, arrowup.bmp
; In the middle of two scrollbars
if (day != "" and uby != "" and day > uay and uby < dby)
{
CoordMode, Pixel, % tmp
goto end
}
CoordMode, Pixel, % tmp
SetBatchLines, % A_BatchLines
return { a: uay + size + 1, b: dby - 1, aa: uax, bb: dbx }
}
|