forked from Drugoy/Autohotkey-scripts-.ahk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MasterScript.ahk
2108 lines (1995 loc) · 80 KB
/
MasterScript.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
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* MasterScript.ahk
Version: 4.1
Last time modified: 2016.10.05 14:20
Compatible with AHK: 1.1.24.01.
Summary: a script manager for AHK scripts with bookmarks, autostart and process assistance support.
Description: this script is used for managing other ahk scripts:
- bookmark folders on your disk to have quick access to some scripts;
- bookmark scripts, so you can run/edit them quicker;
- track running processes and get info about them: are they paused? are their hotkeys suspended? are their processes suspended? what are their processIDs? what are their names? what are their locations? - all that is shown on the "Processes" tab;
- control processes of the running ahk scripts from outside: toggle suspend their hotkeys, toggle pause scripts, toggle suspend their processes, kill them, exit them, reload them, kill and re-execute them;
- control tray icons of running scripts: hide/restore them, show tray menu;
- configure autorun list to start scripts together with MasterScript automatically (+ you may choose to hide tray icons of those startup scripts);
- configure "Process Assistant" rules: you may tell the script to assist one process with another. Process Assistant is a very powerful feature that has options to adjust how to assist processes: you may use Process Assistant so that running your game.exe will trigger the script gamehotkeys.ahk which will get closed when you close your game.exe. Or not - it's up to you how to configure your Process Assistant rules.
Thanks to: I've used a lot of pieces of code from scripts/functions/libs written by other people. I am very grateful to so many people, that I just can't name them all.
Script author: Drugoy a.k.a. Drugmix
Contacts: [email protected], [email protected]
https://github.com/Drugoy/Autohotkey-scripts-.ahk/tree/master/ScriptManager.ahk/MasterScript.ahk
http://forum.script-coding.com/viewtopic.php?id=8724
*/
/* TODO:
1. Decide what to do if a bookmarked item (folder or file) or a file related to an autorun or process assistant rule doesn't exist anymore. Should it be listed in the TV/LV? Should it get purged from settings? Should the user be notified? How?
2. It lacks small things like some context menus, 'Edit' button/menuitem for files and for running uncompiled scripts.
3. Add more description comments to functions.
*/
;{ Settings block.
; Path and name of the file name to store script's settings.
settingsPath := A_ScriptDir "\" SubStr(A_ScriptName, 1, StrLen(A_ScriptName) - 4) "_settings.ini"
settings_O := readSettings(settingsPath)
; Specify a value in milliseconds.
settings_O.memoryScanInterval := 1000
; 1 = Make script store info (into the settings file) about it's window's size and position between script's closures. 0 = do not store that info in the settings file.
settings_O.rememberPosAndSize := 1
; 0 = the scripts in autorun will just be checked to made sure they are running. 1 = the scripts in autorun will get executed irregardless of whether they were already running before.
settings_O.forceExecAutostarts := 0
; 1 = use "exit" to end scripts, let them execute their 'OnExit' sub-routine. 0 = use "kill" to end scripts, that just instantly stops them, so scripts won't execute their 'OnExit' subroutines.
settings_O.quitAssistantsNicely := 1
;}
;{ Initialization.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance, Force
; #Warn ; Recommended for catching common errors.
DetectHiddenWindows, On ; Needed for 'pause' and 'suspend' commands, as well as for 'restoreTrayIcon()' function.
OnExit("exitApp")
WMIQueries_O := ComObjGet("winmgmts:"), scriptsSnapshot_AofO := [], procBinder := [], ownPID := DllCall("GetCurrentProcessId"), wParam := 0, oldSettings_O := readSettings(settings_O), activeTab := activeControl := selectedItemPath := ""
GroupAdd, ScriptHwnd_A, % "ahk_pid " ownPID ; Create an ahk_group "ScriptHwnd_A" and make all the current process's windows get into that group.
GoSub, CreateGUI
fillFoldersTV()
fillBookmarksLV()
fillAutorunsLV()
fillProcessesLV()
fillAssistantsLV()
TV_Modify(TV_GetNext(), "Select") ; Forcefully select topmost item in the TV and thus trigger update/fulfilment of 'fileLV' LV.
showGUI()
OnMessage(0x219, "WM_DEVICECHANGE") ; Track removable devices connecting/disconnecting to update the Folder Tree.
; Hooking ComObjects to track processes.
ComObjConnect(createSink := ComObjCreate("WbemScripting.SWbemSink"), "ProcessCreate_")
ComObjConnect(deleteSink := ComObjCreate("WbemScripting.SWbemSink"), "ProcessDelete_")
Command := "WITHIN 0.5 WHERE TargetInstance ISA 'Win32_Process'"
WMIQueries_O.ExecNotificationQueryAsync(createSink, "SELECT * FROM __InstanceCreationEvent " Command)
WMIQueries_O.ExecNotificationQueryAsync(deleteSink, "SELECT * FROM __InstanceDeletionEvent " Command)
assist()
Return
;}
;{+ CreateGUI (label).
CreateGUI:
;{ Create image lists and populate it with icons for later use in GUI.
IL_TVObjects := IL_Create(4) ; Create an ImageList to hold 4 icons.
IL_Add(IL_TVObjects, "shell32.dll", 4) ; 'Folder' icon.
IL_Add(IL_TVObjects, "shell32.dll", 80) ; 'Logical disk' icon.
IL_Add(IL_TVObjects, "shell32.dll", 27) ; 'Removable disk' icon.
; IL_Add(IL_TVObjects, "shell32.dll", 87) ; 'Folder with bookmarks' icon.
IL_Add(IL_TVObjects, "shell32.dll", 206) ; 'Folder with bookmarks' icon.
IL_scriptStates := IL_Create(6) ; Create an ImageList to hold 5 icons.
IL_Add(IL_scriptStates, A_AhkPath ? A_AhkPath : A_ScriptFullPath, 1) ; '[H]' default green AHK icon with letter 'H'.
IL_Add(IL_scriptStates, A_AhkPath ? A_AhkPath : A_ScriptFullPath, 3) ; '[S]' default green AHK icon with letter 'S'.
IL_Add(IL_scriptStates, A_AhkPath ? A_AhkPath : A_ScriptFullPath, 4) ; '[H]' default red AHK icon with letter 'H'.
IL_Add(IL_scriptStates, A_AhkPath ? A_AhkPath : A_ScriptFullPath, 5) ; '[S]' default red AHK icon with letter 'S'.
IL_Add(IL_scriptStates, "shell32.dll", 21) ; A sheet with a clock (suspended process).
IL_Add(IL_scriptStates, "imageres.dll", 12) ; A program's window (default .exe icon).
IL_LVObject := IL_Create(2) ; Create an ImageList to hold 1 icon.
IL_Add(IL_LVObject, A_AhkPath ? A_AhkPath : A_ScriptFullPath, 2) ; default icon for AHK script.
; IL_Add(IL1, "shell32.dll", 13) ; 'chip' icon.
; IL_Add(IL1, "shell32.dll", 46) ; 'Up to the root folder' icon.
; IL_Add(IL1, "shell32.dll", 71) ; 'Script' icon.
; IL_Add(IL1, "shell32.dll", 138) ; 'Run' icon.
; IL_Add(IL1, "shell32.dll", 272) ; 'Delete' icon.
; IL_Add(IL1, "shell32.dll", 285) ; Neat 'Script' icon.
; IL_Add(IL1, "shell32.dll", 286) ; Neat 'Folder' icon.
; IL_Add(IL1, "shell32.dll", 288) ; Neat 'Bookmark' icon.
; IL_Add(IL1, "shell32.dll", 298) ; 'Folders tree' icon.
;}
;{ Tray menu.
Menu, Tray, NoStandard ; Remove all standard items from tray menu.
Menu, Tray, Add, Manage Scripts, showGUI ; Create a tray menu's menuitem and bind it to a label that opens main window.
Menu, Tray, Default, Manage Scripts ; Set 'Manage Scripts' menuitem as default action (will be executed if tray icon is left-clicked).
Menu, Tray, Add ; Add an empty line (divider).
Menu, Tray, Standard ; Add all standard items to the bottom of tray menu.
;}
;{ Context menu for 'folderTV' TV, 'fileLV' LV and 'bookmarksLV' LV.
Menu, Tab1ContextMenu, Add, Run selected, runSelected
Menu, Tab1ContextMenu, Add, Bookmark selected, bookmarkSelected
Menu, Tab1ContextMenu, Add, Delete selected, deleteSelected
;}
;{ Context menu for 'processesLV' LV.
Menu, MngProcContMenu, Add, Open, Open
Menu, MngProcContMenu, Add, Reload, Reload
Menu, MngProcContMenu, Add, Edit, Edit
Menu, MngProcContMenu, Add, (Un) suspend hotkeys, SuspendHotkeys
Menu, MngProcContMenu, Add, (Un) pause, Pause
Menu, MngProcContMenu, Add, Exit, Exit
Menu, MngProcContMenu, Add, Kill, Kill
Menu, MngProcContMenu, Add, Kill and re-execute, killAndReRun
Menu, MngProcContMenu, Add, (Un) suspend process, toggleSuspendProcess
Menu, MngProcContMenu, Add, Hide tray icon(s), hideSelectedProcessesTrayIcons
Menu, MngProcContMenu, Add, Restore tray icon(s), ahkProcessRestoreTrayIcon
Menu, MngProcContMenu, Add, Show tray menu, showTrayMenu
;}
Gui, +Resize
;{ StatusBar
Gui, Add, StatusBar, vstatusBar
SB_SetParts(60, 85)
;}
;{+ Add tabs and their contents.
Gui, Add, Tab2, x0 y0 w799 h46 Choose1 +Theme -Background GTabSwitch VactiveTab, Files|AutoRuns|Processes|Process assistants
;{+ Tab #1: 'Files'.
Gui, Tab, Files
Gui, Add, Text, x26 y26, Choose a folder:
Gui, Add, Button, x532 y21 GrunSelected, Run selected
Gui, Add, Button, x+0 GbookmarkSelected, Bookmark selected
Gui, Add, Button, x+0 GdeleteSelected, Delete selected
;{ Folders Tree (left pane).
Gui, Add, TreeView, AltSubmit x0 y+0 GfolderTV VfolderTV HwndfolderTVHWND ImageList%IL_TVObjects% ; Add TreeView for navigation in the FileSystem.
;}
;{ File list (right pane).
Gui, Add, ListView, AltSubmit x+0 +Grid GfileLV VfileLV HwndfileLVHwnd, Name|Size|Created|Modified
LV_SetImageList(IL_LVObject) ; Assign ImageList 'IL_LVObject' to the current ListView.
; Set the static widths for some of it's columns.
LV_ModifyCol(2, 76) ; Size.
LV_ModifyCol(2, "Integer")
LV_ModifyCol(3, 117) ; Created.
LV_ModifyCol(4, 117) ; Modified.
;}
;{ Bookmarks (bottom pane).
Gui, Add, Text, vtextBS, Bookmarked scripts:
Gui, Add, ListView, AltSubmit +Grid GbookmarksLV VbookmarksLV, #|Name|Full Path|Size|Created|Modified
LV_SetImageList(IL_LVObject) ; Assign ImageList 'IL_LVObject' to the current ListView.
; Set the static widths for some of it's columns
LV_ModifyCol(1, 36) ; #.
LV_ModifyCol(1, "Integer")
LV_ModifyCol(4, 76) ; Size.
LV_ModifyCol(4, "Integer")
LV_ModifyCol(5, 117) ; Created.
LV_ModifyCol(6, 117) ; Modified.
;}
;}
;{ Tab #2: 'AutoRuns'.
Gui, Tab, AutoRuns
Gui, Add, Button, x656 y21 GaddAutorun, Add new
Gui, Add, Button, x+0 GdeleteSelected, Delete selected
Gui, Add, ListView, x0 y+0 +Checked +Grid -Multi +LV0x2 AltSubmit GautorunsLV HWNDautorunsLVHWND VautorunsLV, Enabled|Tray icon|Name|Path|Command line parameters
LV_SetImageList(IL_scriptStates) ; Assign ImageList 'IL_scriptStates' to the current ListView.
LV_ModifyCol(2, 60)
LV_ModifyCol(3, 200)
;}
;{ Tab #3: 'Processes'.
Gui, Tab, Processes
; Add buttons to trigger functions.
Gui, Add, Button, x1 y21 Gkill, Kill
Gui, Add, Button, x+0 GkillAndReRun, Kill and re-run
Gui, Add, Button, x+0 Gopen, Open
Gui, Add, Button, x+0 Greload, Reload
Gui, Add, Button, x+0 Gedit, Edit
Gui, Add, Button, x+0 GsuspendHotkeys, (Un) suspend hotkeys
Gui, Add, Button, x+0 Gpause, (Un) pause
Gui, Add, Button, x+0 Gexit, Exit
Gui, Add, Button, x+0 GtoggleSuspendProcess, (Un) suspend process
Gui, Add, Button, x+0 GhideSelectedProcessesTrayIcons, Hide tray icon
Gui, Add, Button, x+0 GahkProcessRestoreTrayIcon, Restore tray icon
Gui, Add, Button, x+0 GshowTrayMenu, Show tray menu
; Add the main "ListView" element and define it's size, contents, and a label binding.
Gui, Add, ListView, x0 y+0 +Grid +Count25 +LV0x2 AltSubmit HWNDprocessesLVHWND GprocessesLV VprocessesLV, #|PID|Name|Path
LV_SetImageList(IL_scriptStates) ; Assign ImageList 'IL_scriptStates' to the current ListView.
; Set the static widths for some of it's columns
LV_ModifyCol(1, 36)
LV_ModifyCol(1, "Integer") ; This fixes sorting of the columns with numeric values.
LV_ModifyCol(2, 64)
LV_ModifyCol(2, "Integer")
;}
;{ Tab #4: 'Process assistants'.
Gui, Tab, Process assistants
Gui, Add, Button, x583 y21 GaddEditPA, Add new
Gui, Add, Button, x+0 geditSelectedPA, Edit selected
Gui, Add, Button, x+0 GdeleteSelected, Delete selected
Gui, Add, ListView, x0 y+0 NoSortHdr +Grid -Multi AltSubmit VassistantsLV GassistantsLV, #|Act upon occurence|Act upon death|Bound together|Persistent|Condition|Assistant
LV_SetImageList(IL_scriptStates) ; Assign ImageList 'IL_scriptStates' to the current ListView.
LV_ModifyCol(1, 55)
LV_ModifyCol(2, 20)
LV_ModifyCol(3, 20)
LV_ModifyCol(4, 20)
LV_ModifyCol(5, 20)
;}
;}
Gui, Default
Return
;}
;{+ GUI-related functions.
;{ General functions of main GUI.
;{ ShowGUI() - shows the window and enables 'memoryScan' timer (if needed).
; Called by: initialization, 'tray menu' > 'Manage Scripts'.
showGUI()
{
Global settings_O, activeTab
If !(activeTab) ; After startup the 'activeTab' is empty.
activeTab := "Files"
Gui, Submit, NoHide
If (settings_O.rememberPosAndSize && settings_O.xywh.x) ; If there are previously stored data.
Gui, Show, % "x" settings_O.xywh.x " y" settings_O.xywh.y " w" settings_O.xywh.w - 16 " h" settings_O.xywh.h - 38, Manage Scripts
Else
Gui, Show, w830 h600 Center, Manage Scripts
Gui, +MinSize830x600 ; +Resize
If (activeTab == "Processes") ; 'Processes' tab.
{
memoryScan()
SetTimer, memoryScan, % settings_O.memoryScanInterval
}
}
;}
;{ guiSize() - resizes GUI controls to match the window's new size.
; Called by: automatically, upon minimizing, maximizing, restoring or resizing the window.
guiSize()
{
Global folderTVHWND, activeTab, settings_O
If (A_EventInfo != "1") ; The window has been resized or maximized.
{
workingAreaHeight := A_GuiHeight - 86
GuiControl, Move, folderTV, % " h" (workingAreaHeight * 0.677)
ControlGetPos,, FT_yCoord, FT_Width, FT_Height,, ahk_id %folderTVHWND%
GuiControl, Move, textBS, % "x0 y" (FT_yCoord + FT_Height - 30)
GuiControl, Move, fileLV, % "w" (A_GuiWidth - FT_Width + 30) " h" (workingAreaHeight * 0.677)
Gui, ListView, fileLV
LV_ModifyCol(1, A_GuiWidth - (FT_Width + 339))
GuiControl, Move, bookmarksLV, % "x0 y" (FT_yCoord + FT_Height - 17) "w" (A_GuiWidth + 1) " h" (8 + workingAreaHeight * 0.323)
Gui, ListView, bookmarksLV
LV_ModifyCol(2, (A_GuiWidth - 366) * 0.35)
LV_ModifyCol(3, (A_GuiWidth - 366) * 0.65)
GuiControl, Move, autorunsLV, % "w" (A_GuiWidth + 1) " h" (workingAreaHeight + 42)
Gui, ListView, autorunsLV
LV_ModifyCol(4, (A_GuiWidth - 340) * 0.5)
LV_ModifyCol(5, (A_GuiWidth - 340) * 0.5)
GuiControl, Move, processesLV, % "w" (A_GuiWidth + 1) " h" (workingAreaHeight + 42)
Gui, ListView, processesLV
LV_ModifyCol(3, (A_GuiWidth - 128) * 0.3)
LV_ModifyCol(4, (A_GuiWidth - 128) * 0.7)
GuiControl, Move, assistantsLV, % "w" (A_GuiWidth + 1) " h" (workingAreaHeight + 42)
Gui, ListView, assistantsLV
LV_ModifyCol(6, (A_GuiWidth - 171) * 0.5)
LV_ModifyCol(7, (A_GuiWidth - 171) * 0.5)
If (activeTab == "Processes")
SetTimer, memoryScan, % settings_O.memoryScanInterval
}
}
;}
;{ guiClose() - saves window position, closes it and turns off 'memoryScan' timer.
; Called by: automatically, upon the closure of script's main window.
guiClose()
{
Global settings_O
If (settings_O.rememberPosAndSize)
{
WinGetPos, sw_X, sw_Y, sw_W, sw_H, Manage Scripts ahk_class AutoHotkeyGUI
If (sw_X && sw_X != -32000) ; Guarantees that the previous line didn't fail.
settings_O.xywh.x := sw_X, settings_O.xywh.Y := sw_Y, settings_O.xywh.w := (sw_W < 846 ? 846 : sw_W), settings_O.xywh.h := (sw_H < 638 ? 638 : sw_H) ; 846x638 is the MinSize.
}
Gui, Hide
SetTimer, memoryScan, Off
}
;}
;{ tabSwitch() - hides/restores status bar and enables/disables 'memoryScan' timer.
; Called by: tabbar's G-Label, upon tab switch.
tabSwitch()
{
Global activeTab
Gui, Submit, NoHide
If (activeTab == "Files")
GuiControl, Show, statusBar
Else
GuiControl, Hide, statusBar ; It needs to be shown only on 'Files' tab.
If (activeTab == "Processes")
{
memoryScan()
SetTimer, memoryScan, % settings_O.memoryScanInterval
}
Else
SetTimer, memoryScan, Off ; It needs to be turned on only on 'Processes' tab.
}
;}
;{ exitApp() - saves window position, writes settings to the file and quits.
; Called by: automatically, whenever this script exits nicely.
exitApp()
{
Global settings_O, oldSettings_O, settingsPath
ObjRelease(WMIQueries_O), ObjRelease(createSink), ObjRelease(deleteSink)
If (settings_O.rememberPosAndSize)
{
DetectHiddenWindows, Off
IfWinExist, ahk_group ScriptHwnd_A
{
WinGetPos, sw_X, sw_Y, sw_W, sw_H, Manage Scripts ahk_class AutoHotkeyGUI
If (sw_X && sw_X != -32000) ; Guarantees that the previous line didn't fail.
settings_O.xywh.x := sw_X, settings_O.xywh.Y := sw_Y, settings_O.xywh.w := (sw_W < 846 ? 846 : sw_W), settings_O.xywh.h := (sw_H < 638 ? 638 : sw_H) ; 846x638 is the MinSize.
}
writeSettings(oldSettings_O, settings_O, settingsPath)
}
ExitApp
}
;}
;}
;{+ Fill TV and LVs.
;{ fillFoldersTV() - fills 'folderTV'.
; Called by: initialization.
fillFoldersTV()
{
Global settings_O
Critical, On
For k, v In settings_O.bookmarkedFolders
buildTree(v, TV_Add(v,, "Icon4"))
DriveGet, fixedDrivesList, List, FIXED ; Fixed logical disks.
If !(ErrorLevel)
Loop, Parse, fixedDrivesList ; Add all fixed disks to the TreeView.
buildTree(A_LoopField ":", TV_Add(A_LoopField ":",, "Icon2"))
DriveGet, removableDrivesList, List, REMOVABLE ; Removable logical disks.
If !(ErrorLevel)
Loop, Parse, removableDrivesList ; Add all removable disks to the TreeView.
buildTree(A_LoopField ":", TV_Add(A_LoopField ":",, "Icon3"))
Gui, TreeView, folderTV
TV_Modify(TV_GetNext(), "Select") ; Forcefully select topmost item in the TV.
Critical, Off
}
;}
;{ fillBookmarksLV() - parses settings_O.bookmarkedFiles filling 'bookmarksLV'.
; Called by: initialization.
fillBookmarksLV()
{
Global settings_O
Critical, On
Gui, ListView, bookmarksLV
LV_Delete()
For k, v In settings_O.bookmarkedFiles
addBookmarkToLV(v)
Critical, Off
}
;}
;{ fillAutorunsLV() - parses settings_O.autoruns filling 'autorunsLV' LV and executing the parsed autoruns (and also hiding the tray icons, if needed).
; Called by: initialization.
fillAutorunsLV()
{
Global settings_O, autorunsLVHWND
Critical, On
If !(settings_O.autoruns.Length())
{
Critical, Off
Return
}
For k, arRule In settings_O.autoruns
{
SplitPath, % arRule.path, arRuleName
Gui, ListView, autorunsLV
newRowIndex := LV_Add((arRule.enabled ? "Check" : "") " Icon99",,, arRuleName, arRule.path, arRule.parameters)
If (arRule.trayIcon) ; Draw an icon if the rule doesn't suppose to hide the tray icon of that script.
LV_SetCellIcon(autorunsLVHWND, newRowIndex, 2, 1)
If (arRule.enabled) ; Execute the script and decide whether to hide its tray icon.
{
WinGet, arRulePID, PID, % "ahk_exe " arRule.path ; This will catch exe's, but not uncompiled .ahk script processes.
If !(arRulePID) ; Attempt #2.
{
currentTMM := A_TitleMatchMode
SetTitleMatchMode, RegEx
WinGet, arRulePID, PID, % "Si)^\Q" arRule.path "\E\s-\sAutoHotkey\sv[\d\.]+$ ahk_class AutoHotkey" ; This will catch uncompiled .ahk script processes.
SetTitleMatchMode, % currentTMM
}
If ((!arRulePID || settings_O.forceExecAutostarts) && (FileExist(arRule.path)))
{
arRuleWasNotRunning := 1
Run, % arRule.path " " arRule.parameters,,, arRulePID
}
If !(arRule.trayIcon)
{
While !(arRuleHWND)
WinGet, arRuleHWND, ID, ahk_class AutoHotkey ahk_pid %arRulePID%
While !(TrayIcon_Remove(arRuleHWND) || A_Index == 5 || !arRuleWasNotRunning)
Sleep, 10
}
}
arRulePID := arRuleHWND := arRuleWasNotRunning := ""
}
Critical, Off
}
;}
;{ fillProcessesLV() - executes a WMI query to retrieve a list of running processes and uses these data to fill 'scriptsSnapshot_AofO' object and 'processesLV'.
; Called by: initialization.
fillProcessesLV()
{
Global WMIQueries_O, settings_O, scriptsSnapshot_AofO, processesLVHWND
Critical, On
; Fill scriptsSnapshot_AofO[] arrays with data and 'processesLV' LV.
Gui, ListView, processesLV
For process In WMIQueries_O.ExecQuery("SELECT ProcessId,ExecutablePath,CommandLine,Caption,Description FROM Win32_Process") ; Parsing through a list of running processes to filter out non-ahk ones (filters are based on 'If RegExMatch(…)' rules).
{ ; A list of accessible parameters related to the running processes: http://msdn.microsoft.com/en-us/library/windows/desktop/aa394372%28v=vs.85%29.aspx
If !(process.ProcessId) || (process.ProcessId = 4) || (process.CommandLine = "\SystemRoot\System32\smss.exe") || (process.Caption = "auidiodg.exe" && process.Description = "audiodg.exe") ; PID 0 = System Idle Process, PID 4 = System, smss.exe and audidg.exe have no ExecutablePath and audiodg.exe has no CommandLine.
Continue
For k, v In settings_O.ignoredProcesses
If (v == process.ExecutablePath)
Continue, 2
WinGetClass, class, % "ahk_pid " process.ProcessId
If ((process.ExecutablePath == A_AhkPath && RegExMatch(process.CommandLine, "Si)^(""|\s)*\Q" A_AhkPath "\E.*\\(?<Name>.*\.ahk)(""|\s)*$", script) && RegExMatch(process.CommandLine, "Si)^(""|\s)*\Q" A_AhkPath "\E.*""(?<Path>.*\.ahk)(""|\s)*$", script)) || (class == "AutoHotkey"))
{
If (process.ExecutablePath != A_AhkPath)
{
SplitPath, % process.ExecutablePath, scriptName
scriptPath := process.ExecutablePath
}
iconIndex := (isProcessSuspended(process.ProcessId) ? 5 : 1 + getScriptState(process.ProcessId)) ; The number from 1 to 5, which is the index of the icon in the 'IL_scriptStates' IL.
scriptsSnapshot_AofO.Push({"pid": process.ProcessId, "name": scriptName, "path": scriptPath, "icon": iconIndex})
newRowIndex := LV_Add("Icon" iconIndex, scriptsSnapshot_AofO.MaxIndex(), process.ProcessId, scriptName, scriptPath) ; Add the script to the LV with the proper icon and proper values for all columns.
If (scriptName ~= "Si)^.*\.exe$")
LV_SetCellIcon(processesLVHWND, newRowIndex, 3, 6)
}
}
Critical, Off
}
;}
;{ fillAssistantsLV() - parses settings_O.assistants filling 'assistantsLV'.
; Called by: initialization.
fillAssistantsLV()
{
Global settings_O
Critical, On
Gui, ListView, assistantsLV
LV_Delete()
If !(settings_O.assistants.MaxIndex()) ; There is nothing to do if there are no rules yet.
{
Critical, Off
Return
}
For k, v In settings_O.assistants
{
Loop, % (v.TCg.MaxIndex() > v.TAg.MaxIndex() ? v.TCg.MaxIndex() : v.TAg.MaxIndex())
{
If (A_Index == 1)
LV_Add("Icon" v.enabled, k, v.actUponOccurence, v.actUponDeath, v.bindAllToAll, v.persistent, v.TCg[1], v.TAg[1])
Else
LV_Add("Icon0",,,,,, v.TCg[A_Index], (v.bindAllToAll == 1 ? "" : v.TAg[A_Index]))
}
}
Critical, Off
}
;}
;}
;{+ Update TV and LVs.
;{ buildTree(folder, parentItemID = 0) - modifies 'folderTV' TV.
; Input: folder's path and parentItemID (ID of an item in a TreeView).
; Called by:
; Functions: fillFoldersTV(), WM_DEVICECHANGE(), bookmarkSelected().
; GUI controls G-labels: 'folderTV'.
buildTree(folder, parentItemID = 0)
{
Critical, On
Gui, TreeView, folderTV
If (folder)
Loop, %folder%\*, 2 ; Inception: retrieve all of Folder's sub-folders.
{
parent := TV_Add(A_LoopFileName, parentItemID, "Icon1") ; Add all of those sub-folders to the TreeView.
Loop, %A_LoopFileFullPath%\*, 2 ; We need to go deeper (c).
{
TV_Add("Please, close and re-open the parental folder", parent, "Icon2")
Break ; No need to add more than 1 item: that's needed just to make the parent item expandable (anyways it's contents will get re-constructed when that item gets expanded).
}
}
Critical, Off
}
;}
;{ Track removable drives appearing/disappearing and rebuild TreeView when needed.
WM_DEVICECHANGE(wp, lp, msg, hwnd) ; Add/remove data to the 'folderTV' TV about connected/disconnected removable disks.
; Input: system message details sent to the windows of this script.
; Called by: system, upon receiving message "0x219" (when a removable devices is connected/disconnected). For some reason it's called twice every time a disk got (dis)connected.
{
Critical, On
If (hwnd = A_ScriptHwnd && (wp = 0x8000 || wp = 0x8004) && NumGet(lp + 4, "UInt") = 2) ; 0x8000 == DBT_DEVICEARRIVAL, 0x8004 == DBT_DEVICEREMOVECOMPLETE, 2 == DBT_DEVTYP_VOLUME
{
dbcv_unitmask := NumGet(lp + 12, "UInt")
driveLetter := Chr(Asc("A") + ln(dbcv_unitmask) / ln(2))
Loop
{
driveID := TV_GetNext(driveID)
TV_GetText(thisDrive, driveID)
StringLeft, thisDrive, thisDrive, 1
} Until (driveLetter == thisDrive) || !(driveID)
If (wp == 0x8000) && (driveLetter != thisDrive)
buildTree(driveLetter ":", TV_Add(driveLetter ":",, "Icon3"))
Else If (wp == 0x8004) && (driveID)
TV_Delete(driveID)
}
Critical, Off
}
;}
;{ bookmarkSelected() - gets selected rows in 'fileLV' or 'folderTV' (depending on which one of them is active) and bookmarks those items, updating both: 'settings_O' object and either 'folderTV' or 'bookmarksLV'.
; Called by:
; Buttons: 'Bookmark selected' (tab #1 'Files').
; Menuitems: 'folderTV' > 'Bookmark selected', 'fileLV' > 'Bookmark selected'.
bookmarkSelected()
{
Global activeControl, settings_O
Critical, On
If (activeControl == "fileLV") ; Bookmark a file.
{
Gui, ListView, fileLV
For k, v In getScriptNames()
settings_O.bookmarkedFiles.Push(v), addBookmarkToLV(v)
}
Else If (activeControl == "folderTV") ; Bookmark a folder.
{
settings_O.bookmarkedFolders.Push(selectedItemPath)
buildTree(selectedItemPath, TV_Add(selectedItemPath,, "Vis Icon4"))
}
Critical, Off
}
;}
;{ addBookmarkToLV(pathToFile_S) - adds a new row to 'bookmarksLV' (if file exist by specified path).
; Input: pathToFile_S - string with path to file.
; Called by:
; Functions: fillBookmarksLV(), bookmarkSelected().
addBookmarkToLV(pathToFile_S)
{
Critical, On
Gui, ListView, bookmarksLV
IfExist, % pathToFile_S ; Check whether the previously bookmared file exists.
{ ; If the file exists - display it in the LV.
SplitPath, pathToFile_S, fileName
FileGetSize, fileSize, %pathToFile_S%
FileGetTime, fileCreatedDate, %pathToFile_S%, C
FormatTime, fileCreatedDate, %fileCreatedDate%, yyyy.MM.dd HH:mm:ss ; Transofrm creation date into a readable format.
FileGetTime, fileModifiedDate, %pathToFile_S% ; Get file's last modification date.
FormatTime, fileModifiedDate, %fileModifiedDate%, yyyy.MM.dd HH:mm:ss ; Transofrm creation date into a readable format.
LV_Add("Icon1", LV_GetCount() + 1, fileName, pathToFile_S, Round(fileSize / 1024, 1) " KB", fileCreatedDate, fileModifiedDate)
}
; Else ; The file doesn't exist. Delete it?
Critical, Off
}
;}
;{ addAutorun() - opens a new window with prompt to add a new autorun rule.
; Called by:
; Buttons: 'Add new' (tab #2 'AutoRuns').
addAutorun()
{
Global settings_O, scriptPathEdit, scriptArgsEdit, hideTrayIcon, autorunsLV, autorunsLVHWND
Gui, NewAutorun: New
Gui, Add, Text,, Select script's file:
Gui, Add, Edit, r1 w527 VscriptPathEdit
Gui, Add, Button, x+6 GfileSelect, Browse
Gui, Add, Text, x10, Specify command line arguments (optionally):
Gui, Add, Edit, r1 w579 VscriptArgsEdit
Gui, Add, Checkbox, x10 VhideTrayIcon, Hide tray icon on start
Gui, Add, Button, x520 y130 GfinishAddingNewAutorun, Add this rule
Gui, Show, w600 h160, Add new 'AutoRun' rule
Return
fileSelect:
FileSelectFile, scriptPath, 3,, Select AHK script file, AHK scripts (*.ahk; *.exe)
GuiControl,, scriptPathEdit, % scriptPath
Return
finishAddingNewAutorun:
Gui, NewAutorun: Submit, NoHide
If !(scriptPathEdit ~= "Si)^.*\.(ahk|exe)$")
{
MsgBox, 16, Error, Specified path doesn't point to a script file (*.ahk or *.exe)!
Return
}
Else
{
settings_O.autoruns.Push({"enabled": "0", "trayIcon": (trayIcon ? "1" : "0"), "path": scriptPathEdit, "parameters": scriptArgsEdit})
Gui, NewAutorun: Submit
SplitPath, scriptPathEdit, scriptName
Gui, 1: Default
Gui, ListView, autorunsLV
newRowIndex := LV_Add(,,, scriptName, scriptPathEdit, scriptArgsEdit)
If !(hideTrayIcon)
LV_SetCellIcon(autorunsLVHWND, newRowIndex, 2, 1)
}
Return
}
;}
;{+ addEditPA() - a function that by default opens a new window with prompt to add a new process assistant rule, however the function also contains a set of labels needed to edit an existing process assistant rule.
addEditPA()
{
Global settings_O, thisPAEnabled_B, actUponOccurence_B, actUponDeath_B, bindAllToAll_B, persistent_B, trigger_S, dependentsTopText_P, addDependent_P, dependent_S, affects_P
GoSub, addEditPAGUI
Gui, addEditPA: Show,, New rule
ruleToEdit_N := ""
Return
;{+ Labels
;{ addEditPAGUI - creates a window to add/edit a Process Assistant.
addEditPAGUI:
Gui, addEditPA: New
Gui, Add, Checkbox, VthisPAEnabled_B, Enable rule.
Gui, Add, Checkbox, VactUponOccurence_B GactUponOccurence_B Checked, Act upon occurence: if any trigger occures - dependent(s) will get executed.
Gui, Add, Checkbox, VactUponDeath_B GactUponDeath_B, % "Act upon death: if any trigger dies - dependent(s) will get " (settings_O.quitAssistantsNicely ? "stopped." : "killed.")
Gui, Add, Checkbox, w550 VbindAllToAll_B GbindAllToAll_B , Many-as-one: group all processes reciprocally together: running one will run the whole group.
Gui, Add, Checkbox, w760 h39 Vpersistent_B Gpersistent_B, Make the rule persistent: or "keep state" (treat 'act upon occurence/death' as 'act if trigger is alive/dead').`nFor example: if execution of a.exe triggers execution of b.exe`, but b.exe later died while a.exe is still alive - then b.exe will be re-executed.
Gui, Add, Text, x30, Specify full or partial paths to the triggering executables.
; Gui, Add, Button, GaddTrigger x10 y130, +
Gui, Add, Button, GaddTrigger x10, +
Gui, Add, Edit, x30 y145 w360 Vtrigger_S R15
Gui, Add, Text, x420 y127 VdependentsTopText_P, Specify full or partial paths to the dependent executables.
Gui, Add, Button, GaddDependent_P VaddDependent_P x400 y145, +
Gui, Add, Edit, x420 y145 w360 Vdependent_S R15
Gui, Add, Text, x10 y+10, Notes:`n1. You may use partial paths if you like (the left part in the path may be omitted).`n2. Adding or editing a process assistant rule doesn't scan the already running processes - it will work only with new ones.
Gui, Add, Button, GsavePA x750 y+0, Save
Gui, Add, Text, x400 y220 vaffects_P, ⇒
Return
;}
;{ actUponOccurence_B, actUponDeath_B - makes sure one of them remains checked.
actUponOccurence_B: ; Assistant rule's 'add new/edit selected' checkbox'es g-label.
actUponDeath_B: ; Assistant rule's 'add new/edit selected' checkbox'es g-label.
Gui, addEditPA: Submit, NoHide
If !(%A_ThisLabel%)
GuiControl, addEditPA:, % (A_ThisLabel = "actUponOccurence_B" ? "actUponDeath_B" : "actUponOccurence_B"), 1
Gui, addEditPA: Submit, NoHide
GuiControl, addEditPA: Text, bindAllToAll_B, % "Many-as-one: group all processes reciprocally together: " (actUponOccurence_B ? (actUponDeath_B ? "running or " (settings_O.quitAssistantsNicely ? "stopping" : "killing") : "running") : (settings_O.quitAssistantsNicely ? "stopping" : "killing")) " one will " (actUponOccurence_B ? (actUponDeath_B ? "run or " (settings_O.quitAssistantsNicely ? "stop" : "kill") : "run") : (settings_O.quitAssistantsNicely ? "stop" : "kill")) " the whole group."
GuiControl, addEditPA: Text, persistent_B, % "Keep state: if 'a.exe' triggers 'b.exe', then process assistant will make sure that:" (actUponOccurence_B ? "`nwhile a.exe is running - b.exe will always run too (even if b.exe later dies - it will get re-executed)" : "") (actUponOccurence_B && actUponDeath_B ? " and " : "") (actUponDeath_B ? "`nwhile a.exe is not running - b.exe will be suppressed (even if b.exe gets manually executed - it will get " (settings_O.quitAssistantsNicely ? "stopped" : "killed") ")" : "") "."
Return
;}
;{ bindAllToAll_B - transforms GUI making it have either 1 or 2 'edit' fields + whether to disable or enable the 'persistent_B' checkbox.
bindAllToAll_B: ; 'Bind all to all' checkbox'es g-label.
Gui, addEditPA: Submit, NoHide
GuiControl, addEditPA: Move, trigger_S, % "w" (bindAllToAll_B ? "750" : "360")
GuiControl, % "addEditPA:" (bindAllToAll_B ? "Disable" : "Enable"), persistent_B
If (bindAllToAll_B)
GuiControl, addEditPA:, persistent_B, 0
For k, v In ["affects_P", "dependent_S", "dependentsTopText_P", "addDependent_P"]
GuiControl, % "addEditPA:" (bindAllToAll_B ? "Hide" : "Show"), %v%
Gui, addEditPA: Submit, NoHide
Return
;}
;{ persistent_B - disables/enables 'bindAllToAll_B' checkbox.
persistent_B:
Gui, addEditPA: Submit, NoHide
GuiControl, % "addEditPA:" (persistent_B ? "Disable" : "Enable"), bindAllToAll_B
If (persistent_B)
GuiControl, addEditPA:, bindAllToAll_B, 0
Gui, addEditPA: Submit, NoHide
Return
;}
;{ addTrigger, addDependent_P - G-Labels of buttons that open Explorer Window.
addTrigger: ; gLabel of left "+" button in the 'New/edit rule' window.
addDependent_P: ; gLabel of right "+" button in the 'New/edit rule' window.
FileSelectFile, selectedFiles_S, MS,, Select executables or ahk-scripts, Processes or scripts (*.exe; *.ahk) ; M option makes the output have stupid format.
If (ErrorLevel) ; In case user canceled file selection.
Return
If (A_ThisLabel = "addTrigger")
{
GuiControlGet, trigger_S
trigger_S .= fixFSFOutput(selectedFiles_S)
GuiControl, addEditPA:, trigger_S, %trigger_S%
}
Else
{
GuiControlGet, dependent_S
dependent_S .= fixFSFOutput(selectedFiles_S)
GuiControl, addEditPA:, dependent_S, %dependent_S%
}
Return
;}
;{ editSelectedPA - G-Labelof 'Edit selected' button.
editSelectedPA:
Gui, 1: ListView, assistantsLV
If !(LV_GetCount("Selected")) ; If no assistant is selected.
LV_Modify(1, "Select") ; Forcefully select 1st one.
ruleToEdit_N := ""
While !(ruleToEdit_N) ; Find rule number by getting 1st column's value (and move upwards if it's blank).
LV_GetText(ruleToEdit_N, LV_GetNext() + 1 - A_Index, 1) ; ruleToEdit_N will contain the number of the rule related to the selected row.
GoSub, addEditPAGUI
GuiControl, addEditPA:, thisPAEnabled_B, % settings_O.assistants[ruleToEdit_N].enabled
GuiControl, addEditPA:, actUponOccurence_B, % settings_O.assistants[ruleToEdit_N].actUponOccurence
GuiControl, addEditPA:, actUponDeath_B, % settings_O.assistants[ruleToEdit_N].actUponDeath
GuiControl, addEditPA:, bindAllToAll_B, % settings_O.assistants[ruleToEdit_N].bindAllToAll
GuiControl, addEditPA:, persistent_B, % settings_O.assistants[ruleToEdit_N].persistent
GuiControl, addEditPA:, trigger_S, % arr2ASV(settings_O.assistants[ruleToEdit_N].TCg, "`n")
GuiControl, addEditPA:, dependent_S, % arr2ASV(settings_O.assistants[ruleToEdit_N].TAg, "`n")
Gui, addEditPA: Show,, Edit rule #%ruleToEdit_N%
Return
;}
;{ savePA - gLabel of the 'save' button in the 'New/edit rule' window.
savePA:
;{ Check input.
Gui, addEditPA: Submit, NoHide
trigger_S := Trim(trigger_S, " `n`r`t"), dependent_S := Trim(dependent_S, " `n`r`t")
GuiControlGet, trigger_S,, trigger_S
If !(trigger_S)
{
MsgBox, Error!`nNo triggers specified!
Return
}
GuiControlGet, bindAllToAll_B,, bindAllToAll_B
If (bindAllToAll_B)
{
IfNotInString, trigger_S, `n
{
MsgBox, When selecting 'Many-as-One' there's no point in a rule with only 1 trigger.
Return
}
}
GuiControlGet, dependent_S,, dependent_S
If (!bindAllToAll_B && !dependent_S)
{
MsgBox, Error!`nNo dependents specified!
Return
}
For k, v In ["thisPAEnabled_B", "actUponOccurence_B", "actUponDeath_B", "persistent_B"]
GuiControlGet, %v%,, %v%
Gui, addEditPA: Destroy
;}
;{ Update 'settings_O' and 'assistantsLV'.
Gui, 1: Default
Gui, ListView, assistantsLV
trigger_A := ASV2Arr(trigger_S, "`n"), dependent_A := ASV2Arr(dependent_S, "`n")
If !(ruleToEdit_N) ; If user added new rule.
{
settings_O.assistants.Push({"enabled": thisPAEnabled_B, "actUponOccurence": actUponOccurence_B, "actUponDeath": actUponDeath_B, "bindAllToAll": bindAllToAll_B, "persistent": persistent_B, "TCg": trigger_A, "TAg": dependent_A})
Loop, % (trigger_A.MaxIndex() > dependent_A.MaxIndex() ? trigger_A.MaxIndex() : dependent_A.MaxIndex())
{
If (A_Index == 1)
LV_Add("Icon" thisPAEnabled_B, settings_O.assistants.MaxIndex(), actUponOccurence_B, actUponDeath_B, bindAllToAll_B, persistent_B, trigger_A[1], dependent_A[1])
Else
LV_Add("Icon0",,,,,, trigger_A[A_Index], (bindAllToAll_B == 1 ? "" : dependent_A[A_Index]))
}
}
Else
settings_O.assistants[ruleToEdit_N] := {"enabled": thisPAEnabled_B, "actUponOccurence": actUponOccurence_B, "actUponDeath": actUponDeath_B, "bindAllToAll": bindAllToAll_B, "persistent": persistent_B, "TCg": trigger_A, "TAg": dependent_A}, fillAssistantsLV()
;}
Return
;}
;}
}
;}
;{ deleteSelected() - deletes stuff associated with the selection in existing TreeView or ListViews.
; Called by:
; Buttons: 'Delete selected' (tab #1 'Files', tab #2 'AutoRuns', tab #4 'Process assistants').
; Menuitems: 'folderTV' > 'Delete selected', 'bookmarksLV' > 'Delete selected', 'fileLV' > 'Delete selected'.
deleteSelected()
{
Critical, On
Global settings_O, activeTab, activeControl
If (activeControl != "folderTV")
Gui, ListView, %activeControl%
If (activeTab == "Files")
{
If (activeControl == "bookmarksLV")
{
selected := getSelectedRows(1)
If (selected.Length())
{
For k, v In selected
LV_Delete(v), settings_O.bookmarkedFiles.RemoveAt(v)
; Re-count indexes in 1st column.
For k, v In settings_O.bookmarkedFiles
{
LV_GetText(LVindex, A_Index, 1)
If (A_Index != LVindex)
LV_Modify(A_Index, "Integer", A_Index)
}
}
}
Else If (activeControl == "fileLV") ; In case the last active GUI element was "fileLV" ListView.
{
selected := getScriptNames()
If (selected.MaxIndex() == 0)
{
Critical, Off
Return
}
Critical, Off
Msgbox, 1, Confirmation required, % "Are you sure want to delete the selected file(s)?`n" arr2ASV(selected, "`n")
IfMsgBox, OK
{
Critical, On
For k, v In selected
FileDelete, %v%
Gui, ListView, fileLV
selected := getSelectedRows(1)
For k, v In selected
LV_Delete(v)
Critical, Off
}
}
Else If (activeControl == "folderTV") ; In case the last active GUI element was 'folderTV' TreeView.
{ ; Then we should delete a bookmarked folder.
For k, v In settings_O.bookmarkedFolders
{
If (v == selectedItemPath)
{
TV_Delete(TV_GetSelection())
settings_O.bookmarkedFolders.RemoveAt(k)
Break
}
}
}
}
Else If (activeTab == "AutoRuns")
{
selected_N := LV_GetNext()
LV_Delete(selected_N)
settings_O.autoruns.RemoveAt(selected_N)
}
Else If (activeTab == "Process assistants")
{
selected_N := ""
While !(selected_N) ; Find rule number by getting 1st column's value (and move upwards if it's blank).
LV_GetText(selected_N, LV_GetNext() + 1 - A_Index, 1) ; 'selected_N' will contain the number of the rule related to the selected row.
MsgBox, 4, Confirmation required, Are you sure you'd like to delete assistant rule #%selected_N%?
IfMsgBox, Yes
settings_O.assistants.RemoveAt(selected_N), fillAssistantsLV()
}
Critical, Off
}
;}
;}
;{ statusbarUpdate(fileCount, size, path) - updates the three parts of the status bar to show info about the currently selected folder.
; Input:
; fileCount - a number of files in the viewed directory.
; size - size of files in the viewed directory.
; path - path of the viewed directory.
; Called by:
; Functions: folderTV().
statusbarUpdate(fileCount, size, path)
{
SB_SetText(fileCount " files", 1)
SB_SetText(Round(size / 1024, 1) " KB", 2)
SB_SetText(path, 3)
}
;}
;{+ G-Labels associated with the TV/LVs.
;{ folderTV() - reacts to clicks sent to 'folderTV'.
folderTV()
{
Critical, On
Global activeControl := A_ThisFunc, selectedItemPath
If (A_GuiEvent == "Normal") || (A_GuiEvent == "RightClick") || (A_GuiEvent == "S") || (A_GuiEvent == "+") ; In case of script's initialization, user's left click, keyboard selection or tree expansion - (re)fill the 'fileLV' listview.
{
If (A_GuiEvent == "Normal") || (A_GuiEvent == "RightClick") ; If user left clicked an empty space at right from a folder's name in the TreeView.
{
If (A_EventInfo) ; If user clicked on a line's empty space.
TV_Modify(A_EventInfo, "Select") ; Forcefully select that line.
Else ; If user clicked on the empty space unrelated to any item in the tree.
{
Critical, Off
Return ; We should react only to A_GuiEvents with "S" and "+" values.
}
}
;{ Determine the full path of the selected folder:
Gui, TreeView, folderTV
TV_GetText(selectedItemPath, A_EventInfo)
Loop ; Build the full path to the selected folder.
{
parentID := (A_Index == 1) ? TV_GetParent(A_EventInfo) : TV_GetParent(parentID)
If !(parentID) ; No more ancestors.
Break
TV_GetText(parentText, parentID)
selectedItemPath := parentText "\" selectedItemPath
}
;}
;{ Rebuild TreeView, if it was expanded.
If (A_GuiEvent == "+") || (A_GuiEvent == "Normal" && A_EventInfo) ; If a tree got expanded.
{
Loop, %selectedItemPath%\*.*, 2 ; Parse all the children of the selected item.
{
thisChildID := TV_GetChild(A_EventInfo) ; Get first child's ID.
If (thisChildID) ; && A_EventInfo
TV_Delete(thisChildID)
}
buildTree(selectedItemPath, A_EventInfo) ; Add children and grandchildren to the selected item.
}
;}
;{ Update 'fileLV'.
oldDefLV := A_DefaultListView
Gui, ListView, fileLV
GuiControl, -Redraw, fileLV ; Improve performance by disabling redrawing during load.
LV_Delete() ; Delete old data.
fileCount := totalSize := 0 ; Init prior to loop below.
Loop, %selectedItemPath%\*.ahk ; This omits folders and shows only .ahk-files in the ListView.
{
FormatTime, created, %A_LoopFileTimeCreated%, yyyy.MM.dd HH:mm:ss
FormatTime, modified, %A_LoopFileTimeModified%, yyyy.MM.dd HH:mm:ss
LV_Add("Icon1", A_LoopFileName, Round(A_LoopFileSize / 1024, 1) . " KB", created, modified)
fileCount++
totalSize += A_LoopFileSize
}
GuiControl, +Redraw, fileLV
;}
statusbarUpdate(fileCount, totalSize, selectedItemPath)
If (A_GuiEvent == "RightClick") ; Show context menu if user right clicked anything in the TV + disable 'bookmark selected' command there in case he clicked an already bookmarked folder.
{
Loop, Parse, bookmarkedFolders, |
{
If (selectedItemPath = A_LoopField)
{
bookmarkedFolderDetected := 1
Menu, Tab1ContextMenu, Disable, Bookmark selected
Break
}
}
Menu, Tab1ContextMenu, Show
If (bookmarkedFolderDetected)
{
bookmarkedFolderDetected := 0
Menu, Tab1ContextMenu, Enable, Bookmark selected
}
}
Gui, ListView, % oldDefLV
}
Critical, Off
}
;}
;{ fileLV()
fileLV()
{
Critical, On
Global activeControl
Gui, ListView, % A_ThisFunc
If (A_GuiEvent == "Normal") || (A_GuiEvent == "RightClick")
activeControl := A_ThisFunc
If (A_GuiEvent == "RightClick")
Menu, Tab1ContextMenu, Show
Critical, Off
}
;}
;{ bookmarksLV()
bookmarksLV()
{
Critical, On
Global activeControl
Gui, ListView, % A_ThisFunc
If (A_GuiEvent == "Normal") || (A_GuiEvent == "RightClick")
activeControl := A_ThisFunc
If (A_GuiEvent == "RightClick")
{
Menu, Tab1ContextMenu, Disable, Bookmark selected
Menu, Tab1ContextMenu, Delete, Delete selected
Menu, Tab1ContextMenu, Add, Remove selected bookmark(s), deleteSelected
Menu, Tab1ContextMenu, Show
Menu, Tab1ContextMenu, Enable, Bookmark selected
Menu, Tab1ContextMenu, Delete, Remove selected bookmark(s)
Menu, Tab1ContextMenu, Add, Delete selected, deleteSelected
}