And added the new uiWindow methods on Windows.

This commit is contained in:
Pietro Gagliardi 2016-06-15 21:55:42 -04:00
parent 48c13c738a
commit c3777da0f4
2 changed files with 82 additions and 0 deletions

View File

@ -20,6 +20,7 @@ This README is being written.<br>
* **15 June 2016** * **15 June 2016**
* Added `uiFormDelete()`; thanks to @emersion. * Added `uiFormDelete()`; thanks to @emersion.
* Added `uiWindowPosition()`, `uiWindowSetPosition()`, `uiWindowCenter()`, and `uiWindowOnPositionChanged()`, methods for manipulating uiWindow position.
* **14 June 2016** * **14 June 2016**
* uiDarwinControl now has a `ChildVisibilityChanged()` method and a corresponding `NotifyVisibilityChanged()` function that is called by the default show/hide handlers. This is used to make visibility changes work on OS X; uiBox, uiForm, and uiGrid all respect these now. * uiDarwinControl now has a `ChildVisibilityChanged()` method and a corresponding `NotifyVisibilityChanged()` function that is called by the default show/hide handlers. This is used to make visibility changes work on OS X; uiBox, uiForm, and uiGrid all respect these now.

View File

@ -14,6 +14,9 @@ struct uiWindow {
void *onClosingData; void *onClosingData;
int margined; int margined;
BOOL hasMenubar; BOOL hasMenubar;
void (*onPositionChanged)(uiWindow *, void *);
void *onPositionChangedData;
BOOL changingPosition;
}; };
// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing // from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
@ -87,6 +90,10 @@ static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARA
runMenuEvent(LOWORD(wParam), uiWindow(w)); runMenuEvent(LOWORD(wParam), uiWindow(w));
return 0; return 0;
case WM_WINDOWPOSCHANGED: case WM_WINDOWPOSCHANGED:
if ((wp->flags & SWP_NOMOVE) == 0)
if (!w->changingPosition)
(*(w->onPositionChanged))(w, w->onPositionChangedData);
// and continue anyway
if ((wp->flags & SWP_NOSIZE) != 0) if ((wp->flags & SWP_NOSIZE) != 0)
break; break;
windowRelayout(w); windowRelayout(w);
@ -138,6 +145,11 @@ static int defaultOnClosing(uiWindow *w, void *data)
return 0; return 0;
} }
static void defaultOnPositionChanged(uiWindow *w, void *data)
{
// do nothing
}
static std::map<uiWindow *, bool> windows; static std::map<uiWindow *, bool> windows;
static void uiWindowDestroy(uiControl *c) static void uiWindowDestroy(uiControl *c)
@ -277,6 +289,74 @@ void uiWindowSetTitle(uiWindow *w, const char *title)
// don't queue resize; the caption isn't part of what affects layout and sizing of the client area (it'll be ellipsized if too long) // don't queue resize; the caption isn't part of what affects layout and sizing of the client area (it'll be ellipsized if too long)
} }
void uiWindowPosition(uiWindow *w, int *x, int *y)
{
RECT r;
uiWindowsEnsureGetWindowRect(w->hwnd, &r);
*x = r.left;
*y = r.top;
}
void uiWindowSetPosition(uiWindow *w, int x, int y)
{
w->changingPosition = TRUE;
if (SetWindowPos(w->hwnd, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER) == 0)
logLastError(L"error moving window");
w->changingPosition = FALSE;
}
// this is used for both fullscreening and centering
// see also https://blogs.msdn.microsoft.com/oldnewthing/20100412-00/?p=14353 and https://blogs.msdn.microsoft.com/oldnewthing/20050505-04/?p=35703
static void windowMonitorRect(HWND hwnd, RECT *r)
{
HMONITOR monitor;
MONITORINFO mi;
monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
ZeroMemory(&mi, sizeof (MONITORINFO));
mi.cbSize = sizeof (MONITORINFO);
if (GetMonitorInfoW(monitor, &mi) == 0) {
logLastError(L"error getting window monitor rect");
// default to SM_CXSCREEN x SM_CYSCREEN to be safe
r->left = 0;
r->top = 0;
r->right = GetSystemMetrics(SM_CXSCREEN);
r->bottom = GetSystemMetrics(SM_CYSCREEN);
return;
}
*r = mi.rcMonitor;
}
// TODO use the work rect instead?
void uiWindowCenter(uiWindow *w)
{
RECT wr, mr;
int x, y;
LONG wwid, mwid;
LONG wht, mht;
uiWindowsEnsureGetWindowRect(w->hwnd, &wr);
windowMonitorRect(w->hwnd, &mr);
wwid = wr.right - wr.left;
mwid = mr.right - mr.left;
x = (mwid - wwid) / 2;
wht = wr.bottom - wr.top;
mht = mr.bottom - mr.top;
y = (mht - wht) / 2;
// y is now evenly divided, however https://msdn.microsoft.com/en-us/library/windows/desktop/dn742502(v=vs.85).aspx says that 45% should go above and 55% should go below
// so just move 5% of the way up
// TODO is this correct?
y -= y / 20;
uiWindowSetPosition(w, x, y);
}
void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
{
w->onPositionChanged = f;
w->onPositionChangedData = data;
}
void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data) void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
{ {
w->onClosing = f; w->onClosing = f;
@ -373,6 +453,7 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
setClientSize(w, width, height, hasMenubarBOOL, style, exstyle); setClientSize(w, width, height, hasMenubarBOOL, style, exstyle);
uiWindowOnClosing(w, defaultOnClosing, NULL); uiWindowOnClosing(w, defaultOnClosing, NULL);
uiWindowOnPositionChanged(w, defaultOnPositionChanged, NULL);
windows[w] = true; windows[w] = true;
return w; return w;