Win+Tab键实现自定义程序列表间的窗口切换

程序是用AutoHotkey语言写的,

说明:
  以自己使用频率的顺序在ExeList自定义的程序间切换
  切换可以以所有窗口切换,也可以按程序组切换(比如在word窗口间切换)
  程序组可以分别定义排除的窗口(比如想激活QQ聊天界面,但是想排除QQ主窗口)
切换顺序:
  如果当前激活程序在列表内,并有多个同类程序,则优先切换到同类窗口(比如打开多个word)
  否则切换到ExeList里按顺序第一个找到的窗口
使用方法:
  按热键后继续按Tab键则在所有匹配的窗口间切换,按应用热键则切换到程序窗口,按其他任意虚拟按键则脚本退出
  各程序可以分别设置热键,比如Word设置为W,Excel设置为E,按W就可以切换到Word组,继续按W,会在Word窗口间切换
要求:
  在应用程序名后面增加\加标题名,增加排除的标题名,比如QQ.exe排除标题为abc的窗口,则写QQ.exe\abc
  在应用程序名后面增加&字母,则为给该类应用增加热键,否则默认为程序名第一个字母
示例:每个应用程序格式QQ.exe\QQ&Q,因为QQ.exe第一个字母为Q,最后的&Q可省略,各应用之间用|隔开

下载:http://files.cnblogs.com/files/hyaray/WinTab.7z

#Tab:: ;特定窗口间切换
ExeList := "excel.exe|WINWORD.EXE|PotPlayerMini64.exe|Xmind.exe|Foxit_Reader.exe" ;前面的窗口优先,别忘了.exe后缀
;看当前窗口是否在列表里,如果在,则标记InList = 1,并移动到列表第一项
WinGet, pn, ProcessName, A ;获取当前窗口应用名,如notepad.exe
InList := InStr(ExeList, pn) ? 1 : 0 ;当前窗口在列表里,记录变量InList
If (InStr(ExeList, pn) > 2) ;当前窗口移到ExeList最前面
{
    List_Tmp := ""
    Loop, Parse, ExeList, |
        List_Tmp := (InStr(A_LoopField, pn)) ? A_LoopField . "|" . List_Tmp : List_Tmp . A_LoopField . "|"
    ExeList := Trim(List_Tmp, "|") ;去除两边的|符,防止A_LoopField出来空值
}
;通过ExeList获取窗口信息并存入ObjTotal和ObjKeyAndNum
;下面的变量说明:i为每个应用找到的有效窗口数
ObjTotal := {} ;把所有匹配窗口信息写入此对象
ObjKeyAndNum := {} ;以热键分组,把匹配的窗口信息写入此对象
total := 0 ;记录所有匹配窗口总数,ObjTotal用
Loop, Parse, ExeList, |
{
    ;获取应用程序名name
    Loop, Parse, A_LoopField, &\|
    {
        name := A_LoopField
        Break
    }
    ;获取快捷键k(后面找到的窗口都放在k对应的对象里)
    If InStr(A_LoopField, "&") ;自定义了快捷键
        k := SubStr(A_LoopField, InStr(A_LoopField, "&") + 1) ;&后一位为快捷键
    Else
    {
        StringLeft, k, A_LoopField, 1 ;默认首字母当快捷键
        StringUpper, k, k
    }
    ;获取排除窗口标题数组ms
    p2 := InStr(A_LoopField, "\")
    If p2 ;有排除窗口内容
        ms := hyf_gREP_Match(A_LoopField, "(?<=\\).*?(?=\\|&|$)")
    ;获取当前应用所有有效窗口列表
    WinGet, idList, List, Ahk_exe %name% ;获取当前应用所有窗口ID
    i := 0 ;记录当前应用提取窗口数
    Loop,% idList ;遍历窗口ID,提取想要的窗口
    {
        tt := hyf_winGet("title", "Ahk_id " . idList%A_Index%)
        ;过滤空标题(有些隐藏程序,比如hh.exe)2015-08-02 19:22:26
        If (tt = "")
            Continue
        ;过滤自定义标题(若有)
        If p2
        {
            For k, m In ms
            {
                If (tt = m.value(0))
                    Continue 2 ;跳到Loop,% ID的下个循环(找下个窗口)
            }
        }
        ;记录匹配窗口的各类信息(关键)★★★★★★★★★★★★★★★★★★★★★★★★★★★★
        ;心得:如果以应用程序为出发点,记录多个窗口的数据,理解上就需要3维数组,这结构更像是树状的,不是数组的标准结构
        ;但是以窗口为出发点,还是简单的2维数组,好理解多了。。。
        i++
        total++
        ;把ID值写入两个对象,因为索引有两种方式
        ObjTotal[total] := {"hwnd":IDList%A_Index%, "key": k, "exe": name, "title":tt}
        ObjKeyAndNum[k, i] := {"hwnd":IDList%A_Index%, "key": k, "exe": name, "title":tt}
    }
}
;该If判断匹配窗口为0或1个时,特殊处理后,提示信息并退出脚本
If (total = 0)
    hyf_tooltip("没有找到窗口,脚本退出", , 1)
Else If (total = 1)
{
    If InList
        hyf_tooltip("当前已是唯一目标窗口,脚本退出", , 1)
    Else
    {
        hyf_winActivate(ObjTotal[1].hwnd, "ID")
        hyf_tooltip("已激活唯一窗口,脚本退出", , 1)
    }
}
Else If (total = 2) && InList ;有2个窗口,且当前已在其中1个窗口
{
    Num_InTotal := Mod(hyf_getKeyOfValueInObj1(ObjTotal, hyf_winGet("ID"), "hwnd"), total) + 1
    hyf_winActivate(ObjTotal[Num_InTotal].hwnd, "ID")
    hyf_tooltip("共2个窗口,已激活另一个窗口,脚本退出", , 1)
}
;有2个及2个以上匹配窗口时按热键后的操作
Num_InTotal := InList ? 2 : 1 ;在列表则直接切换到第2个窗口,否则切换第1个找到的窗口
hyf_winActivate(ObjTotal[Num_InTotal].hwnd, "ID")
;列出热键列表和窗口列表
Key_All := ""
Win_All := ""
Num_Tmp := 0
For k1, v1 In ObjKeyAndNum
    For k2, v2 In v1
    {
        If !InStr(key_All, k1)
            Key_All .= v1[1].exe "热键为" . k1 . "`n"
    }
For k1, v1 In ObjTotal
    Win_All .= A_Index . ": " . v1.title . "`n"
;这里开始自定义按键并跳转到相应的程序,脚本主要功能。
ToolTip,% "等待按键(Tab或数字或字母键)`n按其他键则脚本退出。`n`n窗口列表:`n" . Win_All
Loop ;等待按键继续切换
{
    kp := hyf_waitKeyAndReturn()
    If (kp = "Tab") ;按Tab则依次切换到下个窗口
    {
        Num_InTotal := Mod(hyf_getKeyOfValueInObj1(ObjTotal, hyf_winGet("ID"), "hwnd"), total) + 1
        hyf_winActivate(ObjTotal[Num_InTotal].hwnd, "ID")
        hyf_tooltip("您按下了" . kp . "键,窗口位置为" . Num_InTotal . "/" . total . "`n`nPS:按窗口热键会在热键窗口内切换。`n您识别到的应用名和热键分别为:`n" . key_All, 2)
        Continue
    }
    Else If hyf_isWord(kp) ;是字母,则判断是否存在该热键窗口
    {
        If ObjKeyAndNum[kp,1].hwnd ;存在该热键窗口
        {
            If (hyf_winGet("ProcessName") = ObjKeyAndNum[kp,1].exe) ;如果按的热键和当前窗口一样,则跳到该类的下一个窗口
            {
                kn := ObjKeyAndNum[kp].MaxIndex()
                i := Mod(hyf_getKeyOfValueInObj2(ObjKeyAndNum, hyf_winGet("ID"), "hwnd")[2], kn) + 1
                hyf_winActivate(ObjKeyAndNum[kp, i].hwnd, "ID")
                hyf_tooltip("您按下了" . kp . "键,已激活热键内第" . i . "/" . kn . "个窗口`n`nPS:按Tab会按总窗口顺序切换")
            }
            Else
            {
                hyf_winActivate(ObjKeyAndNum[kp, 1].hwnd, "ID")
                hyf_tooltip("您按下了" . kp . "键`n之前窗口和该窗口不同类,已激活热键第1个窗口", 2)
            }
            Continue
        }
        Else ;不存在该快捷键窗口
            hyf_tooltip("按键" . kp . "不是热键,脚本退出", 2, 1)
        Continue
    }
    Else If hyf_isNum(kp) ;是数字,则直接跳到该窗口
    {
        If ObjTotal[kp].hwnd
        {
            hyf_winActivate(ObjTotal[kp].hwnd, "ID")
            hyf_tooltip("您按下了" . kp . "键`n之前窗口和该窗口不同类,已激活热键第1个窗口`n窗口列表:`n`n" . Win_All, 2)
        }
        Else
            hyf_tooltip("按键" . kp . "无效,脚本退出", , 1)
        Continue
    }
    Else
        hyf_tooltip("按键" . kp . "无效,脚本退出", , 1)
}
Return
hyf_gREP_Match(str, zz) ;全局正则   {{{3
{ ;ms.value(0), ms.Len(0), ms.Pos(0)分别存储子项目的值,长度和位置
    options := "U)^[imsxACDJOPSUX`a`n`r]+\)"
    zz := (RegExMatch(zz, options, Opt) ? (InStr(Opt, "O", 1) ? "" : "O") : "O)") . zz
    m := {Len:{0:0}}
    ms := []
    p := 1
    While (p := RegExMatch(str, zz, m, p + m.Len[0]))
        ms[A_Index] := m
    Return ms
}

hyf_winGet(cmd := "title", WinTitle := "A") ;不支持Pos等多变量输出命令  {{{3
{
    If (cmd = "title")
        WinGetTitle, v, %WinTitle%
    Else If (cmd = "Class")
        WinGetClass, v, %WinTitle%
    Else If (cmd = "Text")
        WinGetText, v, %WinTitle%
    Else
        WinGet, v, %cmd%, %WinTitle%
    Return v
}

hyf_tooltip(str, t := 1, ExitScript := 0, x := "", y := "")  ;提示t秒并自动消失   {{{3
{
    t *= 1000
    ToolTip, %str%, %x%, %y%
    SetTimer, hyf_removeToolTip, -%t%
    If ExitScript
    {
        Gui, Destroy
        Exit
    }
}

hyf_winActivate(t, m := "") ;可以支持对象的值,m为Ahk_后面的值,如ID, Class, pid, exe等 {{{3
{
    t := (m = "") ? t :"Ahk_" . m . A_Space . t
    WinActivate %t%
}

hyf_getKeyOfValueInObj1(obj, value, key := "") ;获取单索引参数对象里的k键匹配v值的键    {{{3
{ ;比如获取obj[n] = {"a":x1, "b":y1}里键b的值为3的序号n,则函数参数为(obj, 3, "b"),若为数组,则key=""
    If (key = "")
    {
        For k, v In obj
            If (v = value)
                Return k
    }
    Else
    {
        For k, v In obj
            If (v[key] = value)
                Return k
    }
}

hyf_waitKeyAndReturn(k := "All", t := "") ;t秒内等待按下任意键并返回按键名或超时(个人修改版)   {{{3
{
    If (t != "")
        t := "T" . t
    Suspend On
    If (k = "All") || (k = "A")
        Input, SingleKey, I%t%, ``0123456789-=:[]\'./ABCDEFGHIJKLMNOPQRSTUVWXYZ{LControl}{RControl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}{Enter}{Escape}{CapsLock}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PGUP}{PGDN}{Del}{Ins}{BS}{CapsLock}{NumLock}{Numpad0}{Numpad1}{Numpad2}{Numpad3}{Numpad4}{Numpad5}{Numpad6}{Numpad7}{Numpad8}{Numpad9}{NumpadDot}{NumpadDiv}{NumpadMult}{NumpadAdd}{NumpadSub}{NumpadEnter}{PrintScreen}{ScrollLock}{Pause}{Space}{Tab}`,; ;最后为需要转义的特殊符号,;放最后只是避免语法错误显示
    Else If (k = "xsj") ;修饰键,包括了Tab
        Input, SingleKey, I%t%, {Tab}{LControl}{RControl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}{Enter}{Escape}{CapsLock}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PGUP}{PGDN}{Del}{Ins}{BS}{CapsLock}{NumLock}{NumpadDot}{NumpadDiv}{NumpadMult}{NumpadAdd}{NumpadSub}{NumpadEnter}{PrintScreen}{ScrollLock}{Pause} ;最后为需要转义的特殊符号,;放最后只是避免语法错误显示
    Else
        Input, SingleKey, I%t%, %k%
    Suspend Off
    Return (ErrorLevel = "TimeOut") ? "TimeOut" : SubStr(ErrorLevel, 8)
}

hyf_isWord(char) ;是否字母  {{{3
{
    Return (char ~= "i)[a-z]")
}

hyf_getKeyOfValueInObj2(obj, value, key := "") ;获取双索引参数对象里的k键匹配v值的键,返回数组   {{{3
{ ;比如获取obj[m][n] = {"a":x1, "b":y1}里键b的值为3的序号m和n,则函数参数为(obj, 3, "b")
    o := {}
    If (key = "")
    {
        For k1, v1 In obj
            For k2, v2 In v1
                If (v2 = value)
                {
                    o[1] := k1
                    o[2] := k2
                    Return o
                }
    }
    Else
    {
        For k1, v1 In obj
            For k2, v2 In v1
                If (v2[key] = value)
                {
                    o[1] := k1
                    o[2] := k2
                    Return o
                }
    }
}

hyf_isNum(char) ;是否数字  {{{3
{
    Return (char ~= "\d")
}

hyf_removeToolTip() ;清除ToolTip {{{3
{
    ToolTip
}

  

转载于:https://www.cnblogs.com/hyaray/p/7060567.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows 服务快捷启动命令 gpedit.msc-----组策略 sndrec32-----录音机 nslookup----- ip地址侦测器 explorer------ 打开资源管理器 logoff-------注销命令 tsshutdn------60秒倒计时关机命令 lusrmgr.msc----本机用户和组 services.msc---本地服务设置 oobe/msoobe /a---检查xp是否激活 notepad------打开记事本 cleanmgr------垃圾整理 net start messenger--开始信使服务 compmgmt.msc---计算机管理 net stop messenger--停止信使服务 conf-------启动 dvdplay------dvd播放器 charmap------启动字符映射表 diskmgmt.msc---磁盘管理实用程序 calc--------启动计算器 dfrg.msc------磁盘碎片整理程序 chkdsk.exe-----chkdsk磁盘检查 devmgmt.msc--- 设备管理器 regsvr32 /u *.dll---停止dll文件运行 drwtsn32-----系统医生 rononce -p ----15秒关机 dxdiag------检查directx信息 regedt32-----注册表编辑器 msconfig.exe---系统配置实用程序 rsop.msc------组策略结果集 mem.exe-----显示内存使用情况 regedit.exe----注册表 winchat------xp自带局域网聊天 progman------程序管理器 winmsd------系统信息 perfmon.msc----计算机性能监测程序 winver------检查windows版本 sfc /scannow----扫描错误并复原 winver------检查windows版本 wmimgmt.msc---打开windows管理体系结构 wupdmgr-----windows更新程序 w脚本------windows脚本宿主设置 write-------写字板 winmsd------系统信息 wiaacmgr-----扫描仪和照相机向导 winchat-----xp自带局域网聊天 mem.exe-----显示内存使用情况 msconfig.exe---系统配置实用程序 mplayer2-----简易 mspaint------画图板 mstsc------远程桌面连接 mplayer2-----媒体播放机 magnify------放大镜实用程序 mmc-------打开控制台 mobsync-----同步命令 dxdiag------检查directx信息 drwtsn32-----系统医生 devmgmt.msc--- 设备管理器 dfrg.msc------磁盘碎片整理程序 diskmgmt.msc---磁盘管理实用程序 dcomcnfg-----打开系统组件服务 ddeshare------打开dde共享设置 dvdplay------dvd播放器 net stop messenger--停止信使服务 net start messenger--开始信使服务 notepad------打开记事本 nslookup------网络管理的工具向导 ntbackup------系统备份和还原 narrator------屏幕“讲述人” nyessmgr.msc----移动存储管理器 nyessoprq.msc---移动存储管理员操作请求 netstat -an----(tc)命令检查接口 syncapp------创建一个公文包 sysedit------系统配置编辑器 sigverif------文件签验证程序 sndrec32-----录音机 shrpubw-----创建共享文件夹 secpol.msc----本地安全策略 syskey------系统加密,一旦加密就不能解开,保护windows xp系统的双重密码 services.msc---本地服务设置 sndvol32-----音量控制程序 sfc.exe------系统文件检查器 sfc /scannow---windows文件保护 tsshutdn------60秒倒计时关机命令 tourstart------xp简介(安装完成后出现的漫游xp程序) taskmgr------任务管理器 eventvwr-----事件查看器 eudcedit-----造字程序 explorer-----打开资源管理器 packager-----对象包装程序 perfmon.msc----计算机性能监测程序 progman-----程序管理器 regedit.exe----注册表 rsop.msc-----组策略结果集 regedt32-----注册表编辑器 rononce -p ---15秒关机 regsvr32 /u *.dll---停止dll文件运行 regsvr32 /u zipfldr.dll--取消zip支持 cmd.exe-------cmd命令提示符 chkdsk.exe-----chkdsk磁盘检查 ceryesgr.msc----证书管理实用程序 calc--------启动计算器 charmap-------启动字符映射表 cliconfg-------sql server 客户端网络实用程序 clipbrd-------剪贴板查看器 conf--------启动 compmgmt.msc---计算机管理 cleanmgr------垃圾整理 ciadv.msc------索引服务程序 osk--------打开屏幕盘 odbcad32------odbc数据源管理器 oobe/msoobe /a----检查xp是否激活 lusrmgr.msc----本机用户和组 logoff-------注销命令 iexpress------木马捆绑工具,系统自带 nslookup------ip地址侦测器 fsmgmt.msc-----共享文件夹管理器 utilman-------辅助工具管理器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值