w-mousekey 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/.editorconfig +9 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc.js +55 -0
  4. package/.jsdoc +25 -0
  5. package/AutoHotkey_2.0.19/AutoHotkey.chm +0 -0
  6. package/AutoHotkey_2.0.19/AutoHotkey32.exe +0 -0
  7. package/AutoHotkey_2.0.19/AutoHotkey64.exe +0 -0
  8. package/AutoHotkey_2.0.19/Install.cmd +2 -0
  9. package/AutoHotkey_2.0.19/UX/Templates/Minimal for v2.ahk +6 -0
  10. package/AutoHotkey_2.0.19/UX/WindowSpy.ahk +246 -0
  11. package/AutoHotkey_2.0.19/UX/inc/CommandLineToArgs.ahk +12 -0
  12. package/AutoHotkey_2.0.19/UX/inc/CreateAppShortcut.ahk +37 -0
  13. package/AutoHotkey_2.0.19/UX/inc/EnableUIAccess.ahk +246 -0
  14. package/AutoHotkey_2.0.19/UX/inc/GetGitHubReleaseAssetURL.ahk +26 -0
  15. package/AutoHotkey_2.0.19/UX/inc/HashFile.ahk +96 -0
  16. package/AutoHotkey_2.0.19/UX/inc/README.txt +3 -0
  17. package/AutoHotkey_2.0.19/UX/inc/ShellRun.ahk +7 -0
  18. package/AutoHotkey_2.0.19/UX/inc/bounce-v1.ahk +3 -0
  19. package/AutoHotkey_2.0.19/UX/inc/common.ahk +21 -0
  20. package/AutoHotkey_2.0.19/UX/inc/config.ahk +13 -0
  21. package/AutoHotkey_2.0.19/UX/inc/identify.ahk +29 -0
  22. package/AutoHotkey_2.0.19/UX/inc/identify_regex.ahk +4 -0
  23. package/AutoHotkey_2.0.19/UX/inc/launcher-common.ahk +78 -0
  24. package/AutoHotkey_2.0.19/UX/inc/spy.ico +0 -0
  25. package/AutoHotkey_2.0.19/UX/inc/ui-base.ahk +129 -0
  26. package/AutoHotkey_2.0.19/UX/install-ahk2exe.ahk +53 -0
  27. package/AutoHotkey_2.0.19/UX/install-version.ahk +109 -0
  28. package/AutoHotkey_2.0.19/UX/install.ahk +1056 -0
  29. package/AutoHotkey_2.0.19/UX/launcher.ahk +430 -0
  30. package/AutoHotkey_2.0.19/UX/reload-v1.ahk +22 -0
  31. package/AutoHotkey_2.0.19/UX/reset-assoc.ahk +38 -0
  32. package/AutoHotkey_2.0.19/UX/ui-dash.ahk +200 -0
  33. package/AutoHotkey_2.0.19/UX/ui-editor.ahk +238 -0
  34. package/AutoHotkey_2.0.19/UX/ui-launcherconfig.ahk +195 -0
  35. package/AutoHotkey_2.0.19/UX/ui-newscript.ahk +296 -0
  36. package/AutoHotkey_2.0.19/UX/ui-setup.ahk +175 -0
  37. package/AutoHotkey_2.0.19/UX/ui-uninstall.ahk +68 -0
  38. package/AutoHotkey_2.0.19/WindowSpy.ahk +2 -0
  39. package/AutoHotkey_2.0.19/license.txt +351 -0
  40. package/AutoHotkey_2.0.19/zclick.ahk +5 -0
  41. package/AutoHotkey_2.0.19/zrun_click.bat +2 -0
  42. package/AutoHotkey_2.0.19/zrun_send.bat +2 -0
  43. package/AutoHotkey_2.0.19/zsend.ahk +4 -0
  44. package/LICENSE +21 -0
  45. package/README.md +23 -0
  46. package/SECURITY.md +5 -0
  47. package/_tmp/view.all.png +0 -0
  48. package/_tmp/view.det.png +0 -0
  49. package/babel.config.js +16 -0
  50. package/dist/action.umd.js +32 -0
  51. package/dist/action.umd.js.map +1 -0
  52. package/dist/ck-pic.umd.js +7 -0
  53. package/dist/ck-pic.umd.js.map +1 -0
  54. package/dist/compare.umd.js +7 -0
  55. package/dist/compare.umd.js.map +1 -0
  56. package/dist/get-settings.umd.js +7 -0
  57. package/dist/get-settings.umd.js.map +1 -0
  58. package/dist/mousekey.umd.js +7 -0
  59. package/dist/mousekey.umd.js.map +1 -0
  60. package/dist/screen.umd.js +7 -0
  61. package/dist/screen.umd.js.map +1 -0
  62. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  63. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  64. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  65. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  66. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  67. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  68. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  69. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  70. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  71. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  72. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  73. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  74. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  75. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  76. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  77. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  78. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  79. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  80. package/docs/index.html +84 -0
  81. package/docs/scripts/collapse.js +39 -0
  82. package/docs/scripts/commonNav.js +28 -0
  83. package/docs/scripts/linenumber.js +25 -0
  84. package/docs/scripts/nav.js +12 -0
  85. package/docs/scripts/polyfill.js +4 -0
  86. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  87. package/docs/scripts/prettify/lang-css.js +2 -0
  88. package/docs/scripts/prettify/prettify.js +28 -0
  89. package/docs/scripts/search.js +99 -0
  90. package/docs/styles/jsdoc.css +776 -0
  91. package/docs/styles/prettify.css +80 -0
  92. package/g.mjs +46 -0
  93. package/g.test_opencv.mjs +36 -0
  94. package/package.json +41 -0
  95. package/pic/view.png +0 -0
  96. package/script.txt +17 -0
  97. package/src/action.mjs +132 -0
  98. package/src/ckPic.mjs +95 -0
  99. package/src/compare.mjs +201 -0
  100. package/src/getSettings.mjs +17 -0
  101. package/src/mousekey.mjs +95 -0
  102. package/src/screen.mjs +62 -0
  103. package/test/WMousekey.test.mjs +11 -0
  104. package/toolg/addVersion.mjs +4 -0
  105. package/toolg/cleanFolder.mjs +4 -0
  106. package/toolg/gDistRollup.mjs +33 -0
  107. package/toolg/modifyReadme.mjs +4 -0
@@ -0,0 +1,296 @@
1
+ #requires AutoHotkey v2.0
2
+
3
+ #NoTrayIcon
4
+ #SingleInstance Off
5
+
6
+ #include inc\common.ahk
7
+ #include inc\ui-base.ahk
8
+
9
+ class NewScriptGui extends AutoHotkeyUxGui {
10
+ __new(path:="") {
11
+ super.__new("New Script")
12
+
13
+ SplitPath path,, &dir,, &name
14
+ if this.ExplorerHwnd := WinActive("ahk_class CabinetWClass") {
15
+ this.Opt '+Owner' this.ExplorerHwnd
16
+ if dir = ""
17
+ dir := GetPathForExplorerWindow(this.ExplorerHwnd)
18
+ }
19
+ if dir = ""
20
+ dir := ConfigRead('New', 'DefaultDir', A_MyDocuments "\AutoHotkey")
21
+
22
+ name := this.AddEdit('vName w272', name != "New AutoHotkey Script" ? name : "")
23
+ static EM_SETCUEBANNER := 0x1501
24
+ SendMessage(EM_SETCUEBANNER, true, StrPtr("Untitled"), name)
25
+
26
+ static IconSize := SysGet(49) ; SM_CXSMICON
27
+
28
+ static BrowseIcon := LoadPicture("imageres.dll", 'Icon-1025 w' IconSize, &imgtype)
29
+ this.AddIconButton('vBrowse x+0 yp-1 w28 hp+2', BrowseIcon, "&Browse")
30
+ .OnEvent('Click', 'Browse')
31
+
32
+ this.AddEdit('vDir xm w300 r1 ReadOnly -TabStop', dir)
33
+
34
+ static LVS_SHOWSELALWAYS := 8 ; Seems to have the opposite effect with Explorer theme, at least on Windows 11.
35
+ lv := this.AddListMenu("vLV xm w300 -" LVS_SHOWSELALWAYS, ["Name", "Desc", "Path", "Exec"])
36
+ lv.OnEvent('DoubleClick', 'DoubleClicked')
37
+ lv.OnEvent('ContextMenu', 'RightClicked')
38
+
39
+ deft := GetDefaultTemplate()
40
+ lv.Add(deft = "" ? 'Select Focus' : '', "Empty", "Clean slate")
41
+ for ,t in this.Templates := GetScriptTemplates() {
42
+ if ConfigRead('New\HideTemplate', t.name, false)
43
+ continue
44
+ lv.Add(deft = t.name ? 'Select Focus' : '', t.name, t.desc)
45
+ }
46
+
47
+ lv.AutoSize(8)
48
+ lv.GetPos(&x, &y, &w, &h)
49
+
50
+ static DefaultsIcon := LoadPicture("imageres.dll", 'Icon-114 w' IconSize, &imgtype)
51
+ this.AddIconButton('vDefaults r1 w28 xm y' y + h + this.MarginY, DefaultsIcon, "&Defaults")
52
+ .OnEvent('Click', 'ChangeDefaults')
53
+
54
+ this.AddButton('vCreate yp w75 x150', "&Create").OnEvent('Click', 'Confirm')
55
+ this.AddButton('vEdit Default yp wp xm+225', "&Edit").OnEvent('Click', 'Confirm')
56
+ if ConfigRead('New', 'DefaultButton', 'Edit') = 'Create'
57
+ this['Create'].Opt('Default')
58
+
59
+ if this.ExplorerHwnd {
60
+ this.Show('AutoSize Hide')
61
+ WinGetPos(,, &gw, &gh, this)
62
+ WinGetPos(&x, &y, &ew, &eh)
63
+ WinMove(x + (ew - gw) // 2, y + (eh - gh) // 2,,, this)
64
+ }
65
+ }
66
+
67
+ static __new() {
68
+ OnMessage(WM_KEYDOWN := 0x100, KeyDown)
69
+ KeyDown(wParam, lParam, nmsg, hwnd) {
70
+ static VK_UP := 0x26
71
+ static VK_DOWN := 0x28
72
+ if !(wParam = VK_UP || wParam = VK_DOWN)
73
+ return
74
+ gc := GuiCtrlFromHwnd(hwnd)
75
+ if gc.Gui is NewScriptGui && gc is Gui.Edit {
76
+ PostMessage nmsg, wParam, lParam, gc.Gui['LV']
77
+ return true
78
+ }
79
+ }
80
+ }
81
+
82
+ Browse(*) {
83
+ path := this.FileSelect('S', this['Dir'].Value "\" this['Name'].Value, this.Title, "Script Files (*.ahk)")
84
+ if path = ""
85
+ return
86
+ SplitPath path, &name, &dir
87
+ this['Name'].Value := name
88
+ this['Dir'].Value := dir
89
+ this['LV'].Focus()
90
+ }
91
+
92
+ ChangeDefaults(btn, *) {
93
+ lv := this["LV"]
94
+
95
+ m := Menu()
96
+ m.Add "Default to Create", setDefBtn, "Radio"
97
+ m.Add "Default to Edit", setDefBtn, "Radio"
98
+ m.Add "Stay open", toggleStayOpen
99
+ if stayOpen := ConfigRead('New', 'StayOpen', false)
100
+ m.Check "Stay open"
101
+ m.Add
102
+ m.Add "Set folder as default", (*) => SetDefaultDir(this['Dir'].Value)
103
+ if this['Dir'].Value = GetDefaultDir()
104
+ m.Check "Set folder as default"
105
+ m.Add "Open templates folder", (*) => OpenTemplatesFolder()
106
+
107
+ static DM_GETDEFID := 0x400
108
+ m.Check (1 + (SendMessage(DM_GETDEFID,,, this) & 0xFFFF = DllCall('GetDlgCtrlID', 'ptr', this['Edit'].Hwnd))) "&"
109
+
110
+ this.Opt "-DPIScale"
111
+ btn.GetPos &x, &y, &w, &h
112
+ ;btn.Focus ; This would also apply the "default" style, which would not revert correctly.
113
+ ControlFocus btn
114
+ m.Show x, y + h
115
+
116
+ setDefBtn(itemname, itempos, *) {
117
+ itemname := SubStr(itemname, 12)
118
+ this[itemname].Opt('Default')
119
+ ConfigWrite(itemname, 'New', 'DefaultButton')
120
+ }
121
+ toggleStayOpen(*) {
122
+ ConfigWrite(stayOpen := !stayOpen, 'New', 'StayOpen')
123
+ }
124
+ }
125
+
126
+ Confirm(btn, *) {
127
+ lv := this['LV']
128
+ if !index := lv.GetNext()
129
+ return MsgBox("You need to select a template first.",, 'icon!')
130
+ t := index = 1 ? '' : this.Templates[lv.GetText(index)]
131
+
132
+ stayOpen := GetKeyState('Ctrl') || ConfigRead('New', 'StayOpen', false)
133
+
134
+ DirCreate dir := this['Dir'].Value
135
+ basename := this['Name'].Value
136
+ (basename != '') || basename := "Untitled"
137
+ SubStr(basename, -4) = ".ahk" && basename := SubStr(basename, 1, -4)
138
+ newPath := dir "\" basename ".ahk"
139
+ while FileExist(newPath)
140
+ newPath := dir "\" basename "-" A_Index ".ahk"
141
+
142
+ if t && t.execute
143
+ RunWait Format('"{1}" "{2}" {3}', t.path, newPath, btn.Name), dir
144
+ else {
145
+ code := t = '' ? '' : FileRead(t.path)
146
+ code := RegExReplace(code, 'si)/\*\s+\[NewScriptTemplate\].*\*/\R?')
147
+ FileOpen(newPath, 'w', 'UTF-8').Write(code)
148
+ }
149
+
150
+ if this.ExplorerHwnd && (xp := GetExplorerByHwnd(this.ExplorerHwnd))
151
+ || dir = A_Desktop && (xp := GetExplorerForDesktop()) {
152
+ SplitPath newPath, &basename
153
+ SelectExplorerItem xp, basename
154
+ }
155
+ else if btn.Name != 'Edit'
156
+ Run 'explorer /select,"' newPath '"'
157
+
158
+ if btn.Name = 'Edit'
159
+ Run 'edit "' newPath '"'
160
+
161
+ if !stayOpen
162
+ this.Hide
163
+ }
164
+
165
+ RightClicked(lv, item, isRClick, x, y) {
166
+ if !item
167
+ return
168
+ t := item > 1 ? this.Templates[lv.GetText(item)] : {name: ''}
169
+
170
+ m := Menu()
171
+ if item > 1 {
172
+ m.Add "&Edit template", (*) => EditTemplate(t)
173
+ m.Add "&Hide template", hideTemplate
174
+ }
175
+ m.Add "Set as &default", (*) => SetDefaultTemplate(t.name)
176
+ if t.name = GetDefaultTemplate()
177
+ m.Check "Set as &default"
178
+ m.Show x, y
179
+
180
+ hideTemplate(*) {
181
+ ConfigWrite(true, 'New\HideTemplate', t.name)
182
+ lv.Delete item
183
+ static LVM_ARRANGE := 0x1016
184
+ SendMessage LVM_ARRANGE,,, lv ; Fill in any gap left by item (in Tile view).
185
+ }
186
+ }
187
+
188
+ DoubleClicked(lv, row) {
189
+ if row
190
+ this.Confirm(this.GetDefaultButton())
191
+ }
192
+
193
+ GetDefaultButton() {
194
+ static DM_GETDEFID := 0x400
195
+ hwnd := DllCall("GetDlgItem", "ptr", this.hwnd, "int", SendMessage(DM_GETDEFID,,, this) & 0xFFFF, "uint")
196
+ return hwnd && this[hwnd]
197
+ }
198
+ }
199
+
200
+ class NewScriptTemplate {
201
+ __new(path, name:="", description:="") {
202
+ this.path := path
203
+ if name = ""
204
+ SplitPath path,,,, &name
205
+ this.name := name
206
+ this.desc := IniRead(path, 'NewScriptTemplate', 'Description', description)
207
+ this.execute := false
208
+ switch IniRead(path, 'NewScriptTemplate', 'Execute', false) {
209
+ case true, "true": this.execute := true
210
+ }
211
+ }
212
+ }
213
+
214
+ OpenTemplatesFolder() {
215
+ dir := GetUserTemplateFolder(true)
216
+ if dir != ""
217
+ Run dir "\"
218
+ }
219
+
220
+ GetUserTemplateFolder(checkAndPrompt:=false) {
221
+ static dir := A_MyDocuments "\AutoHotkey\Templates"
222
+ if checkAndPrompt && !FileExist(dir) {
223
+ if MsgBox("User-created templates should be placed in the following folder, "
224
+ "which does not yet exist:`n`n" dir "`n`nCreate it now?",, "YesNo") = "No"
225
+ return
226
+ DirCreate dir
227
+ }
228
+ return dir
229
+ }
230
+
231
+ EditTemplate(t) {
232
+ dir := GetUserTemplateFolder(true)
233
+ if dir = ""
234
+ return
235
+ userPath := dir "\" t.name ".ahk"
236
+ if !FileExist(userPath) {
237
+ FileCopy t.path, userPath
238
+ t.path := userPath
239
+ }
240
+ Run 'edit "' userPath '"'
241
+ }
242
+
243
+ GetScriptTemplates() {
244
+ tmap := Map(), tmap.CaseSense := "off"
245
+ sources := [
246
+ A_ScriptDir "\Templates",
247
+ GetUserTemplateFolder()
248
+ ]
249
+ if FileExist(t := A_WinDir '\ShellNew\Template.ahk')
250
+ tmap["Legacy"] := NewScriptTemplate(t, "Legacy", "From " A_WinDir "\ShellNew")
251
+ for source in sources {
252
+ loop files source "\*.ahk" {
253
+ t := NewScriptTemplate(A_LoopFilePath)
254
+ tmap[t.name] := t
255
+ }
256
+ }
257
+ return tmap
258
+ }
259
+
260
+ SetDefaultTemplate(t) => ConfigWrite(t = "Empty" ? "" : t, 'New', 'DefaultTemplate')
261
+ GetDefaultTemplate() => ConfigRead('New', 'DefaultTemplate', "")
262
+
263
+ SetDefaultDir(dir) => ConfigWrite(dir, 'New', 'DefaultDir')
264
+ GetDefaultDir() => ConfigRead('New', 'DefaultDir', A_MyDocuments "\AutoHotkey")
265
+
266
+ SelectExplorerItem(e, name) {
267
+ sfv := e.Document
268
+ if fi := sfv.Folder.ParseName(name)
269
+ sfv.SelectItem(fi, 1|4|8|16)
270
+ return e
271
+ }
272
+
273
+ GetExplorerByHwnd(hwnd) {
274
+ for window in ComObject("Shell.Application").Windows
275
+ if window.hwnd = hwnd
276
+ return window
277
+ }
278
+
279
+ GetExplorerForDesktop() {
280
+ hwndBuf := Buffer(4, 0), hwndRef := ComValue(0x4003, hwndBuf.Ptr)
281
+ return ComObject("Shell.Application").Windows.FindWindowSW(0, "", 8, hwndRef, 1)
282
+ }
283
+
284
+ GetPathForExplorerWindow(hwnd) {
285
+ try return GetExplorerByHwnd(hwnd).Document.Folder.Self.Path
286
+ }
287
+
288
+ GetExplorerByPath(path) {
289
+ for window in ComObject("Shell.Application").Windows
290
+ try if window.Document.Folder.Self.Path = path
291
+ return window
292
+ return ""
293
+ }
294
+
295
+ if A_ScriptFullPath = A_LineFile
296
+ NewScriptGui.Show(A_Args.Length ? A_Args[1] : "")
@@ -0,0 +1,175 @@
1
+ ; This script shows the initial setup GUI.
2
+ ; It is not intended for use after installation.
3
+ #requires AutoHotkey v2.0
4
+
5
+ #NoTrayIcon
6
+ #SingleInstance Force
7
+
8
+ #include inc\ui-base.ahk
9
+
10
+ A_ScriptName := "AutoHotkey Setup"
11
+ SetRegView 64
12
+ InstallGui.Show()
13
+
14
+ class InstallGui extends AutoHotkeyUxGui {
15
+ __new() {
16
+ super.__new(A_ScriptName, '-MinimizeBox -MaximizeBox')
17
+
18
+ DllCall('uxtheme\SetWindowThemeAttribute', 'ptr', this.hwnd, 'int', 1 ; WTA_NONCLIENT
19
+ , 'int64*', 3 | (3<<32), 'int', 8) ; WTNCA_NODRAWCAPTION=1, WTNCA_NODRAWICON=2
20
+
21
+ static TitleBack := 'BackgroundWhite'
22
+ static TitleFore := 'c3F627F'
23
+ static TotalWidth := 350
24
+ this.AddText('x0 y0 w' TotalWidth ' h84 ' TitleBack)
25
+ this.AddPicture('x32 y16 w32 h32 ' TitleBack, A_AhkPath)
26
+ this.SetFont('s12', 'Segoe UI')
27
+ this.AddText('x+20 yp+4 ' TitleFore ' ' TitleBack, "AutoHotkey v" A_AhkVersion)
28
+ this.SetFont('s9')
29
+
30
+ ; SS_SUNKEN := 0x1000 ; 4096
31
+ this.AddText('x-4 y84 w' TotalWidth+4 ' h188 0x1000 -Background')
32
+
33
+ this.AddText('xm yp+16', 'Install &to:')
34
+ dirEdit := this.AddEdit('vInstallDir w' TotalWidth - (2 * this.MarginX) - 88)
35
+ this.AddButton('vBrowseButton w80 x+8 yp-1', '&Browse')
36
+ .OnEvent('Click', 'Browse')
37
+
38
+ rect := Buffer(16, 0)
39
+ DllCall('GetClientRect', 'ptr', dirEdit.hwnd, 'ptr', rect)
40
+ NumPut('int', 4, 'int', 2, rect)
41
+ ; DllCall('InflateRect', 'ptr', rect, 'int', 0, 'int', )
42
+ EM_SETRECT := 0xB3 ; 179
43
+ SendMessage 0xB3, 0, rect.ptr, dirEdit
44
+
45
+ this.AddGroupBox('xm y+0 w' TotalWidth - (2 * this.MarginX) ' h44')
46
+ this.AddText('xp+8 yp+16', "Install mode:")
47
+ this.AddRadio('vModeAll x+m yp Checked', "&All users")
48
+ .OnEvent('Click', 'ModeChange')
49
+ this.AddRadio('vModeUser x+4', "&Current user")
50
+ .OnEvent('Click', 'ModeChange')
51
+ this.AddRadio('vModePortable x+4 Disabled', "Portable")
52
+ .OnEvent('Click', 'ModeChange')
53
+
54
+ this.AddButton('vInstallButton x' (TotalWidth - 80) // 2 ' w80 y+36 Default', "&Install")
55
+ .OnEvent('Click', 'Install')
56
+
57
+ this.ModeChange()
58
+
59
+ this.MarginY := -1
60
+ this.Show('Hide w' TotalWidth)
61
+ this['InstallButton'].Focus()
62
+ }
63
+
64
+ Browse(*) {
65
+ if ControlGetStyle(this['InstallDir']) & 0x800 { ; ES_READONLY
66
+ rootKey := this['ModeAll'].Value ? 'HKLM' : 'HKCU'
67
+ message := "Changing the installation directory is not recommended."
68
+ if InStr(RegRead(rootKey '\Software\AutoHotkey', 'Version', ''), '1.') = 1
69
+ message .= "`n`nThis installation package is designed to allow both v1 and v2 to be associated with .ahk files, but only if they are installed in the same directory."
70
+ message .= "`n`nExisting files will not be moved."
71
+ if MsgBox(message,, "OKCancel Icon!") != "OK"
72
+ return
73
+ this['InstallDir'].Opt('-ReadOnly')
74
+ }
75
+ dir := this.FileSelect('D', this['InstallDir'].Value '\', "Select installation directory")
76
+ if dir != '' {
77
+ this['InstallDir'].Value := dir
78
+ this.InstallDirChange()
79
+ }
80
+ }
81
+
82
+ ModeChange(p*) {
83
+ if !this.CheckAlreadyInstalled(p.Length = 0, true) {
84
+ ; Ensure InstallDir makes sense for the new mode
85
+ installDir := this['InstallDir'].Value
86
+ if this['ModeAll'].Value {
87
+ if installDir = '' || installDir = InstallUtil.DefaultUserDir
88
+ this['InstallDir'].Value := InstallUtil.DefaultAllDir, this['InstallDir'].Opt('-ReadOnly')
89
+ } else
90
+ if installDir = '' || IsInProgramFiles(installDir)
91
+ this['InstallDir'].Value := InstallUtil.DefaultUserDir, this['InstallDir'].Opt('-ReadOnly')
92
+ }
93
+ this.UpdateShield()
94
+ }
95
+
96
+ InstallDirChange(*) {
97
+ this.UpdateShield()
98
+ }
99
+
100
+ UpdateShield() {
101
+ requireAdmin := this['ModeAll'].Value && !A_IsAdmin
102
+ SendMessage 0x160C, 0, requireAdmin, this['InstallButton'] ; BCM_SETSHIELD
103
+ }
104
+
105
+ CheckAlreadyInstalled(setMode:=false, setDir:=false) {
106
+ for rootKey in setMode ? ['HKCU', 'HKLM'] : [this['ModeAll'].Value ? 'HKLM' : 'HKCU'] {
107
+ dir := RegRead(rootKey '\Software\AutoHotkey', 'InstallDir', '')
108
+ if dir != '' {
109
+ if setDir {
110
+ this['InstallDir'].Value := dir
111
+ this['InstallDir'].Opt('+ReadOnly')
112
+ }
113
+ if setMode
114
+ this[A_Index = 1 ? 'ModeUser' : 'ModeAll'].Value := true
115
+ return dir
116
+ }
117
+ }
118
+ return ''
119
+ }
120
+
121
+ Install(*) {
122
+ problem := ''
123
+ requireAdmin := this['ModeAll'].Value
124
+ installDir := this['InstallDir'].Value
125
+ buf := Buffer(260*2)
126
+ n := DllCall('GetFullPathName', 'str', installDir, 'uint', 260, 'ptr', buf, 'ptr', 0)
127
+ if !n || n > 259 {
128
+ MsgBox "Please enter a valid path.",, 'Icon!'
129
+ return
130
+ }
131
+ fullPath := StrGet(buf)
132
+ if installDir != fullPath {
133
+ problem .= '"' installDir '" resolves to "' fullPath '".`n`n'
134
+ installDir := fullPath
135
+ }
136
+ dir := this.CheckAlreadyInstalled()
137
+ if dir && dir != installDir
138
+ problem .= 'The existing installation in "' dir '" will not be moved or integrated with the new installation.`n`n'
139
+ if requireAdmin && !IsInProgramFiles(installDir) && dir != installDir
140
+ problem .= 'Enabling UI Access will not be possible because the installation directory is not a sub-directory of Program Files. Without UI Access, non-elevated scripts cannot interact with windows of elevated programs.`n`n'
141
+ if problem && MsgBox(problem,, 'OKCancel Default2 Icon!') = 'Cancel'
142
+ return
143
+ if A_IsCompiled && IsSet(Installation)
144
+ cmd := Format('"{1}" /to "{2}"', A_ScriptFullPath, installDir)
145
+ else
146
+ cmd := Format('"{1}" /script "{2}\install.ahk" /to "{3}"', A_AhkPath, A_ScriptDir, installDir)
147
+ if !requireAdmin
148
+ cmd .= ' /user'
149
+ else if !A_IsAdmin
150
+ cmd := '*RunAs ' cmd
151
+ try
152
+ Run cmd,,, &pid
153
+ catch as e {
154
+ if A_LastError != 1223 ; ERROR_CANCELLED
155
+ MsgBox e.Message "`n`n" e.Extra,, 'IconX'
156
+ } else {
157
+ this['InstallButton'].Enabled := false
158
+ this['InstallButton'].Text := "Installing..."
159
+ ProcessWaitClose pid
160
+ ExitApp
161
+ }
162
+ }
163
+ }
164
+
165
+ class InstallUtil {
166
+ static DefaultAllDir := (EnvGet('ProgramW6432') || A_ProgramFiles) '\AutoHotkey'
167
+ static DefaultUserDir := EnvGet('LocalAppData') '\Programs\AutoHotkey'
168
+ static DefaultDir := A_IsAdmin ? this.DefaultAllDir : this.DefaultUserDir
169
+ }
170
+
171
+ IsInProgramFiles(path) {
172
+ other := EnvGet(A_PtrSize=8 ? "ProgramFiles(x86)" : "ProgramW6432")
173
+ return InStr(path, A_ProgramFiles "\") = 1
174
+ || other && InStr(path, other "\") = 1
175
+ }
@@ -0,0 +1,68 @@
1
+ ; This script shows a GUI for uninstalling AutoHotkey or specific versions.
2
+ #include inc\bounce-v1.ahk
3
+ /* v1 stops here */
4
+ #requires AutoHotkey v2.0
5
+
6
+ #include inc\ui-base.ahk
7
+ #include install.ahk
8
+
9
+ #NoTrayIcon
10
+ #SingleInstance Force
11
+
12
+ A_ScriptName := "AutoHotkey Setup"
13
+ SetRegView 64
14
+ ModifySetupGui.Show()
15
+
16
+ class ModifySetupGui extends AutoHotkeyUxGui {
17
+ __new() {
18
+ super.__new(A_ScriptName, '-MinimizeBox -MaximizeBox')
19
+
20
+ this.inst := Installation()
21
+ this.inst.ResolveInstallDir()
22
+ versions := this.inst.GetComponents()
23
+
24
+ this.AddText(, "Remove which versions?")
25
+ iv := this.AddListView('vComponents Checked -Hdr R10 w248', ["Version"])
26
+ iv.OnEvent('ItemCheck', 'Checked')
27
+ for v, files in versions
28
+ iv.Add(files.HasProp('superseded') ? 'Check' : '', v)
29
+
30
+ anyChecked := iv.GetNext(0, 'C')
31
+ this.AddButton('vRemoveAll w120 ' (anyChecked ? '' : 'Default'), "Remove &all")
32
+ .OnEvent('Click', 'ClickedRemove')
33
+ this.AddButton('vRemove w120 yp ' (anyChecked ? 'Default' : 'Disabled'), "Remove &checked")
34
+ .OnEvent('Click', 'ClickedRemove')
35
+
36
+ if !this.inst.UserInstall && !A_IsAdmin {
37
+ SendMessage 0x160C,, true, 'Button1', this ; BCM_SETSHIELD := 0x160C
38
+ SendMessage 0x160C,, true, 'Button2', this
39
+ }
40
+ }
41
+
42
+ ClickedRemove(btn, *) {
43
+ cmd := ''
44
+ if btn.Name = 'Remove' {
45
+ n := 0, iv := this['Components'], count := 0
46
+ while n := iv.GetNext(n, 'C')
47
+ cmd .= ',' iv.GetText(n), ++count
48
+ if count = iv.GetCount()
49
+ cmd := '' ; All are selected - do a full uninstall
50
+ else
51
+ cmd := ' "' SubStr(cmd, 2) '"'
52
+ }
53
+ cmd := Format('"{1}" "{2}\install.ahk" /uninstall{3}', A_AhkPath, A_ScriptDir, cmd)
54
+ if (!this.inst.UserInstall || A_Args.Length && A_Args[1] = '/elevate') && !A_IsAdmin
55
+ cmd := '*RunAs ' cmd
56
+ try {
57
+ Run cmd
58
+ ExitApp
59
+ }
60
+ catch as e
61
+ if !InStr(e.Message e.Extra, 'cancel')
62
+ throw e
63
+ }
64
+
65
+ Checked(iv, *) {
66
+ this['Remove'].Enabled := iv.GetNext(0, 'C')
67
+ }
68
+ }
@@ -0,0 +1,2 @@
1
+ #Requires AutoHotkey v2.0-beta
2
+ #Include UX\WindowSpy.ahk