通过 AutoHotKey 快速且精确地切换虚拟桌面
2022-02-06 07:30:43

AutoHotKey(下文统称 AHK)是一款 Windows 平台下自由开源、用于定义键盘快捷键的利器。以前通过 AHK 实现通过键盘唤醒浏览器、terminal 和 VSCode 等一系列程序,在一定程度上抛弃了鼠标

且修改了 Windows 自定义的用于切换虚拟桌面的快捷键,改到了更顺手的位置;但是只实现左右切换,当需要切换到特定虚拟桌面时,仍然需要多次按键

这次的主要目标是实现对特定虚拟桌面的切换,精准地一次定位到所特定虚拟桌面

主要是通过 这篇教程 实现


2022-2-22更新:

推荐相关项目 windows-desktop-switcher


原理

Windows 自己实现的虚拟桌面切换快捷键,只能依次切换

此脚本的本质,应当是对当前虚拟桌面进行定位,然后根据待切换虚拟桌面的标号,进行多次切换

编码

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
DesktopCount = 2 ; Windows starts with 2 desktops at boot
CurrentDesktop = 1 ; Desktop count is 1-indexed (Microsoft numbers them this way)
mapDesktopsFromRegistry() {
global CurrentDesktop, DesktopCount
IdLength := 32
SessionId := getSessionId()
if (SessionId) {
RegRead, CurrentDesktopId, HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SessionInfo\%SessionId%\VirtualDesktops, CurrentVirtualDesktop
if (CurrentDesktopId) {
IdLength := StrLen(CurrentDesktopId)
}
}
RegRead, DesktopList, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VirtualDesktops, VirtualDesktopIDs
if (DesktopList) {
DesktopListLength := StrLen(DesktopList)
DesktopCount := DesktopListLength / IdLength
}
else {
DesktopCount := 1
}
i := 0
while (CurrentDesktopId and i < DesktopCount) {
StartPos := (i * IdLength) + 1
DesktopIter := SubStr(DesktopList, StartPos, IdLength)
OutputDebug, The iterator is pointing at %DesktopIter% and count is %i%.
if (DesktopIter = CurrentDesktopId) {
CurrentDesktop := i + 1
OutputDebug, Current desktop number is %CurrentDesktop% with an ID of %DesktopIter%.
break
}
i++
}
}
getSessionId()
{
ProcessId := DllCall("GetCurrentProcessId", "UInt")
if ErrorLevel {
OutputDebug, Error getting current process id: %ErrorLevel%
return
}
OutputDebug, Current Process Id: %ProcessId%
DllCall("ProcessIdToSessionId", "UInt", ProcessId, "UInt*", SessionId)
if ErrorLevel {
OutputDebug, Error getting session id: %ErrorLevel%
return
}
OutputDebug, Current Session Id: %SessionId%
return SessionId
}
switchDesktopByNumber(targetDesktop)
{
global CurrentDesktop, DesktopCount
mapDesktopsFromRegistry()
if (targetDesktop > DesktopCount || targetDesktop < 1) {
OutputDebug, [invalid] target: %targetDesktop% current: %CurrentDesktop%
return
}
while(CurrentDesktop < targetDesktop) {
Send ^#{Right}
CurrentDesktop++
OutputDebug, [right] target: %targetDesktop% current: %CurrentDesktop%
}
while(CurrentDesktop > targetDesktop) {
Send ^#{Left}
CurrentDesktop--
OutputDebug, [left] target: %targetDesktop% current: %CurrentDesktop%
}
}
createVirtualDesktop()
{
global CurrentDesktop, DesktopCount
Send, #^d
DesktopCount++
CurrentDesktop = %DesktopCount%
OutputDebug, [create] desktops: %DesktopCount% current: %CurrentDesktop%
}
deleteVirtualDesktop()
{
global CurrentDesktop, DesktopCount
Send, #^{F4}
DesktopCount--
CurrentDesktop--
OutputDebug, [delete] desktops: %DesktopCount% current: %CurrentDesktop%
}
SetKeyDelay, 75
mapDesktopsFromRegistry()
OutputDebug, [loading] desktops: %DesktopCount% current: %CurrentDesktop%

!1::switchDesktopByNumber(1)
!2::switchDesktopByNumber(2)
!3::switchDesktopByNumber(3)
!4::switchDesktopByNumber(4)
!5::switchDesktopByNumber(5)
!6::switchDesktopByNumber(6)
!7::switchDesktopByNumber(7)
!8::switchDesktopByNumber(8)
!9::switchDesktopByNumber(9)

说明

我这里主要是通过Alt + number定位到待切换的虚拟桌面,如果需要定义其他快捷键可以参考以下方式:

  • 通过Win + number切换
1
2
3
4
5
6
7
8
9
LWin & 1::switchDesktopByNumber(1)
LWin & 2::switchDesktopByNumber(2)
LWin & 3::switchDesktopByNumber(3)
LWin & 4::switchDesktopByNumber(4)
LWin & 5::switchDesktopByNumber(5)
LWin & 6::switchDesktopByNumber(6)
LWin & 7::switchDesktopByNumber(7)
LWin & 8::switchDesktopByNumber(8)
LWin & 9::switchDesktopByNumber(9)
  • 通过CAPSLOCK + number切换
1
2
3
4
5
6
7
8
9
CapsLock & 1::switchDesktopByNumber(1)
CapsLock & 2::switchDesktopByNumber(2)
CapsLock & 3::switchDesktopByNumber(3)
CapsLock & 4::switchDesktopByNumber(4)
CapsLock & 5::switchDesktopByNumber(5)
CapsLock & 6::switchDesktopByNumber(6)
CapsLock & 7::switchDesktopByNumber(7)
CapsLock & 8::switchDesktopByNumber(8)
CapsLock & 9::switchDesktopByNumber(9)

可以预见,限制为 1 至 9 号虚拟桌面。实际上应该够用,五个桌面就差不多了,切到 9,手都需要跨越大半个键盘了(笑

2022-02-06_20-22-32