上次心血来潮又写了一篇关于快速切换任务的博文,有访客留言讨论,虽然最终没能得出一个满意的方案,但触发了我的灵感——最迅速的切换任务方式应该是类似于Total Comander那样用几个快捷键组合来切换程序。
那篇博文里用Hoekey+Taskswichxp实现快捷键切换任务的方式并不正规,属于歪门邪道,而且还要对所有可能运行的程序进行配置,非常繁琐。我本来的目标是能够不使用任务栏,但最终任务栏还是没能去掉,仍然在那。所以以hoekey作为入口点是不对的,于是想到用比hoekey强大百倍的AutoHotkey来实现。这几天在厦门落脚了,这套房子里暂时还没有网络,于是今天就想好好的学学AutoHotkey,看看能否实现。
我现在用着一个阮一峰推荐过的AHK脚本——Favmenu,这个脚本就是模仿TC中切换文件夹的操作,正是这个脚本的强大让我相信AHK能实现我所需的功能。但看着AutoHotkey.chm密密麻麻的帮助,就没了兴致,想找找看有无其他已经做好的实用脚本可以用得上。后来看到AutoHotkey文件夹下有一个未解压的“AutoHotKey懒人包@appinn.com.7z”,点进去看看,居然有一个“AltTab.ahk”,看了介绍感觉这正是我一直要找的东西!
这个脚本是替换自带的Alt+Tab,我看到了以下几个功能:
1、替换掉系统的 Alt + Tab 功能。
2、Alt + Tab 之后,按住 alt,输入程序首字母可以快速选择到程序。
3、在右键菜单中还可以对程序设定呼出热键。
4、在右键菜单中可以结束进程。
而第二点正是我一直要寻找的功能。立即试用了一下,发现了一些不足:
1、当标题开头是中文时,无法通过快捷键切换任务。
2、列出所有任务,不像taskswitchXP那样可以排除一些任务。
但不管怎样,我还是很满意的,而且这是AHK脚本,等下我可以自己修改成适合自己的。倒没有相见恨晚的感觉,我是到前段时间才悟出可以不需要任务栏的,要是之前看到这个AHK脚本,只会觉得很普通,没什么用的,只有等到自己发现了,需要了,再去找到这个东西,才会欣喜若狂。(确实最近很着迷快速切换程序,本来还抱怨没有网络,不然就可以写信或留言给阮一峰,问问他是否有兴趣写一个AHK切换任务的脚本)
随着电脑配置越来越高,任务列表实际上早就应该按文件夹的方式——竖向排列了。微软在win7里面也意识到了任务逐渐增多,但因为习惯考虑,还是采用任务栏横向排列的方式,但他强化了用icons来识别,这样就节省了很多任务栏的空间。但有多个notepad程序时就不是那么好辨认了,所以还是用竖向任务列表比较合理。
接下来探讨这个AHK如何改进,现在写下思路:
1、因为标题中可能有中文,这时就无法切换,而进程只有英文的,可否用进程名来识别切换呢?不能,那样的话chrome创建的Gmail、Adsense等程序都是一样的进程,切换起来得按很多次了。
2、可否增加一个选项,松开ALT的时候列表窗口不消失,切换到那个程序时才消失,就像Total Commander的Ctrl+D一样?也不行,因为除了要用快捷键切换任务,Alt+Tab同时还担任着在两个任务间切换,所以如果不消失的话在两个任务间切换就比较麻烦了。
3、可否自己更改目前的这个脚本来实现排除一些任务?不用了,我在这个AHK的代码中看到作者在“TO DO”中写道:include a filter for docked windows to be displayed in alt-tab 。看来作者有可能在下个版本中就加上这个排除功能,现在只需等版本更新。
4、既然标题可能有中文,那能否用软件把所有程序的标题都改为英文的?我找了找,确实有这样的软件,但要么是如同窗口魔术师(g-WinOperator)这种只能临时更改标题的,要么是用Ultra编辑器编辑文件来实现,非常麻烦。所以也放弃。
5、既然无法用软件更改标题,那么这个AHK脚本的下个版本有没有可能加上重命名标题的功能(就像这里提到的)?不太可能,因为作者用英文,在全英文环境下可以很方便地切换,就不太可能为中文用户制作出可自定义窗口名的功能。
最终决定自己写个AHK,用这个AHK动态更改标题(即每次按下Alt+Tab时就把标题改为英文的),使之可以与Alt+Tab的那个AHK脚本配合,实现用字母切换任何程序。现在写下这个脚本的制作过程:(如不想了解可直接下载最后一段中的AHK脚本使用)
第一步:取自WinSetTitle中的例子——更改一个新的notepad文件标题为“This is a new title”,加个#Persistent让这个AHK一直运行,而不是运行一次就退出。
#Persistent
DetectHiddenWindows, on
!Tab::
WinSetTitle, Untitled – Notepad, , This is a new title
Send {Alt down}{tab}
加一句Send {Alt down}{tab},即可实现按住Alt+Tab时可在更改标题的同时实现Alt+Tab切换效果。但这时只对标题中有“Untitled – Notepad”的任务生效,于是想用正则来实现规则,在AutoHotkey.chm中文版中搜索“正则”,可以看到在SetTitleMatchMode中有说明,默认是打开模糊匹配(1)的,但必须是以字符开头的,而我是结尾的,所以直接去掉“Untitled”还是不行的,还必须把需要SetTitleMatchMode改成2。见如下:
#Persistent
DetectHiddenWindows, on
SetTitleMatchMode, 2
!Tab::
WinSetTitle, – Notepad, , This is a new title
Send {Alt down}{tab}
但这时不能更改未被激活的程序标题,所以还必须打开DetectHiddenWindows功能,设置DetectHiddenWindows, On
第二步:因为notepad用标题来识别不方便,所以直接改为用类名来识别。
#Persistent
DetectHiddenWindows, on
SetTitleMatchMode, 2
DetectHiddenWindows, On
!Tab::
WinSetTitle, ahk_class Notepad, , notepad
Send {Alt down}{tab}
但这样子notepad改后的所有标题都是notepad,没法识别,所以还得传递标题值,我想到一个WinGetTitle函数。
#Persistent
DetectHiddenWindows, on
SetTitleMatchMode, 2
DetectHiddenWindows, On
!Tab::
WinGetTitle, Title, ahk_class Notepad
WinSetTitle, ahk_class Notepad, , Notepad – "%Title%"
Send {Alt down}{tab}
但这样子标题会越拖越长,所以每次就取最后一段(十个字),这样就不会变长了。这属于字符串处理了,于是在chm里搜索“字符串 处理”,可找到用StringLeft来处理:
#Persistent
DetectHiddenWindows, on
SetTitleMatchMode, 2
DetectHiddenWindows, On
!Tab::
WinGetTitle, Title, ahk_class Notepad
newtitle=%Title%
StringLeft, OutputVar,newtitle,6
WinSetTitle, ahk_class Notepad, , Notepad – %OutputVar%
Send {Alt down}{tab}
这样子也不行,最终标题都会变得一样,从最后一个开始选取或者后面第N个开始选取字符串也不行。从后面第N个(比如notepad是第10个)开始选取,再加一行notepad.exe也不行。如果用另外的方法,先把notepad取出来,再把余下的字符串加到尾巴上去,就可以了!!但没看到有这个函数。
尾巴上加一个notepad形成首尾对称(如下)也不行。
#Persistent
DetectHiddenWindows, on
SetTitleMatchMode, 2
DetectHiddenWindows, On
!Tab::
WinGetTitle, Title, ahk_class Notepad
newtitle=%Title%
StringTrimRight, OutputVar,newtitle,10
WinSetTitle, ahk_class Notepad, , Notepad – %OutputVar% – Notepad
Send {Alt down}{tab}
看来只能用判断语句了,如下
#Persistent
DetectHiddenWindows, on
SetTitleMatchMode, 2
DetectHiddenWindows, On
!Tab::
WinGetTitle, Title, ahk_class Notepad
newtitle=%Title%
IfInString, newtitle, Notepad
{
StringTrimRight, OutputVar,newtitle,10 ;去掉原有title后面的 – notepad共计10个字,输出为OutputVar
WinSetTitle, ahk_class Notepad, , Note – %OutputVar%
}
Send {Alt down}{tab}
至此,已经可以实现notepad的标题前后对调。
现在加上chrome和TW的,这两个程序不需要判断,直接设置标题为chrome和“S世界之窗”(TW和TC都以T开头,所以用S世界之窗,以S开头):
(不知道为何chrome的用“WinSetTitle, ahk_class Chrome_WidgetWin_0, ,Chrome ”不行,所以用标题判断。)
最终代码:
#Persistent
DetectHiddenWindows, on
SetTitleMatchMode, 2
!Tab::
WinGetTitle, Title, ahk_class Notepad
newtitle=%Title%
IfInString, newtitle, Notepad
{
StringTrimRight, OutputVar,newtitle,10 ;去掉原有title后面的 – notepad共计10个字,输出为OutputVar
WinSetTitle, ahk_class Notepad, , Note – %OutputVar%
}
WinSetTitle, ahk_class XFrame_Wnd, , S世界之窗
WinSetTitle, 谷歌浏览器, ,Chrome
WinSetTitle, ahk_class WindowsForms10.Window.8.app.0.33c0d9d, ,Writer
Send {Alt down}{tab}
效果如图:
总算是完全实现了我预期的设想。