给 AutoHotkey 添加通用的批量输入 Gui(代替inputbox)
写脚本中不可避免需要很多用户输入的情况,自带的
inputbox
只支持一项输入,不断地弹框输入体验太差,
而每次要输入的需求不统一,总是写gui代码更麻烦,
于是想着写个通用的批量输入的Gui
,每次只要传入一个二维数组即可
例子如下:
arr2 := [
["姓名", "name", "hy"],
["性别", "gender", ["男","女"], 2],
["年龄", "age", "20", "n"],
["是否党员", "dangyuan", 0, "b"],
["备注", "beizhu", "", "2"],
]
objOpt := hyf_inputOption(arr2, "提示")
msgbox(json.stringify(objOpt, 4))
每行的数组都代表1个输入值的定义,见下方源代码说明
运行后效果如图:
返回值为一个以变量名为key
的map
{
"age": 20,
"beizhu": "text",
"dangyuan": 0,
"gender": "女",
"name": "hy"
}
附上 AutoHotkey v2-beta 代码
;arr2的子数组各项说明:
; 1.提示文字
; 2.变量名
; 3.默认值|数据范围(可选)
; 数组,则为 ComboBox
; 4.opt(可选)
; "n" Edit只能输入数字,返回为数字类型
; "f" Edit为浮点数
; "b" 是否的 Checkbox
; 数字 多行Edit|ComboBox的默认项
; 5.focus和disable
; focus 默认控件
; 0 禁用(用得少)
;bOne 表示限制单结果,则会在 Edit内容改变时,清空其他控件
*/
hyf_inputOption(arr2, title:="", bTrim:=false, bOne:=false) {
if (arr2 is map) {
for k, v in arr2.clone()
arr2.push([k,k,v])
}
oGui := gui("+resize +AlwaysOnTop +Border +LastFound +ToolWindow")
if (title != "")
oGui.title := title
oGui.OnEvent("escape", doEscape)
oGui.OnEvent("close", doEscape)
oGui.SetFont("cRed s22")
oGui.SetFont("cDefault s11")
funOpt := (x,w:=600)=>format("ys v{1} w{2}", x,w) ;默认宽
focusCtl := ""
for arr in arr2 {
oGui.AddText("x10 section", arr[1])
if (arr.length >= 5 && arr[5]==0)
continue
varName := arr[2]
;设置 opt
ctl := ""
if (arr.length >= 3) {
if (arr[3] is array) {
ctl := "ComboBox"
lMax := max(arr[3].map(x=>strlen(x))*)
opt := funOpt(varName, max(lMax*30, 50))
if (arr.length >= 4)
opt .= format(" choose{1}", arr[4])
} else if (arr.length>=4 && arr[4] == "b") { ;boolean
ctl := "Checkbox"
opt := funOpt(varName, 100)
}
}
;其他为Edit
if (ctl == "") {
ctl := "Edit"
opt := funOpt(varName)
if (arr.length >= 4) {
switch arr[4] {
case "n","f": ;限制为数字
opt .= " number"
default:
if (arr[4] is integer)
opt .= format(" r{1}", arr[4])
}
}
}
switch ctl {
case "ComboBox":
oGui.AddComboBox(opt, arr[3])
case "Checkbox":
oGui.SetFont("cRed")
if (arr[3])
opt .= " checked"
oGui.AddCheckbox(opt)
oGui.SetFont("cDefault")
case "Edit":
if (arr.length >= 3 && arr[3] != "")
oGui.AddEdit(opt, arr[3]).OnEvent("change", editChange)
else
oGui.AddEdit(opt).OnEvent("change", editChange)
}
;默认激活字段
if (arr.length >= 5 && arr[5]=="focus")
focusCtl := varName
}
oBtn := oGui.AddButton("default center", "确定")
oBtn.OnEvent("click", btnClick)
if (focusCtl != "") {
oGui[focusCtl].focus()
}
objRes := map() ;空白值不返回
objRes.default := ""
oGui.show()
WinWaitClose(oGui)
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*) {
o := ctl.gui.submit()
;msgbox(type(o) . "`n" . json.stringify(hyf_props(o), 4))
for arr in arr2 {
v := o[arr[2]]
;记录
if (v != "") { ;过滤空值
;输出结果二次加工
if (bTrim)
v := trim(v) ;TODO 是否trim(比如每行前加"- "转成无序列表)
if (arr.length >=4 && arr[4]~="n|f")
objRes[arr[2]] := number(v)
else
objRes[arr[2]] := v
}
}
ctl.gui.destroy()
}
doEscape(oGui, p*) => oGui.destroy()
}
arr2 := [
["姓名", "name", "hy"],
["性别", "gender", ["男","女"], 2],
["年龄", "age", "20", "n"],
["是否党员", "dangyuan", 0, "b"],
["备注", "beizhu", "", "2"],
]