libui/windows/area.cpp

207 lines
4.7 KiB
C++

// 8 september 2015
#include "uipriv_windows.hpp"
#include "area.hpp"
// TODO handle WM_DESTROY/WM_NCDESTROY
// TODO same for other Direct2D stuff
static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
uiArea *a;
CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam;
RECT client;
WINDOWPOS *wp = (WINDOWPOS *) lParam;
LRESULT lResult;
a = (uiArea *) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
if (a == NULL) {
if (uMsg == WM_CREATE) {
a = (uiArea *) (cs->lpCreateParams);
// assign a->hwnd here so we can use it immediately
a->hwnd = hwnd;
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) a);
}
// fall through to DefWindowProcW() anyway
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
// always recreate the render target if necessary
if (a->rt == NULL)
a->rt = makeHWNDRenderTarget(a->hwnd);
if (areaDoDraw(a, uMsg, wParam, lParam, &lResult) != FALSE)
return lResult;
if (uMsg == WM_WINDOWPOSCHANGED) {
if ((wp->flags & SWP_NOSIZE) != 0)
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
uiWindowsEnsureGetClientRect(a->hwnd, &client);
areaDrawOnResize(a, &client);
areaScrollOnResize(a, &client);
return 0;
}
if (areaDoScroll(a, uMsg, wParam, lParam, &lResult) != FALSE)
return lResult;
if (areaDoEvents(a, uMsg, wParam, lParam, &lResult) != FALSE)
return lResult;
// nothing done
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
// control implementation
uiWindowsControlAllDefaults(uiArea)
static void uiAreaMinimumSize(uiWindowsControl *c, int *width, int *height)
{
// TODO
*width = 0;
*height = 0;
}
ATOM registerAreaClass(HICON hDefaultIcon, HCURSOR hDefaultCursor)
{
WNDCLASSW wc;
ZeroMemory(&wc, sizeof (WNDCLASSW));
wc.lpszClassName = areaClass;
wc.lpfnWndProc = areaWndProc;
wc.hInstance = hInstance;
wc.hIcon = hDefaultIcon;
wc.hCursor = hDefaultCursor;
wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
// this is just to be safe; see the InvalidateRect() call in the WM_WINDOWPOSCHANGED handler for more details
wc.style = CS_HREDRAW | CS_VREDRAW;
return RegisterClassW(&wc);
}
void unregisterArea(void)
{
if (UnregisterClassW(areaClass, hInstance) == 0)
logLastError(L"error unregistering uiArea window class");
}
void uiAreaSetSize(uiArea *a, int width, int height)
{
a->scrollWidth = width;
a->scrollHeight = height;
areaUpdateScroll(a);
}
void uiAreaQueueRedrawAll(uiArea *a)
{
// don't erase the background; we do that ourselves in doPaint()
invalidateRect(a->hwnd, NULL, FALSE);
}
void uiAreaScrollTo(uiArea *a, double x, double y, double width, double height)
{
// TODO
}
void uiAreaBeginUserWindowMove(uiArea *a)
{
HWND toplevel;
// TODO restrict execution
ReleaseCapture(); // TODO use properly and reset internal data structures
toplevel = parentToplevel(a->hwnd);
if (toplevel == NULL) {
// TODO
return;
}
// see http://stackoverflow.com/questions/40249940/how-do-i-initiate-a-user-mouse-driven-move-or-resize-for-custom-window-borders-o#40250654
SendMessageW(toplevel, WM_SYSCOMMAND,
SC_MOVE | 2, 0);
}
void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge)
{
HWND toplevel;
WPARAM wParam;
// TODO restrict execution
ReleaseCapture(); // TODO use properly and reset internal data structures
toplevel = parentToplevel(a->hwnd);
if (toplevel == NULL) {
// TODO
return;
}
// see http://stackoverflow.com/questions/40249940/how-do-i-initiate-a-user-mouse-driven-move-or-resize-for-custom-window-borders-o#40250654
wParam = SC_SIZE;
switch (edge) {
case uiWindowResizeEdgeLeft:
wParam |= 1;
break;
case uiWindowResizeEdgeTop:
wParam |= 3;
break;
case uiWindowResizeEdgeRight:
wParam |= 2;
break;
case uiWindowResizeEdgeBottom:
wParam |= 6;
break;
case uiWindowResizeEdgeTopLeft:
wParam |= 4;
break;
case uiWindowResizeEdgeTopRight:
wParam |= 5;
break;
case uiWindowResizeEdgeBottomLeft:
wParam |= 7;
break;
case uiWindowResizeEdgeBottomRight:
wParam |= 8;
break;
}
SendMessageW(toplevel, WM_SYSCOMMAND,
wParam, 0);
}
uiArea *uiNewArea(uiAreaHandler *ah)
{
uiArea *a;
uiWindowsNewControl(uiArea, a);
a->ah = ah;
a->scrolling = FALSE;
uiprivClickCounterReset(&(a->cc));
// a->hwnd is assigned in areaWndProc()
uiWindowsEnsureCreateControlHWND(0,
areaClass, L"",
0,
hInstance, a,
FALSE);
return a;
}
uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height)
{
uiArea *a;
uiWindowsNewControl(uiArea, a);
a->ah = ah;
a->scrolling = TRUE;
a->scrollWidth = width;
a->scrollHeight = height;
uiprivClickCounterReset(&(a->cc));
// a->hwnd is assigned in areaWndProc()
uiWindowsEnsureCreateControlHWND(0,
areaClass, L"",
WS_HSCROLL | WS_VSCROLL,
hInstance, a,
FALSE);
// set initial scrolling parameters
areaUpdateScroll(a);
return a;
}