package ui import ( "strconv" "strings" "github.com/ying32/govcl/vcl" "github.com/ying32/govcl/vcl/types" ) const ( keyBtnSize int32 = 96 keyFontSize int32 = 24 dispFontSize int32 = 32 gap int32 = 10 margin int32 = 16 ) // showNumKeyPad 弹出触屏数字键盘,返回(输入字符串, 是否确认)。 // initial 为初始显示值;owner 通常为主窗体。 // 布局:顶部显示框 + 左侧 4×3 数字网格 + 右侧纵向整列(退格/清空) + 底部整行(取消/确认)。 func showNumKeyPad(owner vcl.IComponent, initial string) (string, bool) { form := vcl.NewForm(owner) form.SetCaption("输入数值") form.SetPosition(types.PoScreenCenter) form.SetBorderStyle(types.BsDialog) form.SetOnClose(func(sender vcl.IObject, action *types.TCloseAction) { *action = types.CaFree }) // 显示框高度随字号。 dispH := dispFontSize + 24 // 左侧 4 列 x 3 行数字网格。 gridCols := int32(4) gridRows := int32(3) gridW := gridCols*keyBtnSize + (gridCols-1)*gap gridH := gridRows*keyBtnSize + (gridRows-1)*gap // 右侧功能键列宽与数字键同宽,纵向整列高度与网格同高,两个按钮均分。 sideW := keyBtnSize sideH := gridH // 底部整行按钮高度与数字键同高。 bottomH := keyBtnSize formW := margin*2 + gridW + gap + sideW formH := margin + dispH + gap + gridH + gap + bottomH + margin form.SetWidth(formW) form.SetHeight(formH) // 显示框:横跨整个宽度。 display := vcl.NewEdit(form) display.SetParent(form) display.SetLeft(margin) display.SetTop(margin) display.SetWidth(formW - margin*2) display.SetHeight(dispH) display.Font().SetSize(dispFontSize) display.SetText(initial) display.SetReadOnly(true) display.SetAlignment(types.TaRightJustify) var ( result string confirmed bool ) curText := func() string { var s string display.GetTextBuf(&s, 64) return s } setText := func(s string) { display.SetText(s) } makeBtn := func(caption string, l, t, w, h int32) *vcl.TButton { b := vcl.NewButton(form) b.SetParent(form) b.SetLeft(l) b.SetTop(t) b.SetWidth(w) b.SetHeight(h) b.SetCaption(caption) b.Font().SetSize(keyFontSize) return b } gridTop := margin + dispH + gap gridLeft := margin // 数字键 4 列 x 3 行: // [7][8][9][.] // [4][5][6][0] // [1][2][3][+/-] layout := []string{"7", "8", "9", ".", "4", "5", "6", "0", "1", "2", "3", "+/-"} for i, cap := range layout { col := int32(i % int(gridCols)) row := int32(i / int(gridCols)) btn := makeBtn(cap, gridLeft+col*(keyBtnSize+gap), gridTop+row*(keyBtnSize+gap), keyBtnSize, keyBtnSize) btn.SetOnClick(func(sender vcl.IObject) { c := vcl.AsButton(sender).Caption() s := curText() switch c { case "+/-": if strings.HasPrefix(s, "-") { s = s[1:] } else if s != "" { s = "-" + s } case ".": if !strings.Contains(s, ".") { if s == "" || s == "-" { s += "0." } else { s += "." } } default: s += c } setText(s) }) } // 右侧纵向整列:退格 / 清空,均分高度。 sideLeft := margin + gridW + gap sideBtnH := (sideH - gap) / 2 // 两按钮间留一个 gap sideBtns := []struct { cap string fn func() }{ {"退格", func() { s := curText() if len(s) > 0 { s = s[:len(s)-1] } setText(s) }}, {"清空", func() { setText("") }}, } for i, b := range sideBtns { btn := makeBtn(b.cap, sideLeft, gridTop+int32(i)*(sideBtnH+gap), sideW, sideBtnH) btn.SetOnClick(func(sender vcl.IObject) { b.fn() }) } // 底部整行:取消 / 确认,均分宽度。 bottomTop := gridTop + gridH + gap bottomW := (formW - margin*2 - gap) / 2 // 两按钮间留一个 gap cancel := makeBtn("取消", margin, bottomTop, bottomW, bottomH) cancel.SetOnClick(func(sender vcl.IObject) { confirmed = false form.Close() }) ok := makeBtn("确认", margin+bottomW+gap, bottomTop, bottomW, bottomH) ok.Font().SetSize(keyFontSize + 4) ok.SetOnClick(func(sender vcl.IObject) { s := curText() if s == "" || s == "-" { confirmed = false } else if _, err := strconv.ParseFloat(s, 64); err != nil { vcl.ShowMessage("请输入合法数值") return } else { result = s confirmed = true } form.Close() }) form.ShowModal() return result, confirmed }