Matrix 首页推荐 

Matrix 是少数派的写作社区,我们主张分享真实的产品体验,有实用价值的经验与思考。我们会不定期挑选 Matrix 最优质的文章,展示来自用户的最真实的体验和观点。

文章代表作者个人观点,少数派仅对标题和排版略作修改。


很长时间以来,Mac 是我唯一的学习、办公和娱乐电脑。最近,由于工作的关系,必须用一台 Windows 电脑办公。因此,我不得不白天在 Windows 电脑上工作,晚上回家换回我的 Mac。我是一个喜欢使用快捷键的人,切换使用难免会有各种误操作。一些在 macOS 上用惯了的功能,在 Windows 上没有直接的替代品。

我曾经在之前的一篇文章中,介绍过我在使用 Mac 远程连接 Windows 时,用 AutoHotkey 修改了部分 Windows 快捷键。不过,当时的情况仍有别于现在。在远程操作时,我是同时使用 Mac 和 Windows 的。得益于远程操作下共用剪贴板的效果,相当一部分我认为远程不便利的操作,我是在 Mac 上完成的,这包括上网、打字、使用通讯工具等。而在完全使用 Windows 电脑办公时,我需要在上面完成所有操作,有必要对其进一步做改造。这篇文章的内容,正是建立在这一背景下的。

以下是本文的目录。可以看出,本文的主要内容是介绍我对 Windows 系统的折腾改造。目标是统一我在 Windows 电脑和 Mac 上的操作方式。与此同时,我也有意地按照探索使用这些工具的深入程度,来安排本文内容的顺序。因此,本文至少也可以被视为一份 AutoHotkey 的学习笔记。文章的最后,我会比较完整地给出一份自己使用的 AutoHotkey 脚本。此外,本文也将会介绍个别我在 Mac 和 Windows 系统上为了提高效率而使用的软件。希望不论是 Mac + Windows 用户,还是仅仅使用其中一个操作系统的用户,都能够在阅读这篇文章后有一点点收获。

  • 在绝大部分情况下交换 Ctrl 和 Alt:初识 PowerToys 与 AutoHotkey
  • 关闭窗口,退出应用程序:AutoHotkey 中的 Windows Spy、#HotIf
  • Windows 中的预览功能:PowerToys 中的速览,AutoHotkey 中的 Suspend、if、A_PriorKey
  • 在 Windows 中使用「Spotlight」:PowerToys 中的 PowerToys Run
  • Caps 按键切换中英文:AutoHotkey 中的 #UseHook($)
  • 缩写与无格式粘贴:aText , AutoHotkey 中的热字串、A_Clipboard
  • 翻译和文本提取:Mac 上的 Bob,PowerToys Run 翻译插件和 PowerToys 的文本提取器
  • 其它快捷键:AutoHotkey 中的 Run、FileRecycleEmpty……

需要说明的是,我这台工作电脑的配置可能是比较差的,系统版本为 Windows 10 专业版。如何形容这台电脑的日常体验呢,就是稍微多开几个文档就卡,如果不修改鼠标设置的话,卡的时候连左键双击都无法正常被识别,这也是我必须得在这电脑上使用键盘快捷键的原因之一。因此,以下部分涉及实际体验的内容,可能因电脑情况而有差异。

在绝大部分情况下交换 Ctrl 和 Alt:初识 PowerToys 与 AutoHotkey

在 Mac 键盘上,空格键的左边是 Command 键,这个按键承担了大部分 Windows 系统中 Ctrl 键的功能。例如,复制、粘贴,在 Mac 下是 Command + C / V,在 Windows 中是 Ctrl + C / V。对我而言,空格键左边的按键是打字时大拇指可以触碰到的位置,用来实现这些快捷功能,更符合我的日常打字习惯。所以,把 Ctrl 键交换到当前 Alt 的位置,是我需要做的第一步。

可是,虽然多数情况下 Ctrl 相当于 Command,但还是有至少一个例外,那就是切换窗口的 Alt + Tab 按键,在 Mac 上是 Command + Tab。这个操作非常常用,如果我把它换到键盘上 Ctrl 的位置,会对我日常操作造成影响。因此,我需要做的是,既要在大部分情况下交换 Ctrl 和 Alt,又有所保留。以下还是分两步操作。

首先,交换全部的 Ctrl 和 Alt。

有多种方式可以交换这两个按键。

第一,修改注册表,具体可以参照这个帖子或自行在网络上搜索相关方法,对此有大量教学。我没有使用这个方法,主要原因是修改注册表需要重启才能生效,意味着取消 Ctrl 和 Alt 的交换是比较麻烦的。那么,万一有其它人需要使用这台电脑,我就难快速取消交换。

第二,使用微软自己发布的开源工具 PowerToys,本文中还有许多其它功能会用到这个工具。具体而言,下载并安装这个工具(下载地址),打开设置界面(双击右下角图标),启用」键盘管理器「,打开」重新映射键「,点击「添加键重映射」。选择「Alt (Left)」,发送「Ctrl (Left)」;选择「Ctrl (Left)」,发送「Alt (Left)」。如图所示,点击确定后生效。这里有一点小提示是,当打开 PowerToys 设置面板的时候,使用其设置的按键映射是失效的,不要停留在这个界面测试那些经过映射的按键。

image.png

第三,使用 AutoHotkey,这也是本文的另一个主角。在官网下载这个工具。其中,v1 和 v2 版本的语法有很多不同,不相互兼容,如果使用本文的脚本,需要下载 v2.0 以上版本。打开工具后,选择新建脚本(New script),选择保存的地址后打开这个文件。输入以下内容后保存:

Ctrl:: Alt
Alt:: Ctrl

双冒号表示映射,这两行内容不难理解,效果是 Ctrl 和 Alt 的相互映射。找到这个后缀名为「ahk」的文件并运行,右下角出现 AutoHotkey 图标,映射就生效了。

右键点击 AutoHotkey 图标,可以继续编辑脚本(Edit Script),编辑后可以重新加载这个脚本(Reload Script),暂停使用脚本(Suspend Hotkeys)。此外,还可以打开一个重要工具 Window Spy,这个下文再说。要在开机的时自动运行这个脚本,可以对着脚本右键创建快捷方式,将快捷方式放入「启动」这个文件夹中(Win + R 运行「shell: startup」可以快速打开这个文件夹)。

其次,考虑如何使用空格键左侧的「Alt」加上 Tab 键来切换窗口的问题。

上面的交换完成后,原本的 Alt 来到了键盘左下角,但在切换窗口时,我需要空格键左侧的按键重新承担起 Alt 的功能,这看起来同样有多种路径。

一是,注意到 PowerToys 的」键盘管理器「中也有「重新映射快捷键」的功能。那么,理论上只要将改变位置后的 Ctrl 键加上 Tab,映射为 Alt + Tab 就可以产生效果。不过,出于一些原因,不论我如何尝试都不能成功。我看到的这篇文章可能是对这个问题的正确解释。总之,仅使用 PowerToys 不能实现我的目标。

image.png
摘自以上文章,可打开链接查看

二是,单独使用 AutoHotkey 也不行。由于 Alt + Tab 比较特殊,实际使用时,需要保持按下 Alt 键,点击 Tab 键来依次切换窗口,简单将交换后的 Ctrl + Tab 作为触发 Alt +Tab 的热键是不行的。在 AutoHotkey 中,直接提供了」AltTab「来完整地实现这个功能。理论上,我似乎只需要这么加这么一行脚本,就可以实现我的目的:

Ctrl & Tab:: AltTab

然而,我实际这么做时,出现了各种各样的问题,包括 Ctrl 和 Alt 的交换失效,同时使用 Alt 和 Ctrl 的其它快捷键失效等等,我不是特别清楚为什么会存在这样的问题,但我并非个例。这里有一个利用通配符和 KeyWait 方法解决问题的答案,我也尝试了其中的脚本,这里按照 v2.0 版本语法把翻译后的脚本放在这里:

*tab::
{
if (GetKeyState("LAlt", "P"))  
{
Send "{LControl up}{Alt down}{tab}"
KeyWait "tab"  
}
else   
{
send "{tab}"
}      
return
}          
~LAlt Up::
{
send "{lalt up}"
return
}
LAlt::LCtrl 
LCtrl::LAlt  

不过,我实际使用以上脚本时,还是会出现 Ctrl 键无法正确释放、保持按下的问题,看起来似乎是 ~LAlt Up 这部分没有正确生效,不确定是我的电脑的原因,还是其它原因。所以,我并没有在我最终的脚本中使用这段内容。

面对这个问题,有一种更直观的方法是,在 AutoHotkey 中,把所有常用的 Ctrl 类快捷键,都替换为 Alt 快捷键,这也是我之前在 Mac 上远程使用 Windows 时使用的方案。在 v2 版本中写起来是这样的:

!c:: Send "^c"
!v:: Send "^v"
!z:: Send "^z"
!a:: Send "^a"
!s:: Send "^s"
;………………

其中,^ 表示 Ctrl,! 表示 Alt,冒号前为按下的热键,Send 后引号内为映射的结果。

不过,正如我之前所说,有别于同时使用 Windows 和 Mac,在 Windows 中的操作毕竟有限,不难穷尽所有必要操作。但实际长期使用 Windows 时,这么做就容易产生大量遗漏,更不用提各软件使用中的组合快捷键。因此,本次我还是倾向于先映射 Ctrl 和 Alt,再对个别情况调整。

结果是,我没有实现只使用 PowerToys 或 AutoHotkey 中的一个工具,来实现我部分交换 Alt 和 Ctrl 的目的。但是,同时使用两个工具,是可以很容易地解决这个问题的。具体而言,就是先使用注册表或其它工具,交换 Ctrl 和 Alt,再用 AutoHotkey 写 Ctrl & Tab:: AltTab 这句脚本。对我来说,PowerToys 和 AutoHotkey 都还有别的用处,所以我自然采用了这两个工具的组合。

关闭窗口,退出应用程序:AutoHotkey 中的 ~、Windows Spy、#HotIf

在 macOS 的不同应用程序中,关闭窗口和退出应用程序有着相对统一的快捷键,分别为 Command + W 和 Command + Q。在 Windows 中,退出应用程序为 Alt + F4(注:虽然我在上一节交换了 Ctrl 和 Alt,但为了便于理解,如无特别说明,都指代原始按键,下同),但关闭窗口就相对复杂了。比如,关闭资源管理器窗口、浏览器的标签页是 Ctrl + W,关闭微信窗口是 Esc,而关闭 Foxmail 的邮件窗口又需要使用 Alt + F4。显然,我可以用 AutoHotkey 来统一这些快捷键操作。

为了与 Mac 的操作相一致,我首先将 Ctrl + Q(注:同理,由于我在上一节交换了 Ctrl 和 Alt,所以实际使用的时候,我按下的实际是键盘上的 Alt 和 Q 键,下同)作为 Alt + F4 的热键。这部分脚本为:

^q:: Send "!{F4}"

接下来,用 Ctrl + W 表示关闭窗口。这时候,考虑到 Windows 多数情况下关闭窗口是 Ctrl + W 或 Esc,那么有一种可能的方式是,让 Ctrl + W 同时拥有 Esc 的功能。AutoHotkey 提供了这样的方式,我们可以在热键前面加一个」~「修饰,即可以在发送热键的时候,既有冒号后的效果,又保留原有的按键功能。如下,意味着按下 Ctrl + W 时,同时有按下 Esc 的效果和 Ctrl + W 的功能。

~^w:: Send "{esc}"

我实际没有采用这样的方法。一是如前所述有个别程序的关闭窗口是其它快捷键(Alt + F4);二是有时会发生一些冲突,使得 Ctrl + W 实际上失效。比如,我在未保存的 Word 文档中使用 Ctrl + W,结果是弹出的保存窗口,然后这个窗口被 Esc 键关闭了……(我不确定这是否是我电脑运行太慢导致的,所以还是把这个方案写在这里了)。

我实际采取的方式是,针对非 Ctrl + W 的应用程序逐一设置,这里就需要用到 AutoHotkey 自带的 Windows Spy,以及 #Holf 语句。下面以微信为例,我们的目标是在微信运行时,按下 Ctrl + W 时,产生 Esc 关闭窗口的效果。

首先,右键 AutoHotkey 图标,打开 Windows Spy,用鼠标点击打开的微信应用程序窗口,就可以看到以 ahk_ 开头的一些信息。如下:

接下来,使用其中的 ahk_class、ahk_exe 等信息,就可以限制热键的使用范围,脚本如下:

#HotIf WinActive("ahk_exe WeChat.exe")
^w:: Send "{esc}"

这两行脚本的意思,是只有当前活跃的窗口是微信程序时,Ctrl + W 热键才生效。那么,为什么这里我不使用 ahk_class 信息呢。因为微信还有别的窗口,比如朋友圈,对话中打开的图片等。这些窗口都是不同的 ahk_class,但 ahk_exe 在这些窗口打开时没有变化。所以,我在这里用了 ahk_exe 信息。

需要特别注意的是,上面那行 #HotIf 会对到下一个 #HotIf 之前的语句全部生效。如果往后的语句需要恢复到在任何情况下有效,可以使用单独一行 #HotIf 来取消这个限制。

同理,我对 Foxmail 也设置了单独的关闭热键,只不过触发的不是 Esc 而是 Alt + F4,如下:

#HotIf WinActive("ahk_exe Foxmail.exe")
^w:: Send "!{F4}"

Windows 中的预览功能:PowerToys 中的速览,AutoHotkey 中的 Suspend、if、A_PriorKey

预览是 Mac 的一项美妙的功能,在访达(Finder.app)中,选中文件并按下空格键,就会弹出窗口预览该文件的内容,这对于多数文档、表格和图片都有效。通过鼠标或键盘选中不同的文件,被预览的文件会随之切换。对于需要大批量阅览文件夹中的文件,或者在无需编辑,又嫌弃 Word、Excel 等应用程序打开速度慢的场合,非常有帮助。

我总共尝试了三种方式来实现 Windows 上的预览功能。

第一,是 Windows 自带的预览窗格。在资源管理器中打开,快捷键为 Alt + P,效果是在资源管理器右侧显示选中文件的预览内容。显示速度还过得去,选中不同文件时,会自动切换被预览的文件。一个主要问题在于不方便缩放窗格和内容,只能缩放整个资源管理器,或拉动预览窗格的边缘来调整。另外有一个小问题是,刚打开预览窗格时,选中的文件会直接失去焦点(Windows 10),此时不能直接按上下键来改变选中文件,需要再点击一次左侧窗格的文件。

image.png
使用 Alt + P 预览

第二,使用其它第三方工具,例如免费的 QuickLook。这个工具的实际效果和 Mac 中的预览非常相似:空格键预览文件,弹出预览窗口,切换文件后自动切换预览显示内容。问题在于,在我的这台工作电脑上,第一次按空格键弹出预览窗口的速度非常缓慢,通常需要4-6秒的时间,电脑卡顿时就更慢了。不过,打开预览窗口后,切换不同文件时的预览速度较快,没有额外的等待时间。总体而言,在这台电脑上使用这个工具并不合适,但大家可以尝试一下。另外,大家也可以试着使用一些其它付费工具,比如 Seer,这里我就不做评测了。

第三,使用 PowerToys 中的」速览「功能。开启这个功能,在资源管理器中,按下自己指定的快捷键后,会弹出一个窗口,预览该文件的内容,按上下键可以切换显示同个文件夹中的文件,但在资源管理器中切换文件并不会切换显示被预览的文件。这个「速览」的打开速度,即便是在我这台电脑上,也多数时候是较快的,只偶尔会卡住。此外,按上下键切换显示不同文件的功能有时会失效,这应该也是电脑太差的原因。最终,本着少一个工具是一个的原则,我选择使用 PowerToys。

接下来,就需要设置 PowerToys 「速览」的快捷键。

使用 PowerToys 「速览」功能目前有一个很大的问题,那就是它不允许将空格键作为快捷键,只有以 Windows、Ctrl、Shift、Alt 开头的快捷键才有效果。那么,我要实现 Mac 和 Windows 操作习惯统一,注定需要一些额外的操作。

这是它不如 QuickLook 的地方

不过,我们既然有 AutoHotkey,这个问题应该是可以解决的。首先,给」速览「分配一个相对复杂的快捷键,例如 Ctrl + Shift + P,然后,使用 AutoHotkey 将空格键作为触发这个快捷键的热键,并且只在资源管理器中生效(如上一节所述,使用 #Holf 语句,这里用 ahk_class CabinetWClass 或 ahk_exe explorer.exe 都可以,但如果要在桌面也生效,就需要用 ahk_exe explorer.exe ):

#HotIf WinActive("ahk_exe explorer.exe")
Space:: Send "^+{p}"

可是,把空格键限制在资源管理器中触发预览功能就可以了吗。实际上,我们在资源管理器中仍然会打字,比如重命名文件和搜索功能。那么,空格键就至少有两个作用:输入空格,以及在使用中文输入法时将当前的词汇上屏。而上面的语句,让空格键的这两种作用失效了。我找到了至少以下三种方法来处理这个问题:

第一,如果空格键不常使用,那么可以在必须使用空格键的时候,临时挂起 AutoHotkey 脚本。这可以通过右键 AutoHotkey 选择 Suspend Hotkeys 来实现,也可以使用热键来触发。如下所示,为使用 Ctrl + Alt + P 来作为挂起的快捷键的脚本:

#SuspendExempt
^!p:: Suspend
#SuspendExempt False

其中,上下两行的脚本意思是,中间包围的部分,不受到挂起脚本影响。而 Suspend 单独使用,效果是切换挂起状态。显然,这种方法不算好。特别是经常在资源管理器使用空格键原本功能的人,这么做,还不如赋予预览一个非空格的快捷键。不过,这几行脚本我保留在了最终的脚本中,因为我确实需要偶尔临时挂起脚本。

第二,我从这个帖子中受到启发,如果我可以在存在输入法候选框时禁用上述空格键热键,那么我的问题就解决了一大半。因为我在文件命名时,是不会主动使用空格的(搜索时偶尔会用到空格),空格更多时候就是用于输入法上屏。基于这个思路,这段脚本应该使用 if 语句和 WinExist 函数来判断输入法候选框是否存在,具体而言,是这样的:

#HotIf WinActive("ahk_exe explorer.exe")
Space::
{
if (WinExist("输入法候选框的名称,可参考上述帖子"))
{
Send "{Space}"
}
else
{
Send "^+{p}"
}
}

运行这段脚本的结果是,如存在输入法候选框时,空格键的作用是空格键,否则是 Ctrl + Alt + P。不过,我没有使用这个方法,因为我没有找到能够正确识别 Windows 10 自带输入法候选框的 ahk_class 信息。虽然使用 Windows Spy 识别出来的 ahk_pid 和 ahk_id 可以正确实现以上效果,但它们是会变化的,我不可能每次打开电脑就重新识别一次。

第三,发现以上方式效果不佳或失败后,我重新思考空格键的使用场景。我想到,如果我需要在重命名或搜索中使用空格键,那么此前一定是在输入字母、数字、标点等。相反,当我需要使用预览时,之前的动作要么是鼠标点击,要么是用方向键选取文件。由此,我就可以区分空格的两种使用方式。顺着这个思路,不难在 AutoHotkey 中找到这样一个变量:A_PriorKey,它的作用是记录上一个被按下的键盘按键。于是,我写下了如下脚本:

#HotIf WinActive("ahk_exe explorer.exe")
Space::
{
if ((A_PriorKey == "UP") or (A_PriorKey == "Right") or (A_PriorKey == "Down") or (A_PriorKey == "Left") or (A_PriorKey == "LButton") or (A_PriorKey == "Enter") or (A_PriorKey == "Escape") or (A_PriorKey == "Tab"))
{
Send "^+{p}"
}
else
{
Send "{Space}"
}
}

可以看到,除了方向键(UP、Right、Down、Left)和鼠标左键(LButton)之外,我还额外基于使用场景,设置了Enter、ESC 和 Tab 键作为可以触发预览的前置按键。一个我思考后没有加入的设置是,空格键(Space)自身后续跟着的空格键是否应触发预览。连续两个空格键触发预览的好处是,在使用空格键关闭预览后在打开,还可以重新打开预览。但这么做不利于在将输入法选中词上屏后输入一个空格。而且,考虑到这台设备经常卡顿,不允许连续空格键触发预览,也是为了避免多敲空格反复触发预览。

最后,除了上面这段脚本外,有关预览我还做了额外的设置。

一是,我认为 Windows 自带的预览在一些场景下也不错,我将其快捷键设置为 Shift + 空格,与「速览」共同使用,如下(+ 表示 Shift):

#HotIf WinActive("ahk_exe explorer.exe")
+Space:: Send "!{p}"

二是,对于打开的预览窗口,默认关闭按键是和「速览」快捷键一致的,同样需要在 AutoHotkey 中修改一下。这里我也额外加入了一个 Ctrl + W 关闭的设置,这是因为该预览窗口不会在切换资源管理器的时候关闭(也可以设置),有时候我会忘记这是一个预览窗口,而顺手使用 Ctrl + W 来关闭它。

#HotIf WinActive("ahk_exe PowerToys.Peek.UI.exe")
Space:: Send "^+{p}"
^w:: Send "^+{p}"

在 Windows 中使用「Spotlight」:PowerToys 中的 PowerToys Run

Spotlight 是 macOS 上一个非常实用的工具,按下键盘上的 Command + 空格键,可以唤出搜索框。这个搜索框可以被用于搜索电脑里的大部分文件,也包括应用程序和系统设置。比如,我要打开 Mac 版微信,一般只需要输入「we」就已经可以看到自动补全并选中的微信应用程序,按下回车打开,省去了使用 Launchpad 启动台(作用上有点类似 Windows 开始菜单)的时间。Spotlight 也整合有计算器、网页搜索、翻译等其它功能,并且应该还可以通过插件进一步扩展。

Windows 目前没有自带这样的工具,但不难通过第三方应用来实现这个功能。在此之前我有听说过 Wox,并曾经很短暂地使用过。刚好,PowerToys 中的 PowerToys Run 的来源之一就是 Wox,因此我也就没有额外下载和尝试其它工具。PowerToys Run 拥有的功能和 Spotlight 很接近,从这个还可以继续下拉不少的插件列表可以看出,这个工具包含的要素之多,网上也可以找到更多第三方插件

这些功能我还没有全部体验过。就搜索功能而言,要注意的是,使用前需要在 Windows 系统中对要搜索的目录建立索引,才能够实现这个功能(Mac 的原理应该也是一致的,只不过不需要额外设置)。这一点在打开搜索框时会弹出提示,点进去并相应添加需要搜索的文件夹或整个硬盘就可以了。

随便输入点什么,很容易就能看到这个文件索引的提示

那么下一步的问题就是如何唤出这个功能了。在 Mac 上,默认的快捷键是 Command + 空格键。对应到 Windows 电脑中,就应该是 Alt + 空格键。交换了 Alt 和 Ctrl 的情况下就应该是 Ctrl + 空格键,这在 PowerToys Run 中就可以设置。不过,这也带给我一点小的按键冲突问题,关于这一点,在下一节中详述。

Caps 按键切换中英文:AutoHotkey 中的 #UseHook($)

Caps 键通常是用来锁定大小写的。作为中文用户,我日常办公时,基本不会有锁定使用大写字母的情景。因此,我更喜欢将 Caps 键设置为切换中英文输入的快捷键。Windows 中,相对应的按键默认是 Shift,或者 Ctrl + 空格键 。因此,在我刚开始使用 Windows 时,经常误将 Caps 当作中英文切换按键,或者在使用包含 Shfit 的快捷键(也包括临时输入一个大写字母)时,不小心切换中英文,然后就是一阵手忙脚乱地切换输入法和大小写。

使用 AutoHotkey 修改 Caps 快捷键的方式很简单,将其作为触发中英文切换的那个键就可以。首先,在右下角输入法图标右键打开「按键设置」(Windows 10),就可以看到相关选项。

多数人应该不会选择单独的 Ctrl 来切换中英文,选择另外两个时,对应的 AutoHotkey 脚本分别为(二选一即可):

Capslock:: Send "^{Space}"

 

Capslock:: Send "{Shift}"

我勾选的是「Ctrl + 空格」作为中英文切换按键,这是为了避免上面提到的使用 Shift 键时误触发中英文切换效果。但是,在上一节中,我已经把 Ctrl + 空格键设置为 PowerToys Run 的快捷键了。这样一来,不仅 Ctrl + 空格键,连 Caps 键,都会变成弹出 PowerToys Run 搜索框的效果。

这里需要使用 AutoHotkey 的钩子来解决问题。首先,给 PowerToys Run 安排一个无关的快捷键,比如 Win + Ctrl + 空格键。然后,在 AutoHotkey 中添加如下脚本:

$^Space:: Send "#^{Space}"

其中,大部分符号我们在上面都见到过,# 表示 Win 键,而前面的 $ 和 #UseHook 等价,意思是使用钩子。钩子的具体效果看起来挺复杂的,我没有完全理解,大家感兴趣可以自行阅读帮助文档中的 # UseHook 词条。但有一点我是能够理解的,就是如果一个热键使用了钩子,那这个热键就不会在使用其它 AutoHotkey 热键时被触发。

以此为例说明,在以下两行脚本的效果下,当我按下使用了钩子的 Ctrl + Space 时,实际触发的是 Win + Ctrl + 空格键,也就是 PowerToys Run 快捷键。而当我按下 Caps 键时,触发的是 Ctrl + Space,也就是系统设置的中英文切换,此时并不会再连锁地触发 Win + Ctrl + 空格键。

Capslock:: Send "^{Space}"
$^Space:: Send "#^{Space}"

缩写与无格式粘贴:aText , AutoHotkey 中的热字串、A_Clipboard

aText 是 Mac 中的一款自动替换文本的工具,可以把短文本自动替换为长文本。比如可以这么设置,输入 hw,自动扩写为 Hello, world。目前 Windows 上也已经有 aText,但我不打算再买一次,因为大部分我需要的功能 AutoHotkey 也能基本实现。AutoHotkey 的相应功能叫做热字串(Hotstrings)。以上面的 hw 为例,写出来是这样的:

::hw::Hello, world

效果是,输入 hw,再加上一个结束字符(ending character),比如空格键、回车键等,就可以输出 Hello, world。结束字符是可以自选的,但我不太喜欢使用结束字符,更喜欢自己完整定义热字串的内容,那么,比如我要用 hw= 作为完整的热字串,无需额外输入按键,就可以在前面的两个冒号之间加上一个星号,如下:

:*:hw=::Hello, world

aText 中,我们可以插入输入光标,在 AutoHotkey 中也不难实现这一点。

举一个实际的例子,在我的工作中,我经常会需要写这么几个字:(以下简称「」)。这串文内容包含文字和符号,输入起来相对复杂,我需要用一个热字串来表示这个内容,并且,我希望在打出这串字的时候,光标停留在引号之间的位置。在 aText 中通过插入功能可以实现,具体是这样设置的:

在 AutoHotkey 中,可以使用这样的脚本:

:*:jc=::(以下简称“”){left 2}

其中,left 2 表示光标向左移动二位。使用这句脚本,在键盘上依次敲下 jc= 后,就会自动替换为:(以下简称「|」),「|」表示光标位置。

我在 aText 经常使用的另一个功能是粘贴文本,这一点也可以通过 AutoHotkey 实现。

通常来说,这只要使用 Command + C 就可以完成,但如果需要的是无格式文本,在各个软件中可能就需要设置不同的快捷键。并且,我需要的还不仅仅是无格式文本。在中文环境,特别是复制 pdf 文件的时候,很容易出现额外的空格,aText 的替换功能,可以帮助我去除掉这些空格。在插入一个 clipboard 剪贴板后,双击插入的 clipboard,会弹出如下窗口,这里就可以将空格替换为空白。

在 AutoHotkey 中,也能够轻松实现类似的功能。同样需要用到一个变量 A_Clipboard,表示系统剪贴板。用到一个函数 StrReplace(),表示替换字符串中的内容,比如 StrReplace("abc", "a", "d"),表示将 abc 中的 a 替换为 d ,如果省略 d 这一项,则意味着直接删去 a 。那么,这个替换空格的粘贴脚本,就可以这样写:

:*:c;::
{
t:= StrReplace(A_Clipboard, " ")
SendText t
}

这里使用 SendText 而不是 Send,是因为默认的 Send 会把能够识别为键盘按键的内容,识别为按键,而 SendText 会将输出的内容作为纯粹的文本。

类似地,我有时候还希望在粘贴的时候,去掉空行。这意味着要将无论多个换行符替换为一个。这里我采用循环 while 的方法,利用 InStr 函数判断当连续两个换行符(`r`n`r`n)存在时,将两个换行(`r`n`r`n)替换为一个换行(`r`n)。这部分脚本如下:

while InStr(t, "`r`n`r`n")
{
t:= StrReplace(t, "`r`n`r`n", "`r`n")
}

此外,针对英文的复制粘贴,我还设置了不替换空格的粘贴,以及替换空行但不替换空格的粘贴,内容和上面类似。这里我将多种情况做了一个整合,由于需要读取输入的是什么,这里使用了一个函数 paste(命名无所谓),其中函数的参数 s ,传入的是双冒号前的内容,用于区分触发这个函数时,是通过输入了哪个热字串触发的。

:*:cc;::
:*:c;::
:*:ccp;::
:*:cp;::
paste(s)
{
t:= A_Clipboard
if ((s == ":*:c;") or (s == ":*:cp;"))
{
t:= StrReplace(A_Clipboard, " ")
}
if ((s == ":*:ccp;") or (s == ":*:cp;"))
{
while InStr(t, "`r`n`r`n")
{
t:= StrReplace(t, "`r`n`r`n", "`r`n")
}
}
SendText t
}

目前,我在 Wps 中粘贴文本的时候,遇到一个奇怪的 bug,就是所有中文标点符号,会被重复写一次,并替代下一个字符,效果如下所示:

但是,使用别的文字工具不会出现类似的情况,如下:

这个问题可能与 AutoHotkey 的输出方式有关,但我还没有找到解决方案。

翻译和文本提取:Mac 上的 Bob,PowerToys Run 翻译插件和 PowerToys 的文本提取器

在 Mac 上,我用过多个翻译软件,最后保留下来用于翻译句子和段落的,是一款名为 Bob 的付费软件。选中文本,按下快捷键,我就可以在弹出的窗口中看到不同来源的翻译,效果颇佳。出于实(抠)际(门)需要,我不打算在这台办公电脑上额外付费,也不想要同时运行其它工具。所以,我又盯上了上面提到的 PowerToys Run。

第三方插件列表中,找到翻译插件。根据页面内的说明下载安装后,可以在 PowerToys Run 插件列表中找到并打开插件。

根据插件说明,输入直接激活命令(默认为「|」)后,就可以翻译接下来输入的内容。如果剪贴板不是空的,输入该直接激活命令后,就会自动翻译剪贴板的内容。结合这一点,我们就不难写一个 AutoHotkey 脚本,来实现类似 Bob 的翻译选中句子,我的脚本是这样的:

^+d::
{
KeyWait "Ctrl"
KeyWait "Shift"
A_Clipboard:= ""
Send "^c"
ClipWait(2)
A_Clipboard:= StrReplace(A_Clipboard, "`r`n")
Send "#^{Space}"
Sleep 200
Send "|"
}

逐行解释一下。我选择的热键是 Ctrl + Shift + D,没有其它原因,只是为了和我在 Mac 上 Bob 的快捷键一致。两行 KeyWait,意思是等待这两个按键释放,写这两行的原因是,在没有加这个内容之前,我偶尔会出现使用该快捷键后,Shift 键没有被正确释放、保持按下的问题。下面三行的意思是,清空剪贴板(A_Clipboard)并使用 Ctrl + C,复制当前选中内容,并等待复制完毕。

下面这行 StrReplace 替换所有回车(`r`n),是因为我发现在实际使用 PowerToys Run 时,空行会导致后面的内容被忽略。后面的几行内容,分别是打开 PowerToys Run(按下我设置的快捷键 #^{Space},至于为什么不是 ^{Space},因为上面我使用了钩子语句,^{Space} 在我的系统里还是切换中英文的意思),等待一小会儿,然后输入「|」,让 PowerToys Run 翻译内容。

总体而言,这个方案的效果和 Bob 相去甚远。一是翻译的质量有差距,且不能自行选择翻译服务来源;二是在 PowerToys Run 中,翻译是一句一行,不能够一并显示,并且有句子数量的上限;三是这个方案会清空剪贴板。也许使用翻译工具的 API,配合 Msgbox 函数,能够有更好的效果。不过,我日常工作中,暂时对这一功能的需求不是很大,所以,暂时还没有深入探索。

Bob 除了划句翻译以外,还可以截图识别文字(并可以翻译),在 PowerToys 中也有类似的识别文字功能,直接使用即可。效果上,与 Bob 的有不小差距。在我测试的某些图片里,这个「文本提取器」的效果是不如微信提取图片文字功能的。

其它快捷键:AutoHotkey 中的 Run、FileRecycleEmpty……

此外,我还有一些零散的快捷键设置,使用这些设置主要也是为了与 Mac 操作一致,以下依次简要介绍。

第一,备忘录。

在 Mac 中,备忘录是我的常用功能,并可在右下角迅速打开一个备忘录,对此,我在 Windows 中的平替是:快捷键打开记事本(会自动新建记事本文件),这里使用的是 Run 函数,意思是启动某个程序或打开某个文件。

^!e:: Run "Notepad.exe"

第二,下载文件夹。

在 Mac 中,右下角的下载文件夹也是我非常常用的,在 Windows 办公时,我也需要频繁下载内容。所以,在任何位置快捷打开下载文件夹也是必要的,其 AutoHotkey 脚本为(「用户名」处需替换为自己的用户名):

^!d:: Run "C:\Users\用户名\Downloads"

第三,资源管理器快捷键。

在使用 Mac 的访达(Finder)时,我大量使用快捷键操作,在 Windows 的资源管理器中,我也想要使用这些快捷键,包括——

使用 Ctrl + 上下方向键,表示进入下一级文件,和回到上一级文件,这两个操作在 Windows 中原本分别为回车键和 Alt + 上方向键:

#HotIf WinActive("ahk_exe explorer.exe")
^Up:: Send "!{Up}"
^Down:: Send "{Enter}"

在 Mac 中,选中文件后按下回车键是重命名,而 Windows 居然是 F2,那么我是否应该把回车键设置为触发 F2 呢。这确实是一个思路,可以参考上面的空格键触发速览来写,同时注意使用钩子($)来避免连锁触发。不过,实际使用中,由于我的电脑太慢,还是会出现没有按照条件触发效果的情况,往往是需要重命名时不小心打开文件,代价太大。因此,我给重命名设置了其它快捷键,为 Ctrl + 右方向键:

^Right:: Send "{F2}"

在 Mac 中,删除文件的快捷键是 Command + 退格键(Backspace),清空回收站则是在此基础上加一个 Shift,通过 AutoHotkey 设置在 Windows 中实现同样的操作,如下(其中 BS 表示退格键,FileRecycleEmpty 为清空回收站,需要注意的是这没有进一步提示的):

^BS:: Send "^d"
^+BS:: FileRecycleEmpty

在使用微信 Mac 版打字的时候,我经常使用上下方向键来快速切换到段落的开头和结尾,Windows 版的方向键没有这个效果,相似效果位于 PgUp 和 PgDn 这两个键,这里我给微信中的上下键额外增加这一效果,但保留原有作用(使用 ~ 修饰):

#HotIf WinActive("ahk_exe WeChat.exe")
~UP:: Send "{PgUp}"
~Down:: Send "{PgDn}"

经过以上的一系列设置,我白天使用 Windows 办公时的流畅程度大大提升,可以看出,AutoHotkey 是一项神器,PowerToys 也整合有不少功能,值得继续探索。下面,我给出本文使用的完整脚本,供大家参考。其中,分号 ; 表示注释,说明这一行不被视为一句脚本。

#Requires AutoHotkey v2.0


; 已额外使用 PowerToys 交换 Ctrl 和 Alt


; Ctrl + Alt + P 挂起
#SuspendExempt
^!p:: Suspend
#SuspendExempt False

 
; Ctrl + Tab 切换窗口
Ctrl & Tab:: AltTab

 
; Ctrl + Q 退出
^q:: Send "!{F4}"

 
; Caps 切换中英文
Capslock:: Send "^{Space}"

 
; Ctrl + Space 快速启动(配合 PowerToys Run)
$^Space:: Send "#^{Space}"

 
; Ctrl + Alt + E 打开记事本
^!e:: Run "Notepad.exe"

 
; Ctrl + Alt + D 打开下载文件夹(需自行更改“用户名”)
^!d:: Run "C:\Users\用户名\Downloads"

 
; 无格式粘贴
:*:c;::
:*:cc;::
:*:cp;::
:*:ccp;::
paste(s)
{
t:= A_Clipboard
if ((s == ":*:c;") or (s == ":*:cp;"))
{
t:= StrReplace(A_Clipboard, " ")
}
if ((s == ":*:ccp;") or (s == ":*:cp;"))
{
while InStr(t, "`r`n`r`n")
{
t:= StrReplace(t, "`r`n`r`n", "`r`n")
}
}
SendText t
}

 
; Ctrl + Shift + D 翻译选中内容
^+d::
{
KeyWait "Ctrl"
KeyWait "Shift"
A_Clipboard:= ""
Send "^c"
ClipWait(2)
A_Clipboard:= StrReplace(A_Clipboard, "`r`n")
Send "#^{Space}"
Sleep 200
Send "|"
}

 
; Ctrl + Up / Down / Right 资源管理器操作
#HotIf WinActive("ahk_exe explorer.exe")
^Up:: Send "!{Up}"
^Down:: Send "{Enter}"
^Right:: Send "{F2}"

 
; Ctrl + (Shift) + Backspace 删除 / 清空回收站
#HotIf WinActive("ahk_exe explorer.exe")
^BS:: Send "^d"
^+BS:: FileRecycleEmpty

 
; 空格 / Shift + 空格 资源管理器预览(配合 PowerToys 速览功能)
#HotIf WinActive("ahk_exe explorer.exe")
+Space:: Send "!{p}"
Space::
{
if ((A_PriorKey == "UP") or (A_PriorKey == "Right") or (A_PriorKey == "Down") or (A_PriorKey == "Left") or (A_PriorKey == "LButton") or (A_PriorKey == "Enter") or (A_PriorKey == "Escape") or (A_PriorKey == "Tab"))
{
Send "^+{p}"
}
else
{
Send "{Space}"
}
}
#HotIf WinActive("ahk_exe PowerToys.Peek.UI.exe")
Space:: Send "^+{p}"
^w:: Send "^+{p}"

 
; Ctrl + W 在若干程序中关闭窗口或退出(以微信和 Foxmail 为例)
; 微信
#HotIf WinActive("ahk_exe WeChat.exe")
^w:: Send "{esc}"
; Foxmail
#HotIf WinActive("ahk_exe Foxmail.exe")
^w:: Send "!{F4}"

 
; 微信中上下方向键变更输入光标位置
#HotIf WinActive("ahk_exe WeChat.exe")
~UP:: Send "{PgUp}"
~Down:: Send "{PgDn}"

 
; 缩写(以此为例,其余省略)
#HotIf
:*:jc=::(以下简称“”){left 2}

> 下载少数派 客户端、关注 少数派小红书,感受精彩数字生活 🍃

> 实用、好用的 正版软件,少数派为你呈现 🚀