When (and how) to lay out the children of a Win32 window in response to a resize? - winapi

Windows sends several messages when a window is resized:
WM_GETMINMAXINFO
WM_ENTERSIZEMOVE
WM_EXITSIZEMOVE
WM_NCCALCSIZE
WM_SIZING
WM_SIZE
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGED
and possibly more.
If I would like to re-position the children when my window is resized, where and how should I do so?
I'm looking for the "best" method -- i.e. the method with the fewest gotcha's and the least flicker.
My current method is to perform all the repositioning inside WM_NCCALCSIZE, using DeferWindowPos.
However, I've also tried handling it inside WM_WINDOWPOSCHANGED... but no matter where I handle it, it seems like there is always at least one "moment" when the window is painted in an in-between state, where the window's size has changed, but its contents have yet to be resized.
Another effect I would also like to avoid: moving a child after it has already moved. I don't want the user to see a control sliding down and then back up because of my change -- it should have as few transient effects as possible.
Am I doing this correctly? Is there a better place I can lay out the window's children?

You should re-position the window in the WM_SIZE message, because that is the last one that the window recieves before complete it's task...To re-position the window you can use MoveWindow

Related

winapi - DeferWindowPos and InvalidateRect

I have a main window which allows to display a child modal dialog. That dialog window is created based on the resource file using DialogBox function. It contains a few controls and a horizontal splitter which are repositioned/resized when handling WM_SIZE and WM_MOUSEMOVE messages. I use BeginDeferWindowPos, DeferWindowPos and EndDeferWindowPos functions. It looks like that everything is repainted correctly. Should I also call InvalidateRect after EndDeferWindowPos ? Is there any scenario where it may be necessary ? I don't handle WM_PAINT message.
The documentation for the DeferWindowPos function would strongly suggest that, so long as you don't have the SWP_NOREDRAW bit set in the uFlags argument, you do not need to call InvalidateRect after you have called EndDeferWindowPos:
SWP_NOREDRAW 0x0008 Does not redraw changes. If this flag is set,
no repainting of any kind occurs. This applies to the client area, the
nonclient area (including the title bar and scroll bars), and any part
of the parent window uncovered as a result of the window being moved.
When this flag is set, the application must explicitly invalidate or
redraw any parts of the window and parent window that need redrawing.

Location of a maximized window with custom chrome

I've created a window with a custom chrome by:
Handling WM_NCHITTEST and returning the appropriate values for the window caption and borders,
Swallowing WM_NCPAINT (and WM_NCUAHDRAWCAPTION, WM_NCUAHDRAWFRAME),
Handling WM_SETTEXT, WM_SETICON and WM_NCACTIVATE with DefWindowProc by temporarily removing WM_VISIBLE,
Handling WM_WINDOWPOSCHANGED to apply a window region for rounded corners.
Moving/Resizing is handled fine by Windows. I added WS_THICKFRAME to the window styles to enable Aero Snap functionality. But now when the window is maximized it is positioned at (-5,-5) and my custom titlebar is cut off (this doesn't happen without WS_THICKFRAME).
What is the proper way to fix that? What influences that position? It seems to be unrelated to values returned for WM_NCHITTEST.
Late answer, but it seems like noone else has answered.
You can check when the window is maximized and account for the margin when the window is maximized. You may want to handle WM_NCCALCSIZE rather than WM_NCPAINT to make the entire window appear as client area, rather than painting the non-client area.
This describes one approach to implementing custom chrome (I was the author):
http://blogs.msdn.com/b/wpfsdk/archive/2008/09/08/custom-window-chrome-in-wpf.aspx
Hope that helps,

How to draw OpenGL content while resizing win32 window

While resizing win32 window, with OpenGL context, it just shows black on the newly exposed area.
I do get WM_PAINT message while resizing, and I do try to render new content, but it seems as if SwapBuffers does nothing, while resizing.
How should window resizes be handled correctly, so that there is no "broken" content while resizing?
This usually happens if you have a background brush configured for your window's class (see the WNDCLASS or WNDCLASSEX structure). If there's a brush, the system will clear the window right after each redraw step, then send the WM_PAINT. In case of V-Synced SwapBuffers your picture may have been overdrawn by the next resizing step before the buffer swap happened, or just right after it, but before that part of the screen was sent to the display device.
Either way, the solution is to set the background brush of the window to NULL. Also tinkering with the WM_ERASEBKGND message handling may give results.
EDIT due to comment
If the content of the last frame stays visible, you probably just don't react to resizing with a redraw. The easiest solution to this is calling the drawing function from the WM_SIZING (or the WM_SIZE, just try both) message handler.

"coupled" NSWindows

I am trying to have "coupled" NSWindows.
I mean 2 NSWindows of the same size, positioned side by side. If I move one, the other one has to move as well to keep both side by side.
I tried to do this with child window but when the child window is moved, the "mother" stays in place.
How I can get this behavior?
Designate an object as the windows' delegate and respond to the ‑windowDidMove:, ‑windowWillResize:toSize: and/or ‑windowWillMove: delegate methods, or register to receive the corresponding notifications. You can then resize the other window as you see fit.
This sounds like an odd UI, by the way. Can you not just use a split view?

Win32 doesn't send mouse events to my window, only its parent. why?

I have a window that's a CHILD window of another window. For reasons beyond me, NC_HITTEST never gets called on it, no mouse events are called for it (but rather reach its parent window).
Why is that? I want that child window to process his own mouse clicks.
NC_HITTEST is not likely a message you want to be catching for mouse events. You want to be catching WM_MOUSEMOVE, WM_LBUTTONDOWN, etc...

Resources