Jump to content
  • Advertisement
Sign in to follow this  
irreversible

Right/bottom-aligning child windows within a parent in Windows

This topic is 2817 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The problem seems trivial with a trivial solution: respond to parent window's WM_SIZE message and set the position of all child windows that are to be aligned relative to the right/bottom of the parent window (using SetWindowPos()). Unfortunately, this only yields nice results when the user is resizing the parent using the right or bottom edge - when resizing using the left/top edges, the right/bottom aligned children make a very unnatural jolt before settling to their proper position. This jump seems to be equal to the amount dragged (eg he faster you resize the window, the more jitter you see - at worst several hundred pixels whichm, needless to say, looks very unnatural).

I've been scouring the web to find a solution to this and it seems I either can't come up with suitable search terms or this is not a well-documented case. Anyone here have some experience with this?

Share this post


Link to post
Share on other sites
Advertisement
Wow, I never noticed that (or rather never really paid attention to fast resizing), and I've been programming Windows for a long time (it's kind of rare to size a window from the upper left anyways). It even does that with status bars and even in this Firefox window that I am on. It's not a strong jolt though. But you're right. It might not do this if the control was windowless instead.

EDIT: One thing I just tested right now with status bars is that you can hide and show the window in WM_SIZE and it stops that.

[Edited by - yadango on September 2, 2010 2:11:15 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by yadango
Wow, I never noticed that (or rather never really paid attention to fast resizing), and I've been programming Windows for a long time (it's kind of rare to size a window from the upper left anyways). It even does that with status bars and even in this Firefox window that I am on. It's not a strong jolt though. But you're right. It might not do this if the control was windowless instead.

EDIT: One thing I just tested right now with status bars is that you can hide and show the window in WM_SIZE and it stops that.


Hm - how do you mean? You mean hide and immediately show the parent window? It just causes the window to become invisible for a brief moment for me, which is expected and even more epileptic than the regular jumping. Or did you have something different in mind?

I've been trying this out in various programs and just about all of them seem to have this jumpy effect (even VS2008). I'm not sure why this is not something that would be attended to by MS - it doesn't seem like a difficult or overly involved thing to fix... It's really ugly and a lot of applications make great use of attaching somekind of a toolbar or status bar to the right side of the main window (Photoshop and just about any 3D modeling software come to mind first).

Share this post


Link to post
Share on other sites
Something like this (it even works when I drag the size box). It is code from one of my win32 application templates. Though you might want to try iMalc's DeferWindowPos thingy first. I know flashing is one of things everyone likes to get rid of, but even Visual Studio's status bar exhibits this behavior as well, so don't feel bad about it :-). I still think windowless is the way to go if you don't want this behavior (notice this source box doesn't do it, since I think browser controls are windowless because there is a limit to the number of window handles you can have open).


BOOL LayoutMainWindow(void)
{
// validate presence of client window
HWND client = GetMainClient();
if(!client) return FALSE;

// hide status bar
ShowWindow(GetMainStatusBar(), SW_HIDE);

// resize tool bar
TB_AutoSize(GetMainToolBar());
SIZE toolsize;
GetClientDimensions(GetMainToolBar(), &toolsize);

// resize status bar
DivideMainStatusBar();
SendMessage(GetMainStatusBar(), WM_SIZE, 0, 0);
SIZE statsize;
GetClientDimensions(GetMainStatusBar(), &statsize);

// resize client
LONG x0 = 0;
LONG y0 = toolsize.cy;
LONG dx = client_dx;
LONG dy = client_dy - toolsize.cy - statsize.cy;
MoveWindow(client, x0, y0, dx, dy, TRUE);

// reshow status bar
ShowWindow(GetMainStatusBar(), SW_SHOW);

return TRUE;
}



Share this post


Link to post
Share on other sites
I'll try the DefferedWindowPos method tomorrow, although I have doubts about it. The method you showed doesn't seem to be working for me for a gadget-bar like case. I haven't tried this, but one thing I thought of giving a shot at was capturing the DC of the sidebar and blitting it directly to the parent. I'm faily sure this won't work either as observing the way Windows is drawing the child windows seems to indicate that it's not a positioning problem, but a syncing problem between resizing and painting, which cannot be overcome that easily. You get that from spewing out WM_SIZE and WM_PAINT messages arbitrarily (like Windows does) - and as far I can see the only way to overcome this would be to disable updates for something like 200 ms at a time for the parent, which would get rid of the jumping, but would introduce choppiness. Again, I'll try it out tomorrow.

Share this post


Link to post
Share on other sites
You may also want to try experimenting with using the SWP_DEFERERASE, SWP_NOREDRAW, or SWP_NOCOPYBITS flags of SetWindowPos or DeferWindowPos.
I'm sure that somewhere amoungst all of that, it can be done.

Share this post


Link to post
Share on other sites
Hmm - I'm not sure what's going on here, but it seems the following code fails to resize the windows:


HDWP wp;
if(wp = BeginDeferWindowPos(2))
{
wp = DeferWindowPos(wp, w0->GetHandle(), NULL, 0, 0, max(0, iWidth - 600), iHeight, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
wp = DeferWindowPos(wp, w1->GetHandle(), NULL, iWidth - 600, 0, 600, iHeight, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
if(!EndDeferWindowPos(wp))
{ lout << "ewp fail" << endl; }
}
else
lout << "bwp fail" << endl;





None of the functions fail, but the windows aren't adjusted either. Am I missing something?

Share this post


Link to post
Share on other sites
I was having this exact problem until... I gave up.

Even MS Paint, which seems to not even resize the client/child area, has a status bar that flickers when you use the right or bottom resizer. That's a bit unimpressive for standard-as-it-gets MS software. I'm pretty sure my app's status bar doesn't flicker at all when resizing from the right/bottom.

I gave up trying but I'm eager to see if you find a solution. It would be nice to have an app that resizes more cleanly than even MS's software.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!