-
Notifications
You must be signed in to change notification settings - Fork 72
/
Copy pathclass_Spinner.ahk
113 lines (94 loc) · 3.17 KB
/
class_Spinner.ahk
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
#Include, <Gdip>
#If (!LoadLib = 1)
ExitApp
#If
Class Spinner {
Static ID := 0
Static Pi := 4 * ATan(1)
DotCount := 9
DotSize := 12
Radius := 20
Color:= "000000"
Delay := 250
bClockwise := False
__New(oConfig, hParent := 0) {
If oConfig.HasKey("DotCount")
this.DotCount := oConfig.DotCount
If oConfig.HasKey("DotSize")
this.DotSize := oConfig.DotSize
If oConfig.HasKey("Radius")
this.Radius := oConfig.Radius
If oConfig.HasKey("Color")
this.Color := oConfig.Color
If oConfig.HasKey("Delay")
this.Delay := oConfig.Delay
If oConfig.HasKey("bClockwise")
this.bClockwise := oConfig.bClockwise
If (hParent = 0)
this.Width := A_ScreenWidth, this.Height := A_ScreenHeight
Else {
WinGetPos,,, Width, Height, ahk_id %hParent%
this.Width := Width, this.Height := Height
}
this.MidX := (this.Width // 2) - 10
this.MidY := (this.Height // 2) - 10
this.pToken := Gdip_Startup()
this.hDC := CreateCompatibleDC()
this.hBM := CreateDIBSection(this.Width, this.Height)
this.oBM := SelectObject(this.hDC, this.hBM)
this.pGraphics := Gdip_GraphicsFromHDC(this.hDC)
Gdip_SetSmoothingMode(this.pGraphics, 4)
this.ID := Spinner.ID++
Gui, % "Spinner" this.ID ": New", +AlwaysOnTop +hWndhSpin
Gui, +E0x80020 ; WS_EX_LAYERED | WS_EX_TRANSPARENT (click through)
Gui, +0x40000000 -0x80000000 ; +WS_CHILD -WS_POPUP
DllCall("SetParent", "Ptr", this.hSpin := hSpin, "Ptr", hParent)
this.DOT := [], this.ARGB := [], this.BRUSHES := []
Loop, % this.DotCount {
this.DOT[A_Index, "x"] := this.MidX + this.Radius * Cos(A_Index * 2 * this.Pi / this.DotCount)
this.DOT[A_Index, "y"] := this.MidY + this.Radius * Sin(A_Index * 2 * this.Pi / this.DotCount)
this.ARGB.Push(Format("0x{:x}", A_Index * 255 // this.DotCount) this.Color)
this.BRUSHES.Push(Gdip_BrushCreateSolid(this.ARGB[A_Index]))
}
}
__Delete() {
Gui, % "Spinner" this.ID ": Destroy"
SelectObject(this.hDC, this.oBM)
DeleteObject(this.hBM)
DeleteDC(this.hDC)
Gdip_DeleteGraphics(this.pGraphics)
Loop, % this.DotCount
Gdip_DeleteBrush(this.BRUSHES[A_Index])
Gdip_Shutdown(this.pToken)
}
Call() {
;-----------------------------------------------------------------------
; the timer clears the drawing, the draws all the dots again
; when drawing, each dot gets a new brush every time
; I keep the index for brushes in range with Mod(index, DotCount) + 1
; this.Index is initialized large enough for clockwise direction
;-----------------------------------------------------------------------
If (this.Index++ > 2 * this.DotCount)
this.Index -= this.DotCount
Gdip_GraphicsClear(this.pGraphics)
Sign := this.bClockwise ? -1 : 1
Loop, % This.DotCount {
Gdip_FillEllipse(this.pGraphics
, this.BRUSHES[Mod(this.Index + A_Index * Sign, this.DotCount) + 1]
, this.DOT[A_Index].x, this.DOT[A_Index].y, this.DotSize, this.DotSize)
UpdateLayeredWindow(this.hSpin, this.hDC, 0, 0, this.Width, this.Height)
}
}
Start() {
Gui, % "Spinner" this.ID ": Show", % "NA x0 y0 w" this.Width " h" this.Height
this.Index := this.DotCount
SetTimer, %this%, % this.Delay
this.Call()
}
Close() {
this.__Delete()
}
Stop() {
SetTimer, %this%, Off
}
}