Implemented more/most of Area.OpenTextFieldAt() on Windows.
This commit is contained in:
parent
f10c1f56b5
commit
d679f5c5d9
|
@ -233,6 +233,26 @@ static void scrollArea(HWND hwnd, void *data, WPARAM wParam, int which)
|
|||
dx = 0;
|
||||
dy = delta;
|
||||
}
|
||||
|
||||
// first move the edit control, if any, to avoid artifacting
|
||||
if ((HWND) GetWindowLongPtrW(hwnd, 0) != NULL) {
|
||||
HWND edit;
|
||||
int x, y;
|
||||
|
||||
edit = (HWND) GetWindowLongPtrW(hwnd, 0);
|
||||
x = (int) GetWindowLongPtrW(hwnd, sizeof (LONG_PTR));
|
||||
y = (int) GetWindowLongPtrW(hwnd, 2 * sizeof (LONG_PTR));
|
||||
x += dx;
|
||||
y += dy;
|
||||
if (SetWindowPos(edit, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER) == 0)
|
||||
xpanic("error moving Area TextField in response to scroll", GetLastError());
|
||||
SetWindowLongPtrW(hwnd, sizeof (LONG_PTR), (LONG_PTR) x);
|
||||
SetWindowLongPtrW(hwnd, 2 * sizeof (LONG_PTR), (LONG_PTR) y);
|
||||
// TODO doesn't work?
|
||||
if (InvalidateRect(edit, NULL, TRUE) == 0)
|
||||
xpanic("error marking Area TextField as needing redraw", GetLastError());
|
||||
}
|
||||
|
||||
if (ScrollWindowEx(hwnd,
|
||||
(int) dx, (int) dy,
|
||||
// these four change what is scrolled and record info about the scroll; we're scrolling the whole client area and don't care about the returned information here
|
||||
|
@ -253,6 +273,9 @@ static void scrollArea(HWND hwnd, void *data, WPARAM wParam, int which)
|
|||
// NOW redraw it
|
||||
if (UpdateWindow(hwnd) == 0)
|
||||
xpanic("error updating Area after scrolling", GetLastError());
|
||||
if ((HWND) GetWindowLongPtrW(hwnd, 0) != NULL)
|
||||
if (UpdateWindow((HWND) GetWindowLongPtrW(hwnd, 0)) == 0)
|
||||
xpanic("error updating Area TextField after scrolling", GetLastError());
|
||||
}
|
||||
|
||||
static void adjustAreaScrollbars(HWND hwnd, void *data)
|
||||
|
@ -411,7 +434,8 @@ DWORD makeAreaWindowClass(char **errmsg)
|
|||
wc.hInstance = hInstance;
|
||||
wc.hIcon = hDefaultIcon;
|
||||
wc.hCursor = hArrowCursor,
|
||||
wc.hbrBackground = NULL; // no brush; we handle WM_ERASEBKGND
|
||||
wc.hbrBackground = NULL; // no brush; we handle WM_ERASEBKGND
|
||||
wc.cbWndExtra = 3 * sizeof (LONG_PTR); // text field handle, text field current x, text field current y
|
||||
if (RegisterClassW(&wc) == 0) {
|
||||
*errmsg = "error registering Area window class";
|
||||
return GetLastError();
|
||||
|
@ -440,6 +464,7 @@ static LRESULT CALLBACK areaTextFieldSubProc(HWND hwnd, UINT uMsg, WPARAM wParam
|
|||
switch (uMsg) {
|
||||
case WM_KILLFOCUS:
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
areaTextFieldDone((void *) data);
|
||||
return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
|
||||
case WM_NCDESTROY:
|
||||
if ((*fv_RemoveWindowSubclass)(hwnd, areaTextFieldSubProc, id) == FALSE)
|
||||
|
@ -452,7 +477,7 @@ static LRESULT CALLBACK areaTextFieldSubProc(HWND hwnd, UINT uMsg, WPARAM wParam
|
|||
return 0; // unreached
|
||||
}
|
||||
|
||||
HWND newAreaTextField(HWND area)
|
||||
HWND newAreaTextField(HWND area, void *goarea)
|
||||
{
|
||||
HWND tf;
|
||||
|
||||
|
@ -460,11 +485,34 @@ HWND newAreaTextField(HWND area)
|
|||
L"edit", L"",
|
||||
textfieldStyle | WS_CHILD,
|
||||
0, 0, 0, 0,
|
||||
area, // owner window
|
||||
NULL, hInstance, NULL);
|
||||
area, NULL, hInstance, NULL);
|
||||
if (tf == NULL)
|
||||
xpanic("error making Area TextField", GetLastError());
|
||||
if ((*fv_SetWindowSubclass)(tf, areaTextFieldSubProc, 0, (DWORD_PTR) NULL) == FALSE)
|
||||
if ((*fv_SetWindowSubclass)(tf, areaTextFieldSubProc, 0, (DWORD_PTR) goarea) == FALSE)
|
||||
xpanic("error subclassing Area TextField to give it its own WM_KILLFOCUS handler", GetLastError());
|
||||
return tf;
|
||||
}
|
||||
|
||||
void areaOpenTextField(HWND area, HWND textfield, int x, int y, int width, int height)
|
||||
{
|
||||
int sx, sy;
|
||||
int baseX, baseY;
|
||||
LONG unused;
|
||||
|
||||
getScrollPos(area, &sx, &sy);
|
||||
x += sx;
|
||||
y += sy;
|
||||
calculateBaseUnits(textfield, &baseX, &baseY, &unused);
|
||||
width = MulDiv(width, baseX, 4);
|
||||
height = MulDiv(height, baseY, 8);
|
||||
if (MoveWindow(textfield, x, y, width, height, TRUE) == 0)
|
||||
xpanic("error moving Area TextField in Area.OpenTextFieldAt()", GetLastError());
|
||||
ShowWindow(textfield, SW_SHOW);
|
||||
if (SetFocus(textfield) == NULL)
|
||||
xpanic("error giving Area TextField focus", GetLastError());
|
||||
}
|
||||
|
||||
void areaMarkTextFieldDone(HWND area)
|
||||
{
|
||||
SetWindowLongPtrW(area, 0, (LONG_PTR) NULL);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ type area struct {
|
|||
clickCounter *clickCounter
|
||||
|
||||
textfield C.HWND
|
||||
textfielddone *event
|
||||
}
|
||||
|
||||
func makeAreaWindowClass() error {
|
||||
|
@ -36,10 +37,11 @@ func newArea(ab *areabase) Area {
|
|||
a := &area{
|
||||
areabase: ab,
|
||||
clickCounter: new(clickCounter),
|
||||
textfielddone: newEvent(),
|
||||
}
|
||||
a._hwnd = C.newArea(unsafe.Pointer(a))
|
||||
a.SetSize(a.width, a.height)
|
||||
a.textfield = C.newAreaTextField(a._hwnd)
|
||||
a.textfield = C.newAreaTextField(a._hwnd, unsafe.Pointer(a))
|
||||
C.controlSetControlFont(a.textfield)
|
||||
return a
|
||||
}
|
||||
|
@ -76,9 +78,7 @@ 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
|
||||
C.areaOpenTextField(a._hwnd, a.textfield, C.int(x), C.int(y), textfieldWidth, textfieldHeight)
|
||||
}
|
||||
|
||||
func (a *area) TextFieldText() string {
|
||||
|
@ -88,12 +88,17 @@ func (a *area) TextFieldText() string {
|
|||
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
|
||||
a.textfielddone.set(f)
|
||||
}
|
||||
|
||||
//export areaTextFieldDone
|
||||
func areaTextFieldDone(data unsafe.Pointer) {
|
||||
a := (*area)(data)
|
||||
C.areaMarkTextFieldDone(a._hwnd)
|
||||
a.textfielddone.fire()
|
||||
}
|
||||
|
||||
//export doPaint
|
||||
|
|
|
@ -124,12 +124,14 @@ extern DWORD makeContainerWindowClass(char **);
|
|||
extern HWND newContainer(void *);
|
||||
extern void calculateBaseUnits(HWND, int *, int *, LONG *);
|
||||
|
||||
// area_window.c
|
||||
// area_windows.c
|
||||
#define areaWindowClass L"gouiarea"
|
||||
extern void repaintArea(HWND, RECT *);
|
||||
extern DWORD makeAreaWindowClass(char **);
|
||||
extern HWND newArea(void *);
|
||||
extern HWND newAreaTextField(HWND);
|
||||
extern HWND newAreaTextField(HWND, void *);
|
||||
extern void areaOpenTextField(HWND, HWND, int, int, int, int);
|
||||
extern void areaMarkTextFieldDone(HWND);
|
||||
|
||||
// imagelist_windows.c
|
||||
extern HBITMAP unscaledBitmap(void *, intptr_t, intptr_t);
|
||||
|
|
Loading…
Reference in New Issue