From f6fdf932e1916e4254978a73d7fbfa64af9197fc Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Tue, 5 May 2015 15:10:37 -0400 Subject: [PATCH] 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. --- ui_windows.h | 8 +++++++- windows/container.c | 11 +++++++++-- windows/newcontrol.c | 10 ++++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/ui_windows.h b/ui_windows.h index 7c24a4d1..41984242 100644 --- a/ui_windows.h +++ b/ui_windows.h @@ -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); diff --git a/windows/container.c b/windows/container.c index 69ccc360..5af8c0c1 100644 --- a/windows/container.c +++ b/windows/container.c @@ -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) diff --git a/windows/newcontrol.c b/windows/newcontrol.c index a19b8cc8..962695a3 100644 --- a/windows/newcontrol.c +++ b/windows/newcontrol.c @@ -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()"); +}