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;
|
dx = 0;
|
||||||
dy = delta;
|
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,
|
if (ScrollWindowEx(hwnd,
|
||||||
(int) dx, (int) dy,
|
(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
|
// 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
|
// NOW redraw it
|
||||||
if (UpdateWindow(hwnd) == 0)
|
if (UpdateWindow(hwnd) == 0)
|
||||||
xpanic("error updating Area after scrolling", GetLastError());
|
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)
|
static void adjustAreaScrollbars(HWND hwnd, void *data)
|
||||||
|
@ -411,7 +434,8 @@ DWORD makeAreaWindowClass(char **errmsg)
|
||||||
wc.hInstance = hInstance;
|
wc.hInstance = hInstance;
|
||||||
wc.hIcon = hDefaultIcon;
|
wc.hIcon = hDefaultIcon;
|
||||||
wc.hCursor = hArrowCursor,
|
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) {
|
if (RegisterClassW(&wc) == 0) {
|
||||||
*errmsg = "error registering Area window class";
|
*errmsg = "error registering Area window class";
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
|
@ -440,6 +464,7 @@ static LRESULT CALLBACK areaTextFieldSubProc(HWND hwnd, UINT uMsg, WPARAM wParam
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
case WM_KILLFOCUS:
|
case WM_KILLFOCUS:
|
||||||
ShowWindow(hwnd, SW_HIDE);
|
ShowWindow(hwnd, SW_HIDE);
|
||||||
|
areaTextFieldDone((void *) data);
|
||||||
return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
|
return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
|
||||||
case WM_NCDESTROY:
|
case WM_NCDESTROY:
|
||||||
if ((*fv_RemoveWindowSubclass)(hwnd, areaTextFieldSubProc, id) == FALSE)
|
if ((*fv_RemoveWindowSubclass)(hwnd, areaTextFieldSubProc, id) == FALSE)
|
||||||
|
@ -452,7 +477,7 @@ static LRESULT CALLBACK areaTextFieldSubProc(HWND hwnd, UINT uMsg, WPARAM wParam
|
||||||
return 0; // unreached
|
return 0; // unreached
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND newAreaTextField(HWND area)
|
HWND newAreaTextField(HWND area, void *goarea)
|
||||||
{
|
{
|
||||||
HWND tf;
|
HWND tf;
|
||||||
|
|
||||||
|
@ -460,11 +485,34 @@ HWND newAreaTextField(HWND area)
|
||||||
L"edit", L"",
|
L"edit", L"",
|
||||||
textfieldStyle | WS_CHILD,
|
textfieldStyle | WS_CHILD,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
area, // owner window
|
area, NULL, hInstance, NULL);
|
||||||
NULL, hInstance, NULL);
|
|
||||||
if (tf == NULL)
|
if (tf == NULL)
|
||||||
xpanic("error making Area TextField", GetLastError());
|
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());
|
xpanic("error subclassing Area TextField to give it its own WM_KILLFOCUS handler", GetLastError());
|
||||||
return tf;
|
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
|
clickCounter *clickCounter
|
||||||
|
|
||||||
textfield C.HWND
|
textfield C.HWND
|
||||||
|
textfielddone *event
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeAreaWindowClass() error {
|
func makeAreaWindowClass() error {
|
||||||
|
@ -36,10 +37,11 @@ func newArea(ab *areabase) Area {
|
||||||
a := &area{
|
a := &area{
|
||||||
areabase: ab,
|
areabase: ab,
|
||||||
clickCounter: new(clickCounter),
|
clickCounter: new(clickCounter),
|
||||||
|
textfielddone: newEvent(),
|
||||||
}
|
}
|
||||||
a._hwnd = C.newArea(unsafe.Pointer(a))
|
a._hwnd = C.newArea(unsafe.Pointer(a))
|
||||||
a.SetSize(a.width, a.height)
|
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)
|
C.controlSetControlFont(a.textfield)
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
@ -76,9 +78,7 @@ func (a *area) OpenTextFieldAt(x, y int) {
|
||||||
if x < 0 || x >= a.width || y < 0 || y >= a.height {
|
if x < 0 || x >= a.width || y < 0 || y >= a.height {
|
||||||
panic(fmt.Errorf("point (%d,%d) outside Area in Area.OpenTextFieldAt()", x, y))
|
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.areaOpenTextField(a._hwnd, a.textfield, C.int(x), C.int(y), textfieldWidth, textfieldHeight)
|
||||||
C.ShowWindow(a.textfield, C.SW_SHOW)
|
|
||||||
// TODO SetFocus
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *area) TextFieldText() string {
|
func (a *area) TextFieldText() string {
|
||||||
|
@ -88,12 +88,17 @@ func (a *area) TextFieldText() string {
|
||||||
func (a *area) SetTextFieldText(text string) {
|
func (a *area) SetTextFieldText(text string) {
|
||||||
t := toUTF16(text)
|
t := toUTF16(text)
|
||||||
C.setWindowText(a.textfield, t)
|
C.setWindowText(a.textfield, t)
|
||||||
// TODO
|
|
||||||
// c.settextlen(C.controlTextLength(hwnd, t))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *area) OnTextFieldDismissed(f func()) {
|
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
|
//export doPaint
|
||||||
|
|
|
@ -124,12 +124,14 @@ extern DWORD makeContainerWindowClass(char **);
|
||||||
extern HWND newContainer(void *);
|
extern HWND newContainer(void *);
|
||||||
extern void calculateBaseUnits(HWND, int *, int *, LONG *);
|
extern void calculateBaseUnits(HWND, int *, int *, LONG *);
|
||||||
|
|
||||||
// area_window.c
|
// area_windows.c
|
||||||
#define areaWindowClass L"gouiarea"
|
#define areaWindowClass L"gouiarea"
|
||||||
extern void repaintArea(HWND, RECT *);
|
extern void repaintArea(HWND, RECT *);
|
||||||
extern DWORD makeAreaWindowClass(char **);
|
extern DWORD makeAreaWindowClass(char **);
|
||||||
extern HWND newArea(void *);
|
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
|
// imagelist_windows.c
|
||||||
extern HBITMAP unscaledBitmap(void *, intptr_t, intptr_t);
|
extern HBITMAP unscaledBitmap(void *, intptr_t, intptr_t);
|
||||||
|
|
Loading…
Reference in New Issue