From 5fc368fc23f0720fc193883d0709df8417268987 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Wed, 5 Nov 2014 12:59:44 -0500 Subject: [PATCH] Started adding TextField.ReadOnly() and implemented it (mostly) on Windows. --- basicctrls.go | 6 ++++++ basicctrls_windows.c | 13 +++++++++++++ common_windows.c | 1 + textfield_windows.go | 12 ++++++++++++ winapi_windows.h | 2 ++ zz_test.go | 9 +++++++++ 6 files changed, 43 insertions(+) diff --git a/basicctrls.go b/basicctrls.go index b80a25a..e905ad2 100644 --- a/basicctrls.go +++ b/basicctrls.go @@ -57,6 +57,11 @@ type TextField interface { // The string passed to Invalid will be displayed to the user to inform them of what specifically is wrong with the input. // Pass an empty string to remove the warning. Invalid(reason string) + + // ReadOnly and SetReadOnly get and set whether the TextField is read-only. + // A read-only TextField cannot be changed by the user, but its text can still be manipulated in other ways (selecting, copying, etc.). + ReadOnly() bool + SetReadOnly(readonly bool) } // NewTextField creates a new TextField. @@ -127,6 +132,7 @@ func NewGroup(text string, control Control) Group { // TODO rename to TextBox? merge with TextField (but cannot use Invalid())? enable/disable line wrapping? // TODO events // TODO Tab key - insert horizontal tab or tab stop? +// TODO ReadOnly type Textbox interface { Control diff --git a/basicctrls_windows.c b/basicctrls_windows.c index 4cda2eb..b33bce2 100644 --- a/basicctrls_windows.c +++ b/basicctrls_windows.c @@ -128,6 +128,19 @@ void textfieldHideInvalidBalloonTip(HWND hwnd) xpanic("error hiding TextField.Invalid() balloon tip", GetLastError()); } +// also good for Textbox +int textfieldReadOnly(HWND hwnd) +{ + return (GetWindowLongPtrW(hwnd, GWL_STYLE) & ES_READONLY) != 0; +} + +// also good for Textbox +void textfieldSetReadOnly(HWND hwnd, BOOL readonly) +{ + if (SendMessageW(hwnd, EM_SETREADONLY, (WPARAM) readonly, 0) == 0) + xpanic("error setting TextField/Textbox as read-only/not read-only", GetLastError()); +} + static LRESULT CALLBACK groupSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) { LRESULT lResult; diff --git a/common_windows.c b/common_windows.c index ca42eab..207b691 100644 --- a/common_windows.c +++ b/common_windows.c @@ -85,6 +85,7 @@ BOOL sharedWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT * return TRUE; case WM_CTLCOLORSTATIC: case WM_CTLCOLORBTN: + // TODO exempt read-only textboxes if (SetBkMode((HDC) wParam, TRANSPARENT) == 0) xpanic("error setting transparent background mode to Labels", GetLastError()); paintControlBackground((HWND) lParam, (HDC) wParam); diff --git a/textfield_windows.go b/textfield_windows.go index 1d2025b..a78a12f 100644 --- a/textfield_windows.go +++ b/textfield_windows.go @@ -58,6 +58,18 @@ func (t *textfield) Invalid(reason string) { C.textfieldSetAndShowInvalidBalloonTip(t.hwnd, toUTF16(reason)) } +func (t *textfield) ReadOnly() bool { + return C.textfieldReadOnly(t.hwnd) != 0 +} + +func (t *textfield) SetReadOnly(readonly bool) { + if readonly { + C.textfieldSetReadOnly(t.hwnd, C.TRUE) + return + } + C.textfieldSetReadOnly(t.hwnd, C.FALSE) +} + //export textfieldChanged func textfieldChanged(data unsafe.Pointer) { t := (*textfield)(data) diff --git a/winapi_windows.h b/winapi_windows.h index 75476b1..9642397 100644 --- a/winapi_windows.h +++ b/winapi_windows.h @@ -74,6 +74,8 @@ extern void checkboxSetChecked(HWND, BOOL); extern void setTextFieldSubclass(HWND, void *); extern void textfieldSetAndShowInvalidBalloonTip(HWND, WCHAR *); extern void textfieldHideInvalidBalloonTip(HWND); +extern int textfieldReadOnly(HWND); +extern void textfieldSetReadOnly(HWND, BOOL); extern void setGroupSubclass(HWND, void *); extern HWND newUpDown(HWND, void *); extern void setSpinboxEditSubclass(HWND, void *); diff --git a/zz_test.go b/zz_test.go index bc2865f..478d3ea 100644 --- a/zz_test.go +++ b/zz_test.go @@ -54,6 +54,8 @@ var ddata = []dtype{ type testwin struct { t Tab w Window + roenter TextField + roro TextField repainter *repainter fe *ForeignEvent festack Stack @@ -176,6 +178,13 @@ func (tw *testwin) make(done chan struct{}) { done <- struct{}{} return true }) + tw.roenter = NewTextField() + tw.roro = NewTextField() + tw.roro.SetReadOnly(true) + tw.roenter.OnChanged(func() { + tw.roro.SetText(tw.roenter.Text()) + }) + tw.t.Append("Read-Only", newVerticalStack(tw.roenter, tw.roro)) tw.icons, tw.il = readIcons() // repainter uses these tw.repainter = newRepainter(15) tw.t.Append("Repaint", tw.repainter.grid)