Switch to using DeferWindowPos() in Windows resizes. It doesn't optimize anything just yet (because it's still recursively invoked), but it can be optimized later (by not responding to container resizes and only using container updates); and more important, it puts (most of) the resizing invocations in one place.

This commit is contained in:
Pietro Gagliardi 2015-05-05 15:10:37 -04:00
parent f35d68907b
commit f6fdf932e1
3 changed files with 24 additions and 5 deletions

View File

@ -35,17 +35,23 @@ struct uiWindowsMakeControlParams {
void uiWindowsMakeControl(uiControl *c, uiWindowsMakeControlParams *p);
// This contains the Windows-specific parts of the uiSizing structure.
// dwp contains the HDWP to issue a resize request to.
// You only need to worry about it if you are implementing your own Resize().
// baseX and baseY are the dialog base units.
// internalLeading is the standard control font's internal leading; labels in uiForms use this for correct Y positioning.
struct uiSizingSys {
HDWP dwp;
int baseX;
int baseY;
LONG internalLeading;
};
// Use these in your preferredSize() implementation with baseX and baseY.
// Use these in your PreferredSize() implementation with baseX and baseY.
#define uiDlgUnitsToX(dlg, baseX) MulDiv((dlg), baseX, 4)
#define uiDlgUnitsToY(dlg, baseY) MulDiv((dlg), baseY, 8)
// Use this in your Resize() implementation.
void uiWindowsResizeHWND(HWND hwnd, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d);
// and use this if you need the text of the window width
extern intmax_t uiWindowsWindowTextWidth(HWND hwnd);

View File

@ -127,7 +127,15 @@ static HRESULT resize(uiContainer *cc, RECT *r)
d.xPadding = uiDlgUnitsToX(winXPadding, sys.baseX);
d.yPadding = uiDlgUnitsToY(winYPadding, sys.baseY);
d.sys = &sys;
// 32 is an arbitrary number to start with, just to be safe
d.sys->dwp = BeginDeferWindowPos(32);
if (d.sys->dwp == NULL)
logLastError("error beginning resize in resize()");
uiContainerResizeChildren(cc, r->left, r->top, r->right - r->left, r->bottom - r->top, &d);
if (EndDeferWindowPos(d.sys->dwp) == 0)
logLastError("error ending resize in resize()");
return S_OK;
}
@ -301,8 +309,7 @@ static void containerResize(uiControl *cc, intmax_t x, intmax_t y, intmax_t widt
{
struct container *c = (struct container *) (cc->Internal);
if (MoveWindow(c->hwnd, x, y, width, height, TRUE) == 0)
logLastError("error resizing uiContainer in containerResize()");
uiWindowsResizeHWND(c->hwnd, x, y, width, height, d);
}
static int containerVisible(uiControl *cc)

View File

@ -56,8 +56,7 @@ static void singleResize(uiControl *c, intmax_t x, intmax_t y, intmax_t width, i
{
struct singleHWND *s = (struct singleHWND *) (c->Internal);
if (MoveWindow(s->hwnd, x, y, width, height, TRUE) == 0)
logLastError("error moving control in singleResize()");
uiWindowsResizeHWND(s->hwnd, x, y, width, height, d);
}
static int singleVisible(uiControl *c)
@ -207,3 +206,10 @@ void uiWindowsControlSetText(uiControl *c, const char *text)
logLastError("error setting control text in uiWindowsControlSetText()");
uiFree(wtext);
}
void uiWindowsResizeHWND(HWND hwnd, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d)
{
d->sys->dwp = DeferWindowPos(d->sys->dwp, hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
if (d->sys->dwp == NULL)
logLastError("error queuing window for resize in uiWindowsResizeHWND()");
}