给 AutoHotkey 添加个通用的批量输入 Gui(代替inputbox)


写脚本中不可避免需要很多用户输入的情况,自带的inputbox只支持一项输入,不断地弹框输入体验太差,
而每次要输入的需求不统一,总是写gui代码更麻烦,

于是想着写个通用的批量输入的Gui,每次只要传入一个二维数组即可

例子如下:

arr := [
    ["姓名", "name", "default"],
    ["性别", "sex", ["男","女"]],
    ["年龄", "nAge", "20"],
]

每行的数组都代表1个输入值的定义,3个内容分别是:

  1. 提示内容
  2. 变量名(为输出map的key)
    • 如果是 n + 大写字母,如上图的nAge,则强制为数字输入(Edit控件做限制)
  3. 默认值
    • 如果是数组,则输入控件为 CheckBox

运行后效果如图:

返回值为一个以变量名keymap

{
    "nAge": "20",
    "name": "default",
    "sex": "女"
}

附上 AutoHotkey v2-beta 代码

;arr的子数组
;1.提示文字
;2.变量名
;   n+大写字母则强制为数字
;3.默认值]
;   数组,则控件为 AddComboBox
;bOne 表示限制单结果,则会在 Edit内容改变时,清空其他控件
inputOption(arr, sTips:="", bOne:=false) {
    oGui := gui()
    oGui.OnEvent("escape", doEscape)
    oGui.OnEvent("close", doEscape)
    oGui.SetFont("cRed s22")
    if strlen(sTips)
        oGui.AddText("x10", sTips . "`n")
    oGui.SetFont("cDefault s13")
    funOpt := (x)=>"ys w200 v" . x
    focusCtl := ""
    for a in arr {
        oGui.AddText("x10 section", a[1])
        if (a.length > 3) ;NOTE 有第4参数,则跳过
            continue
        if (a.length > 2) { ;NOTE 核心判断
            if isobject(a[3]) {
                oGui.AddComboBox(funOpt(a[2]), a[3])
            } else {
                if (a[2] ~= "^n[A-Z]") ;限制为数字
                    oGui.AddEdit(funOpt.call(a[2]) . " number", a[3]).OnEvent("change", editChange)
                else {
                    if (a[2] ~= "^b[A-Z]") { ;boolean
                        oGui.SetFont("cRed")
                        if a[3]
                            oGui.AddCheckbox(funOpt.call(a[2]) . " checked", "是")
                        else
                            oGui.AddCheckbox(funOpt.call(a[2]), "是")
                        oGui.SetFont("cDefault")
                    } else
                        oGui.AddEdit(funOpt.call(a[2]), a[3]).OnEvent("change", editChange)
                }
            }
            if (a.length >= 4)
                focusCtl := a[2]
        } else
            oGui.AddEdit(funOpt.call(a[2])).OnEvent("change", editChange)
    }
    oBtn := oGui.AddButton("default center", "确定")
    oBtn.OnEvent("click", btnClick)
    if strlen(focusCtl) {
        oGui[focusCtl].focus()
    }
    objRes := map() ;空白值不返回
    oGui.show()
    WinWaitClose("ahk_id " . oGui.hwnd)
    return objRes
    editChange(ctl, p*) {
        if (bOne) {
            for hwnd, ctlLoop in ctl.gui {
                if (ctlLoop.ClassNN ~= "^Edit\d+$" && hwnd != ctl.hwnd)
                    ctlLoop.text := ""
            }
        }
    }
    btnClick(ctl, p*) {
        ctl.gui.submit
        for k, a in arr {
            try ;有些控件并未生成
                oGui[a[2]]
            catch
                continue
            v := (a.length>2) ? oGui[a[2]].text : oGui[a[2]].value
            v := trim(v) ;TODO 是否trim
            if strlen(v)
                objRes[a[2]] := v
        }
        oGui.destroy()
    }
    doEscape(oGui, p*) {
        oGui.destroy()
    }
}

arr := [
    ["姓名", "name", "default"],
    ["性别", "sex", ["男","女"]],
    ["年龄", "nAge", "20"],
]
objOpt := inputOption(arr, "提示")
msgbox(json.stringify(objOpt, 4))