forked from studgeek/AltTabAHK
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathAltTab.ahk
executable file
·2357 lines (2013 loc) · 78.1 KB
/
AltTab.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
; Gui, 99
; Load help files
FileRead, HELP, README.md
FileRead, LATEST_VERSION_CHANGES, Changelog.md
;========================================================================================================
; USER EDITABLE SETTINGS:
; Ini Setting file
Setting_INI_File = Alt_Tab_Settings.ini
; Icons
Use_Large_Icons =1 ; 0 = small icons, 1 = large icons in listview
Listview_Resize_Icons =0 ; Resize icons to fit listview area
; Fonts
Font_Size=10
Font_Color=e9ded3
Font_Style=Bold
Font_Size_Tab =8
Font_Type_Tab =Consolas
Font_Type =Segoe UI
; Position
Gui_x =Center
Gui_y =Center
; Max height
Height_Max_Modifier =0.65 ; multiplier for screen height (e.g. 0.92 = 92% of screen height max )
; Width
Listview_Width := A_ScreenWidth * 0.40
SB_Width := Listview_Width / 4 ; StatusBar section sizes
Exe_Width_Max := Listview_Width / 5 ; Exe column max width
; Tray Icon file name
Tray_Icon := "Icon.ico"
;========================================================================================================
; USER OVERRIDABLE SETTINGS:
; Widths
Col_1 =Auto ; icon column
Col_2 =0 ; hidden column for row number
; col 3 is autosized based on other column sizes
Col_4 =Auto ; exe
Col_5 =AutoHdr ; State
Col_6 =Auto ; OnTop
Col_7 =Auto ; Status - e.g. Not Responding
Gui1_Tab__width := Listview_Width - 2
; Max height
Height_Max := A_ScreenHeight * Height_Max_Modifier ; limit height of listview
Small_to_Large_Ratio =1.6 ; height of small rows compared to large rows
; Colours in RGB hex
Tab_Colour =1c1b1a
Listview_Colour =1c1b1a ; does not need converting as only used for background
StatusBar_Background_Colour =998899
; convert colours to correct format for listview color functions:
Listview_Colour_Max_Text := RGBtoBGR("0xffffff") ; highlight minimised windows
Listview_Colour_Max_Back := RGBtoBGR("0x000000")
Listview_Colour_Min_Text := RGBtoBGR("0x000000") ; highlight minimised windows
Listview_Colour_Min_Back := RGBtoBGR("0xffa724")
Listview_Colour_OnTop_Text := RGBtoBGR("0x000000") ; highlight alwaysontop windows
Listview_Colour_OnTop_Back := RGBtoBGR("0xff2c4b")
Listview_Colour_Dialog_Text := RGBtoBGR("0xFFFFFF")
Listview_Colour_Dialog_Back := RGBtoBGR("0xFB5959")
Listview_Colour_Selected_Text := RGBtoBGR("0xffffff")
Listview_Colour_Selected_Back := RGBtoBGR("0x0a9dff")
Listview_Colour_Not_Responding_Text := RGBtoBGR("0xFFFFFF")
Listview_Colour_Not_Responding_Back := RGBtoBGR("0xFF0000")
;========================================================================================================
#NoEnv
#SingleInstance force
#Persistent
#InstallKeybdHook
#InstallMouseHook
#NoTrayIcon
#MaxHotkeysPerInterval 1000
Process Priority,,High
SetWinDelay, -1
SetBatchLines, -1
Group_Active =
WinGet, TaskBar_ID, ID, ahk_class Shell_TrayWnd ; for docked windows check
Hidden_Tag := "Hidden"
Exclude_Other_Tag := "Exclude_Not_In_List"
If A_PtrSize = 8
GetClassLong_API := "GetClassLongPtr"
else
GetClassLong_API := "GetClassLong"
IniFile_Data("Read")
OnExit, OnExit_Script_Closing
OnMessage( 0x06, "WM_ACTIVATE" ) ; alt tab list window lost focus > hide list
LV_ColorInitiate() ; initiate listview color change procedure
Gosub, Initiate_Hotkeys ; initiate Alt-Tab and Alt-Shift-Tab hotkeys, taskbar scorll event and translate some modifier symbols.
WS_EX_CONTROLPARENT =0x10000
WS_EX_DLGMODALFRAME =0x1
WS_CLIPCHILDREN =0x2000000
WS_EX_APPWINDOW =0x40000
WS_EX_TOOLWINDOW =0x80
WS_DISABLED =0x8000000
WS_VSCROLL =0x200000
WS_POPUP =0x80000000
SysGet, Scrollbar_Vertical_Thickness, 2 ; 2 is SM_CXVSCROLL, Width of a vertical scroll bar
If A_OSVersion =WIN_2000
lv_h_win_2000_adj =2 ; adjust height of main listview by +2 pixels to avoid scrollbar in windows 2000
Else
lv_h_win_2000_adj =0
;Setting when showing tabs
Exclude_Not_In_List =0
PID_Filter = ;Filter windows if does not math the PID. Set empty disable this feature
Hide_Other_Group =0
Display_List_Shown =0
Window_Hotkey =0
Use_Large_Icons_Current =%Use_Large_Icons% ; for remembering original user setting but changing on the fly
Time_Since_Last_Alt_Close =0 ; initialise time for repeat rate allowed for closing windows with alt+\
Viewed_Window_List =
Tab_Shown =
Col_Title_List =#| |Window|Exe|View|Top|Status
StringSplit, Col_Title, Col_Title_List,| ; create list of listview header titles
If not No_Tray_Icon
{
Menu TRAY, Icon
IfExist Icon.ico
Menu TRAY, Icon, %Tray_Icon%
; Clear previous entries
Menu, TRAY, NoStandard
; Window Group sub-menu entry
Menu, TRAY, Add ; spacer
Menu, TRAY, Add, Group - &No Filter, Gui_Window_Group_No_Filter
If (Group_Active != "ALL")
Menu, TRAY, Disable, Group - &No Filter
Loop, Parse, Group_List,|
Menu, Gui_Window_Group_Load, Add,%A_LoopField%, Gui_Window_Group_Load
Menu, TRAY, Add, Group - &Load, :Gui_Window_Group_Load
Menu, TRAY, Add, Group - &Save/Edit, Gui_Window_Group_Save_Edit
Menu, TRAY, Add, Group - Global &Include, Gui_Window_Group_Global_Include
Menu, TRAY, Add, Group - Global &Exclude, Gui_Window_Group_Global_Exclude
Loop, Parse, Group_List,|
If (A_LoopField != "ALL")
Menu, Gui_Window_Group_Delete, Add,%A_LoopField%, Gui_Window_Group_Delete
Menu, Gui_Window_Group_Delete, Color, E10000, Single ; warning colour
Menu, TRAY, Add, Group - &Delete, :Gui_Window_Group_Delete
; Hotkeys entry
Menu, TRAY, Add ; spacer
Menu, TRAY, Add, &Hotkeys, Gui_Hotkeys
; Help + Latest changes
Menu, TRAY, Add ; spacer
Menu, Gui_Settings_Help, Add, Delete Settings (.ini) && Reload, Delete_Ini_File_Settings
Menu, Gui_Settings_Help, Add, Reload, Reload
Menu, Gui_Settings_Help, Add, ; spacer
Menu, Gui_Settings_Help, Add, Help, HELP_and_LATEST_VERSION_CHANGES
Menu, Gui_Settings_Help, Add, Latest Changes, HELP_and_LATEST_VERSION_CHANGES
Menu, TRAY, Add, Settings && Help, :Gui_Settings_Help
; Exit entry
Menu, TRAY, Add ; spacer
Menu, TRAY, Add, &Exit, OnExit_Script_Closing
}
Return
;========================================================================================================
Initiate_Hotkeys:
Use_AND_Symbol = ; initiate
; If both Alt and Tab are modifier keys, write Tab as a word not a modifier symbol, else Alt-Tab is invalid hotkey
If Alt_Hotkey contains #,!,^,+
{
; Replace_Modifier_Symbol( "Alt_Hotkey" , "Alt_Hotkey" )
If Tab_Hotkey contains #,!,^,+
Replace_Modifier_Symbol( "Tab_Hotkey" , "Tab_Hotkey" )
}
Else If Alt_Hotkey contains XButton1,XButton2
Use_AND_Symbol :=" & "
Else If Tab_Hotkey contains WheelUp,WheelDown
Use_AND_Symbol :=" & "
Hotkey, %Alt_Hotkey%%Use_AND_Symbol%%Tab_Hotkey%, Alt_Tab, On ; turn on alt-tab hotkey here to be able to turn it off for simple switching of apps in script
Hotkey, %Alt_Hotkey%%Use_AND_Symbol%%Shift_Tab_Hotkey%, Alt_Shift_Tab, On ; turn on alt-tab hotkey here to be able to turn it off for simple switching of apps in script
If Single_Key_Show_Alt_Tab !=
{
; If Single_Key_Show_Alt_Tab contains #,!,^,+
; Replace_Modifier_Symbol( "Single_Key_Show_Alt_Tab" , "Single_Key_Show_Alt_Tab" )
Hotkey, *%Single_Key_Show_Alt_Tab%, Single_Key_Show_Alt_Tab, On
}
Replace_Modifier_Symbol( "Alt_Hotkey" , "Alt_Hotkey2" )
If (! InStr(Tab_Hotkey, "Wheel") and ! InStr(Shift_Tab_Hotkey, "Wheel")) ; wheel isn't used as an alt-tab hotkey so can be used for scrolling list instead
Use_Wheel_Scroll_List =1
; Listen wheel scroll event in taskbar if need
if Scroll_In_TaskBar {
Hotkey, ~WheelUp, Taskbar_Scroll_Up
Hotkey, ~WheelDown, Taskbar_Scroll_Down
}
Return
Alt_Tab: ; alt-tab hotkey
; Tooltip % time("Alt_Tab_Common_Function", 1)
Alt_Tab_Common_Function(1)
Return
Alt_Shift_Tab: ; alt-shift-tab hotkey
; Tooltip % time("Alt_Tab_Common_Function", -1)
Alt_Tab_Common_Function(-1)
Return
Alt_Tab_Common_Function(dir) ; dir = "Alt_Tab" or "Alt_Shift_Tab"
{
Global
If Display_List_Shown =0
{
WinGet, Active_ID, ID, A
Gosub, Custom_Group__make_array_of_contents
GoSub, Display_Dim_Background
Gosub, Display_List
If Listview_Resize_Icons
Gosub, Alt_Tab_Common__Check_auto_switch_icon_sizes ; limit gui height / auto-switch icon sizes
Gosub, Alt_Tab_Common__Highlight_Active_Window
PrevRowText:=
If (Single_Key_Show_Alt_Tab_Used = "1" or ( GetKeyState(Alt_Hotkey2, "P") or GetKeyState(Alt_Hotkey2))) ; Alt key still pressed, else gui not shown
{
Gui_vx := Gui_CenterX()
Gui, 1: Show, AutoSize x%Gui_vx% y%Gui_y%, Alt-Tab Replacement
Hotkeys_Toggle_Temp_Hotkeys("On") ; (state = "On" or "Off") ; ensure hotkeys are on
}
LV_Modify(0, "Select Vis") ; get selected row and ensure selection is visible
}
;; Check for Alt Up
SetTimer, Check_Alt_Hotkey2_Up, 40
Selected_Row := LV_GetNext(0, "F")
Selected_Row += dir
If (Selected_Row > Window_Found_Count)
Selected_Row =1
If Selected_Row < 1
Selected_Row := Window_Found_Count
LV_Modify(Selected_Row, "Focus Select Vis") ; get selected row and ensure selection is visible
; Bring the focused lines window to the front
Get__Selected_Row_and_RowText()
Gui_wid := Window%RowText%
WinGet, OldExStyle, ExStyle, ahk_id %Gui_wid%
PPrevRowText:=(PrevRowText>RowText)?PrevRowText+1:RowText+1
WinSet, Top, , ahk_id %Gui_wid%
; Put previous window back in window stack
DllCall("SetWindowPos", "uint", Window%PrevRowText%, "uint", Window%PPrevRowText%
, "int", 0, "int", 0, "int", 0, "int", 0
, "uint", 0x13) ; NOSIZE|NOMOVE|NOACTIVATE (0x1|0x2|0x10)
WinSet, Top, , ahk_id %Gui4_ID%
WinGetClass, cla, ahk_id %Gui_wid%
if (cla !="ahk_class VirtualConsoleClass")
{
WinSet, AlwaysOnTop, On , ahk_id %Gui_wid%
WinSet, AlwaysOnTop, Off , ahk_id %Gui_wid%
}
; DllCall("SetForegroundWindow", "uint", Gui_wid)
WinSet, Top, , ahk_id %Gui_wid%
; WinGet, MinMax, MinMax, ahk_id %Gui_wid%
; ; Tooltip, %MinMax%
; If MinMax = -1
; {
; WinGetPos, minX, minY, minW, minH, ahk_id %Gui_wid%
; Coordmode, Tooltip, Screen
; ; 28, 29 SM_CXMIN, SM_CYMIN: Minimum width and height of a window, in pixels.
; ; 57, 58 SM_CXMINIMIZED, SM_CYMINIMIZED: Dimensions of a minimized window, in pixels.
; Sysget, MINX, 57, ahk_id %Gui_wid%
; ; Tooltip minX %minX% minY %minY% minW %minW% minH %minH% ahk_id %Gui_wid%, 0, 0
; }
; WinSet, Top,, ahk_id %Gui_wid%
; CoordMode, Tooltip, Screen
; Tooltip, % RowText . ":" . Title%RowText% . "|" . PrevRowText . ":" . Title%PrevRowText%, 0, 0
; PPrevRowText:=RowText
PrevRowText:=RowText
; Sometimes you lose the window
; WinSet, AlwaysOnTop, On, Alt-Tab Replacement
; Check if AlwaysOnTop status changed.
WinGet, ExStyle, ExStyle, ahk_id %Gui_wid%
if (OldExStyle ^ ExStyle) & 0x8
WinSet, AlwaysOnTop, Toggle, ahk_id %Gui_wid%
; GuiControl, Focus, Listview1 ; workaround for gui tab bug - gosub not activated when already activated button clicked on again
; Gosub, SB_Update__ProcessCPU
; SetTimer, SB_Update__ProcessCPU, 1000
Return
}
Alt_Tab_Common__Check_auto_switch_icon_sizes: ; limit gui height / auto-switch icon sizes
If (Listview_NowH > Height_Max AND Use_Large_Icons_Current =1) ; switch to small icons
{
Use_Large_Icons_Current =0
Gosub, Alt_Tab_Common__Switching_Icon_Sizes
}
If ((Listview_NowH * Small_to_Large_Ratio) < Height_Max AND Use_Large_Icons_Current =0 AND Use_Large_Icons=1) ; switch to large icons
{
Use_Large_Icons_Current =1
Gosub, Alt_Tab_Common__Switching_Icon_Sizes
}
Return
Alt_Tab_Common__Switching_Icon_Sizes:
Gosub, GuiControl_Disable_ListView1
Display_List_Shown =0
Gui, 1: Destroy
Gosub, Display_List
Gosub, GuiControl_Enable_ListView1
; Exit
Return
Alt_Tab_Common__Highlight_Active_Window:
Active_ID_Found =0 ; init
Loop, %Window_Found_Count% ; select active program in list (not always the top item)
{
LV_GetText(RowText, A_Index, 2) ; Get hidden column numbers
If (Window%RowText% = Active_ID)
{
Active_ID_Found :=A_Index
Break
}
}
If Active_ID_Found =0 ; active window has an icon in another main window & was excluded from Alt-Tab list
{
WinGet, Active_Process, ProcessName, ahk_id %Active_ID%
WinGetClass, Active_Class, ahk_id %Active_ID%
; If desktop/taskbar selected or nothing at all, don't select item in alt-tab list
If ( !(Active_Class ="Progman" OR Active_Class ="WorkerW" OR Active_Class ="Shell_TrayWnd" OR Active_Class =""))
Loop, %Window_Found_Count% ; find top item in window list with same exe name as active window
If (Exe_Name%A_Index% = Active_Process)
{
Active_ID := Window%A_Index% ; find this new ID in the listview
LV_GetText(RowText, A_Index, 2) ; Get hidden column numbers
If (Window%RowText% = Active_ID)
{
Active_ID_Found :=A_Index
Break
}
}
}
If Active_ID_Found !=0
LV_Modify(Active_ID_Found, "Focus Select Vis")
Return
Single_Key_Show_Alt_Tab:
Single_Key_Show_Alt_Tab_Used =1
Send, {%Alt_Hotkey2% down}
Gosub, Alt_Tab
Hotkey, *%Single_Key_Hide_Alt_Tab%, ListView_Destroy, On
Return
Alt_Esc: ; abort switching
Alt_Esc =1
Gosub, ListView_Destroy
Return
Alt_Esc_Check_Alt_State: ; hides alt-tab gui - shows again if alt still pressed
Gosub, Alt_Esc
If ( GetKeyState(Alt_Hotkey2, "P") or GetKeyState(Alt_Hotkey2)) ; Alt key still pressed - show alt-tab again
Gosub, Alt_Tab
Return
Hotkeys_Toggle_Temp_Hotkeys(state) ; (state = "On" or "Off")
{
Global
; UseErrorLevel in case of exiting script before hotkey created
Hotkey, %Alt_Hotkey%%Use_AND_Symbol%%Esc_Hotkey%, Alt_Esc, %state% UseErrorLevel ; abort
If Use_Wheel_Scroll_List =1
{
Hotkey, %Alt_Hotkey%%Use_AND_Symbol%WheelUp, Alt_Shift_Tab, %state% UseErrorLevel ; previous window
Hotkey, %Alt_Hotkey%%Use_AND_Symbol%WheelDown, Alt_Tab, %state% UseErrorLevel ; next window
}
Hotkey, %Alt_Hotkey%%Use_AND_Symbol%Mbutton, MButton_Close, %state% UseErrorLevel ; close the window clicked on
Hotkey, *~LButton, LButton_Tab_Check, %state% UseErrorLevel ; check if user clicked/dragged a tab
}
Check_Alt_Hotkey2_Up:
If ! ( GetKeyState(Alt_Hotkey2, "P") or GetKeyState(Alt_Hotkey2)) ; Alt key released
Gosub, ListView_Destroy
Return
;========================================================================================================
Display_List:
LV_ColorChange() ; clear all highlighting
if Hide_Other_Group
Tab_Shown = %Group_Active%
else
Tab_Shown = %Group_Shown%
If Display_List_Shown =1 ; empty listview and image list if only updating - e.g. when closing a window (mbutton)
LV_Delete()
Else ; not shown - need to create gui for updating listview
{
; Create the ListView gui
Gui, 1: +AlwaysOnTop +ToolWindow -Caption
Gui, 1: Color, %Tab_Colour% ; i.e. border/background
Gui, 1: Margin, 0, 0
; Tab stuff
; Gui, 1: Add, StatusBar, Background%StatusBar_Background_Colour% ; add before changing font
Gui, 1: Font, s%Font_Size% c%Font_Color% %Font_Style%, %Font_Type%
Gui, 1: Add, ListView, x-1 y+-4 w%Listview_Width% AltSubmit -Redraw -Multi NoSort Background%Listview_Colour% Count10 gListView_Event vListView1 HWNDhw_LV_ColorChange,%Col_Title_List%
; Gui, 1:Default
LV_ModifyCol(2, "Integer") ; sort hidden column 2 as numbers
; SB_SetParts(SB_Width, SB_Width, SB_Width)
; Gosub, SB_Update__CPU
; SetTimer, SB_Update__CPU, 1000
Gui, 1: Font, s%Font_Size_Tab% c%Font_Color% bold, %Font_Type_Tab%
Gui, 1: Add, Tab2, Bottom vGui1_Tab HWNDhw_Gui1_Tab w%Gui1_Tab__width% h22 -0x200 -Multi, %Group_List% ; -0x200 = ! TCS_MULTILINE
Gui, 1:+LastFound
WinSet, Transparent, 240
; Winset, TransColor, %Tab_Colour% 150 ; i.e. border/background
; WinSet, Transparent,65 , ahk_id %hw_LV_ColorChange%
; Winset, TransColor, %Tab_Colour% 150, ahk_id %hw_LV_ColorChange%; i.e. border/background
}
GuiControl,, Gui1_Tab, |%Group_List% ; update in case of changes
GuiControl, ChooseString, Gui1_Tab2, %Group_Active%
ImageListID1 := IL_Create(10,5,Use_Large_Icons_Current) ; Create an ImageList so that the ListView can display some icons
LV_SetImageList(ImageListID1, 1) ; Attach the ImageLists to the ListView so that it can later display the icons
Gosub, Display_List__Find_windows_and_icons
If Window_Found_Count =0
{
Window_Found_Count =1
LV_Add("","","","","","","") ; No Windows Found! - avoids an error on selection if nothing is added
}
ColumnClickSort(Sort_By_Column, "") ; Col = column clicked on, Update = 1 if true else blank (apply only, not change order)
Gosub, Gui_Resize_and_Position
If Display_List_Shown =1 ; resize gui for updating listview
{
Gui_vx := Gui_CenterX()
Gui, 1: Show, AutoSize x%Gui_vx% y%Gui_y%, Alt-Tab Replacement
If Selected_Row >%Window_Found_Count% ; less windows now - select last one instead of default 1st row
Selected_Row =%Window_Found_Count%
LV_Modify(Selected_Row, "Focus Select Vis") ; select 1st entry since nothing selected
}
Display_List_Shown =1 ; Gui 1 is shown back in Alt_Tab_Common_Function() for initial creation
Return
Display_Dim_Background:
; define background GUI to dim all active applications
SysGet, Width, 78
SysGet, Height, 79
SysGet, X0, 76
SysGet, Y0, 77
; Background GUI used to show foremost window
Gui, 4: +LastFound -Caption +ToolWindow
Gui, 4: Color, Black
Gui, 4: Show, Hide
WinSet, Transparent, 120
Gui, 4: Show, NA x%X0% y%Y0% w%Width% h%Height%
Gui4_ID := WinExist() ; for auto-sizing columns later
return
Display_List__Find_windows_and_icons:
if PID_Filter !=
{
WinGet, Window_List, List, ahk_pid %PID_Filter%
}
else {
WinGet, Window_List, List ; Gather a list of running programs
}
Window_Found_Count =0
Window_Found_Count_For_Top_Recent=0
; GuiControl, -Redraw, ListView1
Loop, %Window_List%
{
;TODO: filter according to process name
wid := Window_List%A_Index%
WinGetTitle, wid_Title, ahk_id %wid%
If ((Style & WS_DISABLED) or ! (wid_Title)) ; skip unimportant windows ; ! wid_Title or
Continue
WinGet, es, ExStyle, ahk_id %wid%
WinGetClass, cla, ahk_id %wid%
Parent := Decimal_to_Hex( DllCall( "GetParent", "uint", wid ) )
If ((es & WS_EX_TOOLWINDOW) and !(Parent)) or (es =0x00200008) ; filters out program manager, etc
continue
WinGet, Style_parent, Style, ahk_id %Parent%
Owner := Decimal_to_Hex( DllCall( "GetWindow", "uint", wid , "uint", "4" ) ) ; GW_OWNER = 4
WinGet, Style_Owner, Style, ahk_id %Owner%
If (!( es & WS_EX_APPWINDOW ))
{
; NOTE - some windows result in blank value so must test for zero instead of using NOT operator!
If ((Parent) and ((Style_parent & WS_DISABLED) =0)) ; filter out windows that have a parent
continue
If ((Owner) and ((Style_Owner & WS_DISABLED) =0)) ; filter out owner window that is NOT disabled -
continue
; This filter's logic is copy from the internet, I don't know the detail.
If ( Owner or ( es & WS_EX_TOOLWINDOW ))
{
WinGetClass, Win_Class, ahk_id %wid%
If ( ! ( Win_Class ="#32770" ) )
Continue
}
}
WinGet, Exe_Name, ProcessName, ahk_id %wid%
WinGetClass, Win_Class, ahk_id %wid%
hw_popup := Decimal_to_Hex(DllCall("GetLastActivePopup", "uint", wid))
Window_Found_Count_For_Top_Recent += 1
if Window_Found_Count_For_Top_Recent !=2 ; the last window will escap from GROUP FILTERING
{
; CUSTOM GROUP FILTERING
If (Group_Active != "ALL") ; i.e. list is filtered, check filter contents to include
{
Custom_Group_Include_wid_temp = ; initialise/reset
Loop, %Group_Active_0% ; check current window id against the list to filter
{
Loop_Item := Group_Active_%A_Index%
StringLeft, Exclude_Item, Loop_Item, 1
If Exclude_Item =! ; remove ! for matching strings
StringTrimLeft, Loop_Item, Loop_Item, 1
If ((Loop_Item = Exe_Name) or InStr(wid_Title, Loop_Item)) ; match exe name, title
{
Custom_Group_Include_wid_temp =1 ; include this window
Break
}
}
If (((Custom_Group_Include_wid_temp =1) and (Exclude_Item ="!"))
or ((Custom_Group_Include_wid_temp !=1) and (Exclude_Not_In_List =1)))
Continue
}
}
Dialog =0 ; init/reset
If (Parent and ! Style_parent)
CPA_file_name := GetCPA_file_name( wid ) ; check if it's a control panel window
Else
CPA_file_name =
If (CPA_file_name or (Win_Class ="#32770") or ((style & WS_POPUP) and (es & WS_EX_DLGMODALFRAME)))
Dialog =1 ; found a Dialog window
If (CPA_file_name)
{
Window_Found_Count += 1
Gui_Icon_Number := IL_Add( ImageListID1, CPA_file_name, 1 )
}
Else
Get_Window_Icon(wid, Use_Large_Icons_Current) ; (window id, whether to get large icons)
Window__Store_attributes(Window_Found_Count, wid, "") ; Index, wid, parent (or blank if none)
LV_Add("Icon" . Window_Found_Count,"", Window_Found_Count, Title%Window_Found_Count%, Exe_Name%Window_Found_Count%, State%Window_Found_Count%, OnTop%Window_Found_Count%, Status%Window_Found_Count%)
}
GuiControl, +Redraw, ListView1
GuiControl,, Gui1_Tab, |%Group_List% ; update in case of changes
GuiControl, ChooseString, Gui1_Tab2, %Group_Active%
Return
Window__Store_attributes(Index, wid, ID_Parent) ; Index = Window_Found_Count, wid = window id, ID_Parent = parent or blank if none
{
Local State_temp
Window%Index% =%wid% ; store ahk_id's to a list
Window_Parent%Index% =%ID_Parent% ; store Parent ahk_id's to a list to later see if window is owned
Title%Index% := wid_Title ; store titles to a list
hw_popup%Index% := hw_popup ; store the active popup window to a list (eg the find window in notepad)
WinGet, Exe_Name%Index%, ProcessName, ahk_id %wid% ; store processes to a list
WinGet, PID%Index%, PID, ahk_id %wid% ; store pid's to a list
Dialog%Index% := Dialog ; 1 if found a Dialog window, else 0
WinGet, State_temp, MinMax, ahk_id %wid%
If State_temp =1
State%Index% =Max
Else If State_temp =-1
State%Index% =Min
Else If State_temp =0
State%Index% =
WinGet, es_hw_popup, ExStyle, ahk_id %hw_popup% ; eg to detect on top status of zoomplayer window
If ((es & 0x8) or (es_hw_popup & 0x8)) ; 0x8 is WS_EX_TOPMOST.
{
OnTop%Index% =Top
OnTop_Found =1
}
Else
OnTop%Index% =
If Responding
Status%Index% =
Else
{
Status%Index% =Not Responding
Status_Found =1
}
; Listview Higlighting Colours
If Status%Index% =Not Responding
LV_ColorChange(Index, Listview_Colour_Not_Responding_Text, Listview_Colour_Not_Responding_Back)
Else If Dialog%Index%
LV_ColorChange(Index, Listview_Colour_Dialog_Text, Listview_Colour_Dialog_Back)
Else If OnTop%Index% =Top
LV_ColorChange(Index, Listview_Colour_OnTop_Text, Listview_Colour_OnTop_Back)
Else If State%Index% =Max
LV_ColorChange(Index, Listview_Colour_Max_Text, Listview_Colour_Max_Back)
Else If State%Index% =Min
LV_ColorChange(Index, Listview_Colour_Min_Text, Listview_Colour_Min_Back)
}
LButton_Tab_Check:
Tab_Button_Clicked := TCM_HITTEST()
If Tab_Button_Clicked
{
Tab_Button_Clicked_Text := Tab_Button_Get_Text(Tab_Button_Clicked)
if not Hide_Other_Group
SetTimer, Tab__Drag_and_Drop, 60 ; check status of drag operation
}
Return
Tab__Drag_and_Drop:
If ! GetKeyState("LButton")
{
SetTimer, Tab__Drag_and_Drop, Off
Group_Active := Tab_Button_Clicked_Text
Gosub, Gui_Window_Group_Load__part2
Return
}
If TCM_HITTEST()
Tab_Button_Over := TCM_HITTEST()
Tab_Button_Over_Text := Tab_Button_Get_Text(Tab_Button_Over)
If (Tab_Button_Over < Tab_Button_Clicked)
Tab_Swap(Group_Shown, Tab_Button_Clicked_Text, Tab_Button_Over_Text)
Else If (Tab_Button_Over > Tab_Button_Clicked)
Tab_Swap(Group_Shown, Tab_Button_Over_Text, Tab_Button_Clicked_Text)
Return
Tab_Swap(ByRef Tab_List, ByRef Text1, ByRef Text2)
{
Global
StringReplace, Tab_List, Tab_List, %Text1% , %Text2%
StringReplace, Tab_List, Tab_List, %Text2% , %Text1%
Tab_Button_Clicked := Tab_Button_Over ; update
GuiControl,, Gui1_Tab, |%Group_Shown% ; This function must not been called when Hide_Other_Group is 1.
GuiControl, ChooseString, Gui1_Tab, %Tab_Button_Clicked_Text%
}
TCM_HITTEST() ; returns 1-based index of clicked tab
{
Global hw_Gui1_Tab
MouseGetPos, mX, mY, hWnd, Control, 2
If (Control != hw_Gui1_Tab) ; not clicked on tab control
Return, False
ControlGetPos, cX, cY,,,, ahk_id %Control%
x:=mX-cX, y:=mY-cY ; co-ordinatess relative to tab control
VarSetCapacity(lparam, 12, 0)
NumPut(x, lparam, 0, "Int")
NumPut(y, lparam, 4, "Int")
SendMessage, 0x130D, 0, &lparam,, ahk_id %Control% ; TCM_HITTEST
result := ErrorLevel ; 0-based index, FAIL, or 0xFFFFFFFF (in a tab but not the button)
If (result = "FAIL" or result = 0xFFFFFFFF)
Return, False
Else
Return, result + 1 ; change to 1-based index
}
Tab_Button_Get_Text(Tab_Index)
{
Global
If Tab_Index
Loop, Parse, Tab_Shown,|
If (A_Index = Tab_Index)
Return, A_LoopField
}
Gui_Resize_and_Position:
DetectHiddenWindows, On ; retrieving column widths to enable calculation of col 3 width
Gui, +LastFound
Gui_ID := WinExist() ; for auto-sizing columns later
If Display_List_Shown =0 ; resize listview columns - no need to resize columns for updating listview
{
LV_ModifyCol(1, Col_1) ; icon column
LV_ModifyCol(2, Col_2) ; hidden column for row number
; col 3 - see below
LV_ModifyCol(4, Col_4) ; exe
SendMessage, 0x1000+29, 3, 0,, ahk_id %hw_LV_ColorChange% ; LVM_GETCOLUMNWIDTH is 0x1000+29
Width_Column_4 := ErrorLevel
If Width_Column_4 > %Exe_Width_Max%
LV_ModifyCol(4, Exe_Width_Max) ; resize title column
LV_ModifyCol(5, Col_5) ; State
If OnTop_Found
LV_ModifyCol(6, Col_6) ; OnTop
Else
LV_ModifyCol(6, 0) ; OnTop
If Status_Found
LV_ModifyCol(7, Col_7) ; Status
Else
LV_ModifyCol(7, 0) ; Status
Loop, 7
{
SendMessage, 0x1000+29, A_Index -1, 0,, ahk_id %hw_LV_ColorChange% ; LVM_GETCOLUMNWIDTH is 0x1000+29
Width_Column_%A_Index% := ErrorLevel
}
Col_3_w := Listview_Width - Width_Column_1 - Width_Column_2 - Width_Column_4 - Width_Column_5 - Width_Column_6 - Width_Column_7 - 4 ; total width of columns - 4 for border
LV_ModifyCol(3, Col_3_w) ; resize title column
}
ListView_Resize_Vertically(Gui_ID) ; Automatically resize listview vertically - pass the gui id value
GuiControlGet, Listview_Now, Pos, ListView1 ; retrieve listview dimensions/position ; for auto-sizing (elsewhere)
; resize listview according to scrollbar presence
; If (Listview_NowH > Height_Max AND Use_Large_Icons_Current =0) ; already using small icons so limit height
If (Listview_NowH > Height_Max) ; limit height to specified fraction of window size
{
Col_3_w -= Scrollbar_Vertical_Thickness ; allow for vertical scrollbar being visible
LV_ModifyCol(3, Col_3_w) ; resize title column
; GuiControl, MoveDraw, Gui1_Tab
GuiControl, Move, ListView1, h%Height_Max%
}
DetectHiddenWindows, Off
Return
SB_Update__CPU:
Format_Float := A_FormatFloat
SetFormat, Float, 4.1
SB_SetText( "CPU (%): " GetSystemTimes(), 1)
SetFormat, Float, %Format_Float%
Return
SB_Update__ProcessCPU:
Format_Float := A_FormatFloat
SetFormat, Float, 4.1
Get__Selected_Row_and_RowText()
SB_SetText( "Process CPU (%): " GetProcessTimes(PID%RowText%), 2)
SetFormat, Float, %Format_Float%
Return
Get__Selected_Row_and_RowText()
{
Global
If ListView1__Disabled = 1 ; don't update - for statusbar (timer)
Return
Selected_Row := LV_GetNext(0, "F")
LV_GetText(RowText, Selected_Row, 2) ; Get the row's 2nd column's text for real order number (hidden column).
}
;========================================================================================================
ListView_Event:
Critical, 50
If MButton_Clicked =1 ; closing a window so don't process events
Return
If A_GuiEvent =DoubleClick ; activate clicked window
Gosub, ListView_Destroy
If A_GuiEvent =K ; letter was pressed, select next window name starting with that letter
Gosub, Key_Pressed_1st_Letter
If A_GuiEvent =ColClick ; column was clicked - do custom sort to allow for sorting hidden column + remembering state
ColumnClickSort(A_EventInfo) ; A_EventInfo = column clicked on
Return
GuiContextMenu: ; right-click or press of the Apps key -> displays the menu only for clicks inside the ListView
If Menu__Gui_1 ; destroy previously generated menus
Get__Selected_Row_and_RowText()
Gui_wid := Window%RowText%
Gui_wid_Title :=Title%RowText%
StringLeft, Gui_wid_Title, Gui_wid_Title, 40
Menu, Tray, UseErrorLevel
; Clear previous entries
Menu, ContextMenu1, DeleteAll
Menu, Gui_MinMax_Windows, DeleteAll
Menu, Gui_Un_Exclude_Windows, DeleteAll
Menu, Gui_Window_Group_Load, DeleteAll
Menu, Gui_Window_Group_Delete, DeleteAll
Menu, Gui_Processes, DeleteAll
Menu, Gui_Settings_Help, DeleteAll
; Min/Max windows
Menu, Gui_MinMax_Windows, Add, % "Maximize all: " Exe_Name%RowText%, Gui_MinMax_Windows
Menu, Gui_MinMax_Windows, Add, % "Minimize all: " Exe_Name%RowText%, Gui_MinMax_Windows
Menu, Gui_MinMax_Windows, Add
Menu, Gui_MinMax_Windows, Add, % "Normal all: " Exe_Name%RowText%, Gui_MinMax_Windows
Menu, ContextMenu1, Add, &Min / Max, :Gui_MinMax_Windows
; Window Group sub-menu entry
Menu, ContextMenu1, Add ; spacer
Menu, ContextMenu1, Add, Group - &No Filter, Gui_Window_Group_No_Filter
If (Group_Active != "ALL")
Menu, ContextMenu1, Disable, Group - &No Filter
Loop, Parse, Group_List,|
Menu, Gui_Window_Group_Load, Add,%A_LoopField%, Gui_Window_Group_Load
Menu, Gui_Window_Group_Load, Check, %Group_Active%
Menu, ContextMenu1, Add, Group - &Load, :Gui_Window_Group_Load
Menu, ContextMenu1, Add, Group - &Save/Edit, Gui_Window_Group_Save_Edit
Menu, ContextMenu1, Add, Group - Global &Include, Gui_Window_Group_Global_Include
Menu, ContextMenu1, Add, Group - Global &Exclude, Gui_Window_Group_Global_Exclude
Loop, Parse, Group_List,|
If (A_LoopField != "ALL")
Menu, Gui_Window_Group_Delete, Add,%A_LoopField%, Gui_Window_Group_Delete
Menu, Gui_Window_Group_Delete, Check, %Group_Active%
Menu, Gui_Window_Group_Delete, Color, E10000, Single ; warning colour
Menu, ContextMenu1, Add, Group - &Delete, :Gui_Window_Group_Delete
; Hotkeys entry
Menu, ContextMenu1, Add ; spacer
Menu, ContextMenu1, Add, &Hotkeys, Gui_Hotkeys
; Processes entry
Menu, ContextMenu1, Add ; spacer
Menu, Gui_Processes, Add, % "End: " Gui_wid_Title, End_Process_Single
Menu, Gui_Processes, Add ; spacer
Menu, Gui_Processes, Add, % "End All: " Exe_Name%RowText%, End_Process_All_Instances
Menu, Gui_Processes, Color, E10000, Single ; warning colour
Menu, ContextMenu1, Add, &Processes, :Gui_Processes
; Help + Latest changes
Menu, ContextMenu1, Add ; spacer
Menu, Gui_Settings_Help, Add, Delete Settings (.ini) && Reload, Delete_Ini_File_Settings
Menu, Gui_Settings_Help, Add, ; spacer
Menu, Gui_Settings_Help, Add, Help, HELP_and_LATEST_VERSION_CHANGES
Menu, Gui_Settings_Help, Add, Latest Changes, HELP_and_LATEST_VERSION_CHANGES
Menu, ContextMenu1, Add, Settings && Help, :Gui_Settings_Help
; Exit entry
Menu, ContextMenu1, Add ; spacer
Menu, ContextMenu1, Add, &Exit, OnExit_Script_Closing
Menu, ContextMenu1, Show, %A_GuiX%, %A_GuiY%
Return
Gui_MinMax_Windows:
Gosub, GuiControl_Disable_ListView1
List_of_Process_To_MinMax = ; need to store list now as re-drawing the listview over-writes necessary variables
Loop, %Window_Found_Count%
{
If ( Exe_Name%A_Index% = Exe_Name%RowText% and ! Dialog%A_Index% ) ; don't try to act on dialog windows (e.g. save prompts)
List_of_Process_To_MinMax .= "|" . Window%A_Index%
}
StringTrimLeft, List_of_Process_To_MinMax, List_of_Process_To_MinMax, 1 ; remove 1st | character (empty reference otherwise)
If A_ThisMenuItem contains Maximize
MinMax_Message =0xF030 ; SC_MAXIMIZE
Else If A_ThisMenuItem contains Minimize
MinMax_Message =0xF020 ; SC_MINIMIZE
Else If A_ThisMenuItem contains Normal
MinMax_Message =0xF120 ; SC_RESTORE
Loop, Parse, List_of_Process_To_MinMax,|
PostMessage, 0x112, %MinMax_Message%,,, ahk_id %A_LoopField% ; 0x112 = WM_SYSCOMMAND
Sleep, 50 ; wait for min/max state to change otherwise updated listview will be wrong
Gosub, Display_List
Gosub, GuiControl_Enable_ListView1
Return
GuiControl_Disable_ListView1:
OnMessage( 0x06, "" ) ; turn off: no alt tab list window lost focus -> hide list
ListView1__Disabled = 1
GuiControl, Disable, ListView1
Return
GuiControl_Enable_ListView1:
GuiControl, Enable, ListView1
GuiControl, Focus, ListView1
ListView1__Disabled = 0
OnMessage( 0x06, "WM_ACTIVATE" ) ; turn on again - alt tab list window lost focus > hide list
Return
; HOTKEYS MENU SECTION:
;============================================================================================================================
#If WinActive("Alt-Tab Replacement ahk_class AutoHotkeyGUI")
!1:: ColumnClickSort(1, 1) ;
!2:: ColumnClickSort(3, 1) ;
!3:: ColumnClickSort(4, 1) ;
!4:: ColumnClickSort(5, 1) ; Sort by window
#If
Gui_Hotkeys:
Gosub, Alt_Esc
Gui, 2: Default ; for listview operations
Gui, 2: Font, s10
Gui, 2: Add, Text, xm y+15, Main hotkeys:
Gui, 2: Font
Gui, 2: Add, Text, x+5 yp+2, (Note that "Alt" must be either Alt, Ctrl, Shift, Win or mouse XButton1 / 2 - but using XButton requires "Shift+Tab" is a single key!)
Gui, 2: Add, Checkbox, vScroll_In_Taskbar Checked%Scroll_In_Taskbar% xm+188, Scorll in taskbar to active AltTab?
Gui, 2: Add, Checkbox, vNo_Tray_Icon Checked%No_Tray_Icon% xp+300, Hide Tray Icon?
; Gui_Add_Hotkey(Gui number, Text, Comment, variable name)
Gui_Add_Hotkey(2, "Alt","(key in Alt+Tab)", "Alt_Hotkey")
GuiControl, 2: Disable, Alt_Hotkey_Tab
GuiControl, 2: Disable, Alt_Hotkey_Esc
GuiControl, 2: Disable, Alt_Hotkey_Enter
GuiControl, 2: Disable, Alt_Hotkey_WheelUp
GuiControl, 2: Disable, Alt_Hotkey_WheelDown
GuiControl, 2: Disable, Alt_Hotkey_Hotkey
Gui_Add_Hotkey(2, "Tab","(key in Alt+Tab)", "Tab_Hotkey")
Gui_Add_Hotkey(2, "Shift+Tab","(Key(s) in Alt+Shift+Tab)", "Shift_Tab_Hotkey")
Gui_Add_Hotkey(2, "Esc","(key in Alt+Esc)", "Esc_Hotkey")
Gui, 2: Font, s10
Gui, 2: Add, Text,xm y+15, Single keys:
Gui, 2: Font
Gui, 2: Add, Text, x+5 yp+2, (Alternative way to show the Alt+Tab list by 1 key (blank for no hotkey) and another for selection)
Gui_Add_Hotkey(2, "Alt+Tab list", "", "Single_Key_Show_Alt_Tab")
Gui_Add_Hotkey(2, "Alt+Tab selection", "", "Single_Key_Hide_Alt_Tab")
Gui, 2: Font, s10
Gui, 2: Add, Text,xm y+30, Group TabKeys:
Gui, 2: Font
GuiControl, 2: Focus, Static1
Gui, 2: Add, ListView, section xm r15 w470 -Multi, Group name|Assigned TabKey
Loop, Parse, Group_List, |
LV_Add("", A_LoopField, %A_LoopField%_Group_TabKey)
Gui, 2: Add, Button, x+10 yp+40 gGui_2_Group_TabKey_Assign w170, Assign TabKey to selected group:
Gui, 2: Add, Hotkey, vGui_2_Group_TabKey xp y+5,
Gui, 2: Add, Checkbox, vGui_2_Group_TabKey_WinNeed Checked0 , Win key Need?
Gui, 2: Add, Button, xp y+30 gGui_2_Group_TabKey_Clear w170, Clear TabKey of selected group
Gui, 2: Add, Text, xp y+30, ( Key: !=Alt, ^=Ctrl, +=Shift, #=Win )
Gui, 2: Add, Text, xm+250, WARNING! No error checking for hotkeys - be careful what you choose! (Delete the .ini file to reset settings)
Gui, 2: Add, Button, xm+430 g2GuiClose w100, &Cancel
Gui, 2: Add, Button, x+20 gGui_2_OK wp Default, &OK
Gui, 2: Show,, Hotkeys
Return
Gui_2_Group_TabKey_Assign:
Gui, 2: Submit, NoHide
Selected_Row := LV_GetNext(0, "F")
If (! Selected_Row or ! Gui_2_Group_TabKey)
Return
if Gui_2_Group_TabKey_WinNeed
{
IfNotInString, #, %Gui_2_Group_TabKey%
_Actual_Hotkey = #%Gui_2_Group_TabKey%