diff --git a/redo/area_windows.c b/redo/area_windows.c index 7e49bff..8985c04 100644 --- a/redo/area_windows.c +++ b/redo/area_windows.c @@ -438,3 +438,37 @@ HWND newArea(void *data) xpanic("container creation failed", GetLastError()); return hwnd; } + +static LRESULT CALLBACK areaTextFieldSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) +{ + switch (uMsg) { + case WM_KILLFOCUS: + ShowWindow(hwnd, SW_HIDE); + return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); + case WM_NCDESTROY: + if ((*fv_RemoveWindowSubclass)(hwnd, areaTextFieldSubProc, id) == FALSE) + xpanic("error removing Area TextField subclass (which was for handling WM_KILLFOCUS)", GetLastError()); + return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); + default: + return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); + } + xmissedmsg("Area TextField", "areaTextFieldSubProc()", uMsg); + return 0; // unreached +} + +HWND newAreaTextField(HWND area) +{ + HWND tf; + + tf = CreateWindowExW(textfieldExtStyle | WS_EX_TOOLWINDOW, + L"edit", L"", + textfieldStyle | WS_POPUP, + 0, 0, 0, 0, + area, // owner window + NULL, hInstance, NULL); + if (tf == NULL) + xpanic("error making Area TextField", GetLastError()); + if ((*fv_SetWindowSubclass)(tf, areaTextFieldSubProc, 0, (DWORD_PTR) NULL) == FALSE) + xpanic("error subclassing Area TextField to give it its own WM_KILLFOCUS handler", GetLastError()); + return tf; +} diff --git a/redo/area_windows.go b/redo/area_windows.go index 1ab3156..e2f4fb6 100644 --- a/redo/area_windows.go +++ b/redo/area_windows.go @@ -18,6 +18,8 @@ type area struct { _hwnd C.HWND clickCounter *clickCounter + + textfield C.HWND } func makeAreaWindowClass() error { @@ -37,6 +39,8 @@ func newArea(ab *areabase) Area { } a._hwnd = C.newArea(unsafe.Pointer(a)) a.SetSize(a.width, a.height) + a.textfield = C.newAreaTextField(a._hwnd) + C.controlSetControlFont(a.textfield) return a } @@ -67,6 +71,31 @@ func (a *area) RepaintAll() { C.SendMessageW(a._hwnd, C.msgAreaRepaintAll, 0, 0) } +// TODO somehow use textfield.preferredSIze() here +func (a *area) OpenTextFieldAt(x, y int) { + if x < 0 || x >= a.width || y < 0 || y >= a.height { + panic(fmt.Errorf("point (%d,%d) outside Area in Area.OpenTextFieldAt()", x, y)) + } + C.moveWindow(a.textfield, C.int(x), C.int(y), C.int(200), C.int(20)) + C.ShowWindow(a.textfield, C.SW_SHOW) + // TODO SetFocus +} + +func (a *area) TextFieldText() string { + return getWindowText(a.textfield) +} + +func (a *area) SetTextFieldText(text string) { + t := toUTF16(text) + C.setWindowText(a.textfield, t) + // TODO +// c.settextlen(C.controlTextLength(hwnd, t)) +} + +func (a *area) OnTextFieldDismissed(f func()) { + // TODO +} + //export doPaint func doPaint(xrect *C.RECT, hscroll C.int, vscroll C.int, data unsafe.Pointer, dx *C.intptr_t, dy *C.intptr_t) unsafe.Pointer { a := (*area)(data) diff --git a/redo/textfield_windows.go b/redo/textfield_windows.go index 5f89691..236be97 100644 --- a/redo/textfield_windows.go +++ b/redo/textfield_windows.go @@ -19,8 +19,8 @@ var editclass = toUTF16("EDIT") func startNewTextField(style C.DWORD) *textfield { hwnd := C.newControl(editclass, - style | C.ES_AUTOHSCROLL | C.ES_LEFT | C.ES_NOHIDESEL | C.WS_TABSTOP, - C.WS_EX_CLIENTEDGE) // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog) + style | C.textfieldStyle, + C.textfieldExtStyle) // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog) t := &textfield{ _hwnd: hwnd, changed: newEvent(), diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h index 7beb888..e92cca3 100644 --- a/redo/winapi_windows.h +++ b/redo/winapi_windows.h @@ -67,6 +67,8 @@ extern void setButtonSubclass(HWND, void *); extern void setCheckboxSubclass(HWND, void *); extern BOOL checkboxChecked(HWND); extern void checkboxSetChecked(HWND, BOOL); +#define textfieldStyle (ES_AUTOHSCROLL | ES_LEFT | ES_NOHIDESEL | WS_TABSTOP) +#define textfieldExtStyle (WS_EX_CLIENTEDGE) extern void setTextFieldSubclass(HWND, void *); extern void textfieldSetAndShowInvalidBalloonTip(HWND, WCHAR *); extern void textfieldHideInvalidBalloonTip(HWND); @@ -127,6 +129,7 @@ extern void calculateBaseUnits(HWND, int *, int *, LONG *); extern void repaintArea(HWND, RECT *); extern DWORD makeAreaWindowClass(char **); extern HWND newArea(void *); +extern HWND newAreaTextField(HWND); // imagelist_windows.c extern HBITMAP unscaledBitmap(void *, intptr_t, intptr_t);