textedit.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright 2010 The Walk Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build windows
  5. package walk
  6. import (
  7. "syscall"
  8. "unsafe"
  9. )
  10. import (
  11. "github.com/lxn/win"
  12. )
  13. type TextEdit struct {
  14. WidgetBase
  15. readOnlyChangedPublisher EventPublisher
  16. textChangedPublisher EventPublisher
  17. }
  18. func NewTextEdit(parent Container) (*TextEdit, error) {
  19. te := new(TextEdit)
  20. if err := InitWidget(
  21. te,
  22. parent,
  23. "EDIT",
  24. win.WS_TABSTOP|win.WS_VISIBLE|win.WS_VSCROLL|win.ES_MULTILINE|win.ES_WANTRETURN,
  25. win.WS_EX_CLIENTEDGE); err != nil {
  26. return nil, err
  27. }
  28. te.MustRegisterProperty("ReadOnly", NewProperty(
  29. func() interface{} {
  30. return te.ReadOnly()
  31. },
  32. func(v interface{}) error {
  33. return te.SetReadOnly(v.(bool))
  34. },
  35. te.readOnlyChangedPublisher.Event()))
  36. te.MustRegisterProperty("Text", NewProperty(
  37. func() interface{} {
  38. return te.Text()
  39. },
  40. func(v interface{}) error {
  41. return te.SetText(v.(string))
  42. },
  43. te.textChangedPublisher.Event()))
  44. return te, nil
  45. }
  46. func (*TextEdit) LayoutFlags() LayoutFlags {
  47. return ShrinkableHorz | ShrinkableVert | GrowableHorz | GrowableVert | GreedyHorz | GreedyVert
  48. }
  49. func (te *TextEdit) MinSizeHint() Size {
  50. return te.dialogBaseUnitsToPixels(Size{20, 12})
  51. }
  52. func (te *TextEdit) SizeHint() Size {
  53. return Size{100, 100}
  54. }
  55. func (te *TextEdit) Text() string {
  56. return windowText(te.hWnd)
  57. }
  58. func (te *TextEdit) TextLength() int {
  59. return int(te.SendMessage(win.WM_GETTEXTLENGTH, 0, 0))
  60. }
  61. func (te *TextEdit) SetText(value string) error {
  62. return setWindowText(te.hWnd, value)
  63. }
  64. func (te *TextEdit) MaxLength() int {
  65. return int(te.SendMessage(win.EM_GETLIMITTEXT, 0, 0))
  66. }
  67. func (te *TextEdit) SetMaxLength(value int) {
  68. te.SendMessage(win.EM_SETLIMITTEXT, uintptr(value), 0)
  69. }
  70. func (te *TextEdit) TextSelection() (start, end int) {
  71. te.SendMessage(win.EM_GETSEL, uintptr(unsafe.Pointer(&start)), uintptr(unsafe.Pointer(&end)))
  72. return
  73. }
  74. func (te *TextEdit) SetTextSelection(start, end int) {
  75. te.SendMessage(win.EM_SETSEL, uintptr(start), uintptr(end))
  76. }
  77. func (te *TextEdit) ReplaceSelectedText(text string, canUndo bool) {
  78. te.SendMessage(win.EM_REPLACESEL,
  79. uintptr(win.BoolToBOOL(canUndo)),
  80. uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))))
  81. }
  82. func (te *TextEdit) AppendText(value string) {
  83. s, e := te.TextSelection()
  84. l := te.TextLength()
  85. te.SetTextSelection(l, l)
  86. te.ReplaceSelectedText(value, false)
  87. te.SetTextSelection(s, e)
  88. }
  89. func (te *TextEdit) ReadOnly() bool {
  90. return te.hasStyleBits(win.ES_READONLY)
  91. }
  92. func (te *TextEdit) SetReadOnly(readOnly bool) error {
  93. if 0 == te.SendMessage(win.EM_SETREADONLY, uintptr(win.BoolToBOOL(readOnly)), 0) {
  94. return newError("SendMessage(EM_SETREADONLY)")
  95. }
  96. te.readOnlyChangedPublisher.Publish()
  97. return nil
  98. }
  99. func (te *TextEdit) TextChanged() *Event {
  100. return te.textChangedPublisher.Event()
  101. }
  102. func (te *TextEdit) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
  103. switch msg {
  104. case win.WM_COMMAND:
  105. switch win.HIWORD(uint32(wParam)) {
  106. case win.EN_CHANGE:
  107. te.textChangedPublisher.Publish()
  108. }
  109. case win.WM_GETDLGCODE:
  110. if wParam == win.VK_RETURN {
  111. return win.DLGC_WANTALLKEYS
  112. }
  113. return win.DLGC_HASSETSEL | win.DLGC_WANTARROWS | win.DLGC_WANTCHARS
  114. case win.WM_KEYDOWN:
  115. if Key(wParam) == KeyA && ControlDown() {
  116. te.SetTextSelection(0, -1)
  117. }
  118. }
  119. return te.WidgetBase.WndProc(hwnd, msg, wParam, lParam)
  120. }