用 AutoHotkey 实现【同一按键】在任意界面执行【默认功能】

AutoHotkey 对热键的控制非常强大。可以通过窗口的以下信息综合起来作为条件判断

  • class
  • 标题
  • 程序名
  • 控件信息(当前激活控件,当前鼠标所在控件,控件状态,控件值)

正因为有如此强大的判断条件,就可以轻松设计一个(或多个)通用热键(我用 F4)来针对各种界面的【默认功能】实现一键完成。

首先根据程序名分类

为大部分【主流程序】建个单独的ahk文件(比如微信用 WeChat.ahk)

并用#HotIf WinActive("ahk_exe WeChat.exe")来定义动态热键条件(优先级高)

这样后续定义的热键只会在微信生效(其他应用的热键也用此法定义)

以下用 微信 举例

  • 在程序里,可能需要根据不同的子窗口做相应的事
    • 微信的主界面 class = WeChatMainWndForPC
    • 转发界面 class = SelectContactWnd
      转发
    • 设置界面 class = SettingWnd
      image
    • 查看聊天记录界面 class = FileManagerWnd(还可定义针对不同人的聊天记录,自动设置默认要查找的内容)
      image
    • 另存为界面 class = #32770(大部分的保存对话框都是这个类名,由于有通用性,放到后面通用功能内)
  • 如果不匹配,则调用下方定义的【通用函数

非主流程序

其他通用功能,就不需要单独建文件了,直接由自定义的【通用函数】(如general_smartDo())判断执行

步骤
  • 程序名(由于程序名可能会带 x64 或【空格】等内容,所以需要做下处理)
    exeName := StrReplace(RegExReplace(WinGetProcessName("A"), "i)_?(x?(64))?(\.\w+)?$"), " ", "_")

    定义各【程序名】的 map 列表,如果包含 exeName 则执行相应的函数(以下都是用此思想判断)

  • class(获取方法cls := WinGetClass("A"))
    上面提及的通用#32770保存对话框,我的主需求就是一键保存到桌面,就是在这里定义功能
  • 标题(获取方法tt := WinGetTitle("A")) 其他原理同上
  • 控件等其他方式
  • 确定没定义功能,则模拟发送F4热键执行原生功能send("{F4}")

示例代码如下,主要看思路结构

#HotIf WinActive("ahk_exe WeChat.exe") ;指定微信界面的热键
F4::wechat_smartDo() ;在微信界面,则执行此函数(如果函数里都不匹配,可考虑执行通用函数 general_smartDo)

#HotIf WinActive("ahk_exe Excel.exe") ;指定Excel界面的热键
F4::excel_smartDo()

#HotIf ;结束特定界面热键定义,以下是通用的热键
F4::general_smartDo() ;通用功能定义

;微信各界面的默认功能
wechat_smartDo(*) {
    if WinActive("ahk_class SelectContactWnd") {
        msgbox("【转发】界面的自动化处理")
    } else if WinActive("ahk_class ImagePreviewWnd") { ;图片查看
        WinGetPos(&winX, &winY, &w, &h)
        ControlClick(format("X{1} Y{2}", w//2+14, h-33)) ;图片旋转90度
    } else if WinActive("ahk_class SettingWnd") { ;设置界面
        msgbox("【设置】界面的自动化处理")
    } else ;NOTE 如果微信里没定义,可考虑执行通用的功能
        general_smartDo()
}

excel_smartDo(*) {
    titleA := WinGetTitle("A")
    if WinActive("ahk_class NetUIHWND1") { ;打印页面
        msgbox("空白打印页如何解决?")
    } else if WinActive("排序") {
        t := ControlGetText("REComboBox20W3")
        if (t = "升序")
            ControlChooseIndex(2, "REComboBox20W3")
        else ;选升序
            ControlChooseIndex(1, "REComboBox20W3")
    } else {
        general_smartDo()
    }
}

;通用的功能定义模板
general_smartDo(*) {
    WinActive("A")
    ;程序名由于不规则,建议删除 x64等文字,并把空格替换成_
    exeName := StrReplace(RegExReplace(WinGetProcessName(), "i)_?(x?(64))?(\.\w+)?$"), A_Space, "_")
    cls := WinGetClass()
    tt := WinGetTitle()
    ;exeName
    objExe := map(
        "rundll32",(p*)=>exe_rundll32(),
    )
    if objExe.has(exeName) {
        objExe[exeName].call()
        return
    }
    ;class
    objClass := map(
        "#32770" , (p*)=>class_32770(),
        "TMainFormFontCreator" , (p*)=>class_TMainFormFontCreator(),
    )
    if objClass.has(cls) {
        objClass[cls].call()
        return
    }
    exe_rundll32() {
        if WinActive("Internet 属性") {
            ControlChooseIndex(5, "SysTabControl321")
            send("{alt down}l{alt up}")
        }
    }
    class_32770() {
        ;先判断保存对话框的数据类型
        MouseGetPos(&x, &y, &hwnd, &ctlName)
        if instr(ctlName, "ComboBox") {
            hCtl := ControlGetHwnd(ctlName)
            if (UIA.ElementFromHandle(hCtl).GetCurrentPropertyValue("LegacyIAccessibleState") == 1049092) { ;1049604
                _ComboBox(ctlName).selectByText()
                return
            } else {
                tooltip("未扩展")
                SetTimer(tooltip, -1000)
            }
        }
        WinActive("A")
        sText := WinGetText()
        if instr(sText, "MSVCP120.dll") { ;由于找不到 MSVCP120.dll,无法继续执行代码。重新安装程序可能会解决此问题。
            WinClose
            msgbox(sText)
        }
    }
}
posted @ 2021-10-31 11:34  火冷  阅读(1586)  评论(0编辑  收藏  举报