1 Star 0 Fork 0

橙子/lxnWalk

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
numberedit.go 19.95 KB
一键复制 编辑 原始数据 按行查看 历史
橙子 提交于 2020-08-13 10:03 . .
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
// Copyright 2011 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package walk
import (
"bytes"
"fmt"
"math"
"strconv"
"strings"
"syscall"
"unsafe"
"github.com/xuchengzhi/win"
)
const numberEditWindowClass = `\o/ Walk_NumberEdit_Class \o/`
func init() {
MustRegisterWindowClass(numberEditWindowClass)
}
// NumberEdit is a widget that is suited to edit numeric values.
type NumberEdit struct {
WidgetBase
edit *numberLineEdit
maxValueChangedPublisher EventPublisher
minValueChangedPublisher EventPublisher
prefixChangedPublisher EventPublisher
suffixChangedPublisher EventPublisher
}
// NewNumberEdit returns a new NumberEdit widget as child of parent.
func NewNumberEdit(parent Container) (*NumberEdit, error) {
ne := new(NumberEdit)
if err := InitWidget(
ne,
parent,
numberEditWindowClass,
win.WS_VISIBLE,
win.WS_EX_CONTROLPARENT); err != nil {
return nil, err
}
var succeeded bool
defer func() {
if !succeeded {
ne.Dispose()
}
}()
var err error
if ne.edit, err = newNumberLineEdit(ne); err != nil {
return nil, err
}
ne.edit.applyFont(ne.Font())
ne.SetRange(-math.MaxFloat64, math.MaxFloat64)
if err = ne.SetValue(0); err != nil {
return nil, err
}
ne.GraphicsEffects().Add(InteractionEffect)
ne.GraphicsEffects().Add(FocusEffect)
ne.MustRegisterProperty("MaxValue", NewProperty(
func() interface{} {
return ne.MaxValue()
},
func(v interface{}) error {
return ne.SetRange(ne.MinValue(), assertFloat64Or(v, 0.0))
},
ne.minValueChangedPublisher.Event()))
ne.MustRegisterProperty("MinValue", NewProperty(
func() interface{} {
return ne.MinValue()
},
func(v interface{}) error {
return ne.SetRange(assertFloat64Or(v, 0.0), ne.MaxValue())
},
ne.maxValueChangedPublisher.Event()))
ne.MustRegisterProperty("Prefix", NewProperty(
func() interface{} {
return ne.Prefix()
},
func(v interface{}) error {
return ne.SetPrefix(assertStringOr(v, ""))
},
ne.prefixChangedPublisher.Event()))
ne.MustRegisterProperty("ReadOnly", NewProperty(
func() interface{} {
return ne.ReadOnly()
},
func(v interface{}) error {
return ne.SetReadOnly(v.(bool))
},
ne.edit.readOnlyChangedPublisher.Event()))
ne.MustRegisterProperty("Suffix", NewProperty(
func() interface{} {
return ne.Suffix()
},
func(v interface{}) error {
return ne.SetSuffix(assertStringOr(v, ""))
},
ne.suffixChangedPublisher.Event()))
ne.MustRegisterProperty("Value", NewProperty(
func() interface{} {
return ne.Value()
},
func(v interface{}) error {
return ne.SetValue(assertFloat64Or(v, 0.0))
},
ne.edit.valueChangedPublisher.Event()))
succeeded = true
return ne, nil
}
func (ne *NumberEdit) applyEnabled(enabled bool) {
ne.WidgetBase.applyEnabled(enabled)
if ne.edit == nil {
return
}
ne.edit.applyEnabled(enabled)
}
func (ne *NumberEdit) applyFont(font *Font) {
ne.WidgetBase.applyFont(font)
if ne.edit == nil {
return
}
ne.edit.applyFont(font)
}
// LayoutFlags returns information that is mainly interesting to Layout
// implementations.
func (*NumberEdit) LayoutFlags() LayoutFlags {
return ShrinkableHorz | GrowableHorz
}
// MinSizeHint returns information that is mainly interesting to Layout
// implementations.
func (ne *NumberEdit) MinSizeHint() Size {
return ne.dialogBaseUnitsToPixels(Size{20, 12})
}
// SizeHint returns information that is mainly interesting to Layout
// implementations.
func (ne *NumberEdit) SizeHint() Size {
return ne.dialogBaseUnitsToPixels(Size{50, 12})
// s := ne.dialogBaseUnitsToPixels(Size{50, 12})
// return Size{s.Width, maxi(s.Height, 22)}
}
// Decimals returns the number of decimal places in the NumberEdit.
func (ne *NumberEdit) Decimals() int {
return ne.edit.decimals
}
// SetDecimals sets the number of decimal places in the NumberEdit.
func (ne *NumberEdit) SetDecimals(decimals int) error {
if decimals < 0 || decimals > 8 {
return newError("decimals must >= 0 && <= 8")
}
ne.edit.decimals = decimals
return ne.SetValue(ne.edit.value)
}
// Prefix returns the text that appears in the NumberEdit before the number.
func (ne *NumberEdit) Prefix() string {
return syscall.UTF16ToString(ne.edit.prefix)
}
// SetPrefix sets the text that appears in the NumberEdit before the number.
func (ne *NumberEdit) SetPrefix(prefix string) error {
if prefix == ne.Prefix() {
return nil
}
p, err := syscall.UTF16FromString(prefix)
if err != nil {
return err
}
old := ne.edit.prefix
ne.edit.prefix = p[:len(p)-1]
if err := ne.edit.setTextFromValue(ne.edit.value); err != nil {
ne.edit.prefix = old
return err
}
ne.prefixChangedPublisher.Publish()
return nil
}
// PrefixChanged returns the event that is published when the prefix changed.
func (ne *NumberEdit) PrefixChanged() *Event {
return ne.prefixChangedPublisher.Event()
}
// Suffix returns the text that appears in the NumberEdit after the number.
func (ne *NumberEdit) Suffix() string {
return syscall.UTF16ToString(ne.edit.suffix)
}
// SetSuffix sets the text that appears in the NumberEdit after the number.
func (ne *NumberEdit) SetSuffix(suffix string) error {
if suffix == ne.Suffix() {
return nil
}
s, err := syscall.UTF16FromString(suffix)
if err != nil {
return err
}
old := ne.edit.suffix
ne.edit.suffix = s[:len(s)-1]
if err := ne.edit.setTextFromValue(ne.edit.value); err != nil {
ne.edit.suffix = old
return err
}
ne.suffixChangedPublisher.Publish()
return nil
}
// SuffixChanged returns the event that is published when the suffix changed.
func (ne *NumberEdit) SuffixChanged() *Event {
return ne.suffixChangedPublisher.Event()
}
// Increment returns the amount by which the NumberEdit increments or decrements
// its value, when the user presses the KeyDown or KeyUp keys, or when the mouse
// wheel is rotated.
func (ne *NumberEdit) Increment() float64 {
return ne.edit.increment
}
// SetIncrement sets the amount by which the NumberEdit increments or decrements
// its value, when the user presses the KeyDown or KeyUp keys, or when the mouse
// wheel is rotated.
func (ne *NumberEdit) SetIncrement(increment float64) error {
ne.edit.increment = increment
return nil
}
// MinValue returns the minimum value the NumberEdit will accept.
func (ne *NumberEdit) MinValue() float64 {
return ne.edit.minValue
}
// MinValue returns the maximum value the NumberEdit will accept.
func (ne *NumberEdit) MaxValue() float64 {
return ne.edit.maxValue
}
// SetRange sets the minimum and maximum values the NumberEdit will accept.
//
// If the current value is out of this range, it will be adjusted.
func (ne *NumberEdit) SetRange(min, max float64) error {
if min > max {
return newError(fmt.Sprintf("invalid range - min: %f, max: %f", min, max))
}
minChanged := min != ne.edit.minValue
maxChanged := max != ne.edit.maxValue
ne.edit.minValue = min
ne.edit.maxValue = max
if min != max {
if ne.edit.value < min {
if err := ne.edit.setValue(min, true); err != nil {
return err
}
} else if ne.edit.value > max {
if err := ne.edit.setValue(max, true); err != nil {
return err
}
}
}
if minChanged {
ne.minValueChangedPublisher.Publish()
}
if maxChanged {
ne.maxValueChangedPublisher.Publish()
}
return nil
}
// Value returns the value of the NumberEdit.
func (ne *NumberEdit) Value() float64 {
return ne.edit.value
}
// SetValue sets the value of the NumberEdit.
func (ne *NumberEdit) SetValue(value float64) error {
if ne.edit.minValue != ne.edit.maxValue &&
(value < ne.edit.minValue || value > ne.edit.maxValue) {
return newError("value out of range")
}
return ne.edit.setValue(value, true)
}
// ValueChanged returns an Event that can be used to track changes to Value.
func (ne *NumberEdit) ValueChanged() *Event {
return ne.edit.valueChangedPublisher.Event()
}
// SetFocus sets the keyboard input focus to the NumberEdit.
func (ne *NumberEdit) SetFocus() error {
if win.SetFocus(ne.edit.hWnd) == 0 {
return lastError("SetFocus")
}
return nil
}
// TextSelection returns the range of the current text selection of the
// NumberEdit.
func (ne *NumberEdit) TextSelection() (start, end int) {
return ne.edit.TextSelection()
}
// SetTextSelection sets the range of the current text selection of the
// NumberEdit.
func (ne *NumberEdit) SetTextSelection(start, end int) {
ne.edit.SetTextSelection(start, end)
}
// ReadOnly returns whether the NumberEdit is in read-only mode.
func (ne *NumberEdit) ReadOnly() bool {
return ne.edit.ReadOnly()
}
// SetReadOnly sets whether the NumberEdit is in read-only mode.
func (ne *NumberEdit) SetReadOnly(readOnly bool) error {
if readOnly != ne.ReadOnly() {
ne.invalidateBorderInParent()
}
return ne.edit.SetReadOnly(readOnly)
}
// Background returns the background Brush of the NumberEdit.
//
// By default this is nil.
func (ne *NumberEdit) Background() Brush {
return ne.edit.Background()
}
// SetBackground sets the background Brush of the NumberEdit.
func (ne *NumberEdit) SetBackground(bg Brush) {
ne.edit.SetBackground(bg)
}
// TextColor returns the Color used to draw the text of the NumberEdit.
func (ne *NumberEdit) TextColor() Color {
return ne.edit.TextColor()
}
// TextColor sets the Color used to draw the text of the NumberEdit.
func (ne *NumberEdit) SetTextColor(c Color) {
ne.edit.SetTextColor(c)
}
// WndProc is the window procedure of the NumberEdit.
//
// When implementing your own WndProc to add or modify behavior, call the
// WndProc of the embedded NumberEdit for messages you don't handle yourself.
func (ne *NumberEdit) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
switch msg {
case win.WM_CTLCOLOREDIT, win.WM_CTLCOLORSTATIC:
if hBrush := ne.handleWMCTLCOLOR(wParam, lParam); hBrush != 0 {
return hBrush
}
case win.WM_SIZE, win.WM_SIZING:
if ne.edit == nil {
break
}
cb := ne.ClientBoundsPixels()
if err := ne.edit.SetBoundsPixels(cb); err != nil {
break
}
}
return ne.WidgetBase.WndProc(hwnd, msg, wParam, lParam)
}
type numberLineEdit struct {
*LineEdit
buf *bytes.Buffer
prefix []uint16
suffix []uint16
value float64
minValue float64
maxValue float64
increment float64
decimals int
valueChangedPublisher EventPublisher
inEditMode bool
}
func newNumberLineEdit(parent Widget) (*numberLineEdit, error) {
nle := &numberLineEdit{
buf: new(bytes.Buffer),
increment: 1,
}
var err error
if nle.LineEdit, err = newLineEdit(parent); err != nil {
return nil, err
}
succeeded := false
defer func() {
if !succeeded {
nle.Dispose()
}
}()
if err := nle.LineEdit.setAndClearStyleBits(win.ES_RIGHT, win.ES_LEFT|win.ES_CENTER); err != nil {
return nil, err
}
if err := InitWrapperWindow(nle); err != nil {
return nil, err
}
succeeded = true
return nle, nil
}
func (nle *numberLineEdit) TextColor() Color {
return nle.LineEdit.TextColor()
}
func (nle *numberLineEdit) SetTextColor(c Color) {
nle.LineEdit.SetTextColor(c)
}
func (nle *numberLineEdit) setValue(value float64, setText bool) error {
if setText {
if err := nle.setTextFromValue(value); err != nil {
return err
}
}
if value == nle.value {
return nil
}
nle.value = value
nle.valueChangedPublisher.Publish()
return nil
}
func (nle *numberLineEdit) setTextFromValue(value float64) error {
nle.buf.Reset()
nle.buf.WriteString(syscall.UTF16ToString(nle.prefix))
if nle.decimals > 0 {
nle.buf.WriteString(FormatFloatGrouped(value, nle.decimals))
} else {
nle.buf.WriteString(FormatFloat(value, nle.decimals))
}
nle.buf.WriteString(syscall.UTF16ToString(nle.suffix))
return nle.SetText(nle.buf.String())
}
func (nle *numberLineEdit) endEdit() error {
if err := nle.setTextFromValue(nle.value); err != nil {
return err
}
nle.inEditMode = false
return nil
}
func (nle *numberLineEdit) processChar(text []uint16, start, end int, key Key, char uint16) {
hadSelection := start != end
if !nle.inEditMode {
var groupSepsBeforeStart int
if nle.decimals > 0 {
groupSepsBeforeStart = uint16CountUint16(text[:start], groupSepUint16)
}
if hadSelection {
text = append(text[:start], text[end:]...)
}
if nle.decimals > 0 {
text = uint16RemoveUint16(text, groupSepUint16)
start -= groupSepsBeforeStart
}
nle.inEditMode = true
} else {
if hadSelection {
text = append(text[:start], text[end:]...)
}
}
end = start
switch key {
case KeyBack:
if !hadSelection && start > 0 {
start -= 1
text = append(text[:start], text[start+1:]...)
}
case KeyDelete:
if !hadSelection && start < len(text) {
text = append(text[:start], text[start+1:]...)
}
default:
t := make([]uint16, len(text[:start]), len(text)+1)
copy(t, text[:start])
t = append(t, char)
text = append(t, text[start:]...)
start += 1
}
nle.buf.Reset()
str := syscall.UTF16ToString(text)
nle.buf.WriteString(syscall.UTF16ToString(nle.prefix))
nle.buf.WriteString(str)
nle.buf.WriteString(syscall.UTF16ToString(nle.suffix))
nle.SetText(nle.buf.String())
start += len(nle.prefix)
nle.SetTextSelection(start, start)
nle.tryUpdateValue(false)
}
func (nle *numberLineEdit) tryUpdateValue(setText bool) bool {
t := nle.textUTF16()
t = t[len(nle.prefix) : len(t)-len(nle.suffix)]
text := strings.Replace(syscall.UTF16ToString(t), decimalSepS, ".", 1)
switch text {
case "", ".":
text = "0"
}
if value, err := strconv.ParseFloat(text, 64); err == nil {
if nle.minValue == nle.maxValue || value >= nle.minValue && value <= nle.maxValue {
return nle.setValue(value, setText) == nil
}
}
return false
}
func (nle *numberLineEdit) selectNumber() {
nle.SetTextSelection(len(nle.prefix), len(nle.textUTF16())-len(nle.suffix))
}
func (nle *numberLineEdit) textUTF16() []uint16 {
textLength := nle.SendMessage(win.WM_GETTEXTLENGTH, 0, 0)
buf := make([]uint16, textLength+1)
nle.SendMessage(win.WM_GETTEXT, uintptr(textLength+1), uintptr(unsafe.Pointer(&buf[0])))
return buf[:len(buf)-1]
}
func (nle *numberLineEdit) incrementValue(delta float64) {
value := nle.value + delta
if nle.minValue != nle.maxValue {
if value < nle.minValue {
value = nle.minValue
} else if value > nle.maxValue {
value = nle.maxValue
}
}
nle.setValue(value, true)
nle.selectNumber()
}
func (nle *numberLineEdit) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
switch msg {
case win.WM_CHAR:
if nle.ReadOnly() {
break
}
if AltDown() {
return 0
}
if ControlDown() {
if wParam == 1 {
// Ctrl+A
return 0
}
break
}
char := uint16(wParam)
text := nle.textUTF16()
text = text[len(nle.prefix) : len(text)-len(nle.suffix)]
start, end := nle.TextSelection()
start -= len(nle.prefix)
end -= len(nle.prefix)
if Key(wParam) == KeyBack {
nle.processChar(text, start, end, KeyBack, 0)
return 0
}
switch char {
case uint16('0'), uint16('1'), uint16('2'), uint16('3'), uint16('4'), uint16('5'), uint16('6'), uint16('7'), uint16('8'), uint16('9'):
if start == end && nle.decimals > 0 {
if i := uint16IndexUint16(text, decimalSepUint16); i > -1 && i < len(text)-nle.decimals && start > i {
return 0
}
}
nle.processChar(text, start, end, 0, char)
return 0
case uint16('-'):
if nle.minValue != nle.maxValue && nle.minValue >= 0 {
return 0
}
if start > 0 || uint16ContainsUint16(text, uint16('-')) && end == 0 {
return 0
}
nle.processChar(text, start, end, 0, char)
return 0
case decimalSepUint16:
if nle.decimals == 0 {
return 0
}
if start == 0 && end == 0 && len(text) > 0 && text[0] == '-' {
return 0
}
if end < len(text)-nle.decimals {
return 0
}
if i := uint16IndexUint16(text, decimalSepUint16); i > -1 && i <= start || i > end {
return 0
}
nle.processChar(text, start, end, 0, char)
return 0
default:
return 0
}
case win.WM_KEYDOWN:
switch Key(wParam) {
case KeyA:
if ControlDown() {
nle.selectNumber()
return 0
}
case KeyDelete:
if nle.ReadOnly() {
break
}
text := nle.textUTF16()
text = text[len(nle.prefix) : len(text)-len(nle.suffix)]
start, end := nle.TextSelection()
start -= len(nle.prefix)
end -= len(nle.prefix)
nle.processChar(text, start, end, KeyDelete, 0)
return 0
case KeyDown:
if nle.ReadOnly() || nle.increment <= 0 {
return 0
}
nle.incrementValue(-nle.increment)
return 0
case KeyEnd:
start, end := nle.TextSelection()
end = len(nle.textUTF16()) - len(nle.suffix)
if !ShiftDown() {
start = end
}
nle.SetTextSelection(start, end)
return 0
case KeyHome:
start, end := nle.TextSelection()
start = len(nle.prefix)
if !ShiftDown() {
end = start
}
nle.SetTextSelection(start, end)
return 0
case KeyLeft:
var pos win.POINT
win.GetCaretPos(&pos)
lParam := uintptr(win.MAKELONG(uint16(pos.X), uint16(pos.Y)))
i := int(win.LOWORD(uint32(nle.SendMessage(win.EM_CHARFROMPOS, 0, lParam))))
if min := len(nle.prefix); i <= min {
if !ShiftDown() {
nle.SetTextSelection(min, min)
}
return 0
}
case KeyReturn:
if nle.ReadOnly() {
break
}
if nle.inEditMode {
nle.endEdit()
nle.selectNumber()
return 0
}
case KeyRight:
var pos win.POINT
win.GetCaretPos(&pos)
lParam := uintptr(win.MAKELONG(uint16(pos.X), uint16(pos.Y)))
i := int(win.LOWORD(uint32(nle.SendMessage(win.EM_CHARFROMPOS, 0, lParam))))
if max := len(nle.textUTF16()) - len(nle.suffix); i >= max {
if !ShiftDown() {
nle.SetTextSelection(max, max)
}
return 0
}
case KeyUp:
if nle.ReadOnly() || nle.increment <= 0 {
return 0
}
nle.incrementValue(nle.increment)
return 0
}
case win.WM_GETDLGCODE:
if !nle.inEditMode {
if form := ancestor(nle); form != nil {
if dlg, ok := form.(dialogish); ok {
if dlg.DefaultButton() != nil {
// If the NumberEdit lives in a Dialog that has a
// DefaultButton, we won't swallow the return key.
break
}
}
}
}
if wParam == win.VK_RETURN {
return win.DLGC_WANTALLKEYS
}
case win.WM_KILLFOCUS:
nle.onFocusChanged()
nle.endEdit()
case win.WM_LBUTTONDOWN:
i := int(win.LOWORD(uint32(nle.SendMessage(win.EM_CHARFROMPOS, 0, lParam))))
if min := len(nle.prefix); i < min {
nle.SetFocus()
nle.SetTextSelection(min, min)
return 0
}
if max := len(nle.textUTF16()) - len(nle.suffix); i > max {
nle.SetFocus()
nle.SetTextSelection(max, max)
return 0
}
case win.WM_LBUTTONDBLCLK:
nle.selectNumber()
return 0
case win.WM_MOUSEMOVE:
i := int(win.LOWORD(uint32(nle.SendMessage(win.EM_CHARFROMPOS, 0, lParam))))
if min := len(nle.prefix); i < min {
return 0
}
if max := len(nle.textUTF16()) - len(nle.suffix); i > max {
return 0
}
case win.WM_MOUSEWHEEL:
if nle.ReadOnly() || nle.increment <= 0 {
break
}
delta := float64(int16(win.HIWORD(uint32(wParam))))
nle.incrementValue(delta / 120 * nle.increment)
return 0
case win.WM_PASTE:
if nle.ReadOnly() {
break
}
ret := nle.LineEdit.WndProc(hwnd, msg, wParam, lParam)
if !nle.tryUpdateValue(true) {
nle.setTextFromValue(nle.value)
}
nle.selectNumber()
return ret
case win.WM_SETFOCUS:
nle.onFocusChanged()
nle.selectNumber()
case win.EM_SETSEL:
start := int(wParam)
end := int(lParam)
adjusted := false
if min := len(nle.prefix); start < min {
start = min
adjusted = true
}
if max := len(nle.textUTF16()) - len(nle.suffix); end < 0 || end > max {
end = max
adjusted = true
}
if adjusted {
nle.SetTextSelection(start, end)
return 0
}
}
return nle.LineEdit.WndProc(hwnd, msg, wParam, lParam)
}
func (nle *numberLineEdit) onFocusChanged() {
if ne := windowFromHandle(win.GetParent(nle.hWnd)); ne != nil {
if wnd := windowFromHandle(win.GetParent(ne.Handle())); wnd != nil {
if _, ok := wnd.(Container); ok {
ne.(Widget).AsWidgetBase().invalidateBorderInParent()
}
}
}
}
func (ne *NumberEdit) SetToolTipText(s string) error {
return ne.edit.SetToolTipText(s)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/xuchengzhi/lxnWalk.git
git@gitee.com:xuchengzhi/lxnWalk.git
xuchengzhi
lxnWalk
lxnWalk
6b3f71bcaf88

搜索帮助