Discussion:
Problems with z-order and layered windows, please help!
(too old to reply)
a***@gmail.com
2005-08-08 16:10:37 UTC
Permalink
Hi group!

I have a very strange problem; I try to set a transparent child window
to always be ontop of its parent. I already have a parent window, then
I create a layered child window which I want to put one step on top of
the parent window. This does not work all the time, sometimes
everything is OK and the layered window is always visible over the
parent window. I have a second thread in the layered window which
checks every second if the layered child window is the previous window
in the z-order with regards to the parent window. Sometimes it is not
and sometimes it is...

Any help with this would be grealy appreciated.

The code below is how I create the layerd child window:
wnd is the parent window.

hudWnd = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
"OverlayCls", "", WS_POPUP, 0,0,800,500, wnd, NULL,
(HINSTANCE)dllHandle, NULL);

//set the window attributes
SetWindowLong(hudWnd,
GWL_EXSTYLE, GetWindowLong(hudWnd, GWL_EXSTYLE) | WS_EX_LAYERED);

SetWindowLong(hudWnd,
GWL_STYLE, GetWindowLong(hudWnd, GWL_STYLE) | WS_POPUP |
WS_VISIBLE );


The code below is how I try to set the z-order:
wnd is the parent window.

SetWindowPos(hudWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );

SetWindowPos(hudWnd, GetParent(hudWnd), 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );


The code below is executed in a separate thread which should move the
layerd window if the parent is moved.

//get parent windows coords.
RECT tableRect;
GetWindowRect(wnd, &tableRect);

//check which window is the previous to the parent
zWnd = GetNextWindow(wnd, GW_HWNDPREV);

//if all is well the layered child window should be the previous to the
parent window
//if so only update the layered windows x and y pos.
if(zWnd == hudWnd){

::SetWindowPos(hudWnd, // handle of window
zWnd , // placement-order handle
tableRect.left+3, // horizontal position
tableRect.top+29, // vertical position
0, // width
0, // height SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE );


}
//if the z-order is incorrect try to set it again
//this is what happens sometimes the z.order is not correct
//sometimes the code below will fix it, sometime the frist try
sometimes the 10th or 20th and some time never....!
else{

SetWindowPos(hudWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
SetWindowPos(hudWnd, GetParent(hudWnd), 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
}

If someone know what I am doing wrong or konw a better way of doing
this please let me know.

Best Regards
AET
Gary Chanson
2005-08-08 17:38:01 UTC
Permalink
Post by a***@gmail.com
Hi group!
I have a very strange problem; I try to set a transparent child window
to always be ontop of its parent. I already have a parent window, then
I create a layered child window which I want to put one step on top of
the parent window. This does not work all the time, sometimes
everything is OK and the layered window is always visible over the
parent window. I have a second thread in the layered window which
checks every second if the layered child window is the previous window
in the z-order with regards to the parent window. Sometimes it is not
and sometimes it is...
Any help with this would be grealy appreciated.
wnd is the parent window.
hudWnd = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
"OverlayCls", "", WS_POPUP, 0,0,800,500, wnd, NULL,
(HINSTANCE)dllHandle, NULL);
//set the window attributes
SetWindowLong(hudWnd,
GWL_EXSTYLE, GetWindowLong(hudWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetWindowLong(hudWnd,
GWL_STYLE, GetWindowLong(hudWnd, GWL_STYLE) | WS_POPUP |
WS_VISIBLE );
wnd is the parent window.
SetWindowPos(hudWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
SetWindowPos(hudWnd, GetParent(hudWnd), 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
The code below is executed in a separate thread which should move the
layerd window if the parent is moved.
//get parent windows coords.
RECT tableRect;
GetWindowRect(wnd, &tableRect);
//check which window is the previous to the parent
zWnd = GetNextWindow(wnd, GW_HWNDPREV);
//if all is well the layered child window should be the previous to the
parent window
//if so only update the layered windows x and y pos.
if(zWnd == hudWnd){
::SetWindowPos(hudWnd, // handle of window
zWnd , // placement-order handle
tableRect.left+3, // horizontal position
tableRect.top+29, // vertical position
0, // width
0, // height SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE );
}
//if the z-order is incorrect try to set it again
//this is what happens sometimes the z.order is not correct
//sometimes the code below will fix it, sometime the frist try
sometimes the 10th or 20th and some time never....!
else{
SetWindowPos(hudWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
SetWindowPos(hudWnd, GetParent(hudWnd), 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
}
If someone know what I am doing wrong or konw a better way of doing
this please let me know.
First, calling SetWindowPos with SWP_TOPMOST and then again with another
window cancels its effect. From the SetWindowPos documentation:

If a topmost window is repositioned to the bottom (HWND_BOTTOM) of the Z order
or after any non-topmost window, it is no longer topmost. When a topmost
window is made non-topmost, its owners and its owned windows are also made
non-topmost windows.

Second, your second call to SetWindowPos is trying to put the child window
behind the parent window which shouldn't work. The child window will always
be above its parent.

If you're trying to position the child to be below all other child
windows, use your second SetWindowPos command with the handles reversed. If
you need to watch for changes in the z-order of your child windows, you should
be able to do it without a separate thread by hanging the processing on the
appropriate message (probably WM_MOVE).
--
-GJC [MS Windows SDK MVP]
-Software Consultant (Embedded systems and Real Time Controls)
- http://www.mvps.org/ArcaneIncantations/consulting.htm
-***@mvps.org
a***@gmail.com
2005-08-08 18:45:35 UTC
Permalink
Post by Gary Chanson
Post by a***@gmail.com
Hi group!
I have a very strange problem; I try to set a transparent child window
to always be ontop of its parent. I already have a parent window, then
I create a layered child window which I want to put one step on top of
the parent window. This does not work all the time, sometimes
everything is OK and the layered window is always visible over the
parent window. I have a second thread in the layered window which
checks every second if the layered child window is the previous window
in the z-order with regards to the parent window. Sometimes it is not
and sometimes it is...
Any help with this would be grealy appreciated.
wnd is the parent window.
hudWnd = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
"OverlayCls", "", WS_POPUP, 0,0,800,500, wnd, NULL,
(HINSTANCE)dllHandle, NULL);
//set the window attributes
SetWindowLong(hudWnd,
GWL_EXSTYLE, GetWindowLong(hudWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetWindowLong(hudWnd,
GWL_STYLE, GetWindowLong(hudWnd, GWL_STYLE) | WS_POPUP |
WS_VISIBLE );
wnd is the parent window.
SetWindowPos(hudWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
SetWindowPos(hudWnd, GetParent(hudWnd), 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
The code below is executed in a separate thread which should move the
layerd window if the parent is moved.
//get parent windows coords.
RECT tableRect;
GetWindowRect(wnd, &tableRect);
//check which window is the previous to the parent
zWnd = GetNextWindow(wnd, GW_HWNDPREV);
//if all is well the layered child window should be the previous to the
parent window
//if so only update the layered windows x and y pos.
if(zWnd == hudWnd){
::SetWindowPos(hudWnd, // handle of window
zWnd , // placement-order handle
tableRect.left+3, // horizontal position
tableRect.top+29, // vertical position
0, // width
0, // height SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE );
}
//if the z-order is incorrect try to set it again
//this is what happens sometimes the z.order is not correct
//sometimes the code below will fix it, sometime the frist try
sometimes the 10th or 20th and some time never....!
else{
SetWindowPos(hudWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
SetWindowPos(hudWnd, GetParent(hudWnd), 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
}
If someone know what I am doing wrong or konw a better way of doing
this please let me know.
Thank you for the answer.
Post by Gary Chanson
First, calling SetWindowPos with SWP_TOPMOST and then again with another
If a topmost window is repositioned to the bottom (HWND_BOTTOM) of the Z order
or after any non-topmost window, it is no longer topmost. When a topmost
window is made non-topmost, its owners and its owned windows are also made
non-topmost windows.
Yes, I know this and it is OK for me.
Post by Gary Chanson
Second, your second call to SetWindowPos is trying to put the child window
behind the parent window which shouldn't work. The child window will always
be above its parent.
This is what I tried first (as it say in the API: hWndInsertAfter
Identifies the window to precede the positioned window in the Z order),
however, it did not work. I then saw the two SetWindowPos lines in a
MFC example which did exactly what I tried to do, so I tried it and it
works 95% (which of course is not good enough)

I also tried to do:

HWND pWnd = GetNextWindow(wnd, GW_HWNDPREV); // to get the window over
the parent window
//and then use it in SetWindowPos
SetWindowPos(hudWnd, pWnd, 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );

this worked until I moved the window.

Maybe it is because the parent window belongs to a 3:rd party
application?
Post by Gary Chanson
If you're trying to position the child to be below all other child
windows, use your second SetWindowPos command with the handles reversed. If
you need to watch for changes in the z-order of your child windows, you should
be able to do it without a separate thread by hanging the processing on the
appropriate message (probably WM_MOVE).
Thank you for the tip, can my threaded solution cause any problems? In
other words is it better/safer to handle it in the WndProc?

Thanks again.
Post by Gary Chanson
--
-GJC [MS Windows SDK MVP]
-Software Consultant (Embedded systems and Real Time Controls)
- http://www.mvps.org/ArcaneIncantations/consulting.htm
Gary Chanson
2005-08-09 01:43:41 UTC
Permalink
Post by a***@gmail.com
Post by Gary Chanson
Second, your second call to SetWindowPos is trying to put the child window
behind the parent window which shouldn't work. The child window will always
be above its parent.
This is what I tried first (as it say in the API: hWndInsertAfter
Identifies the window to precede the positioned window in the Z order),
however, it did not work. I then saw the two SetWindowPos lines in a
MFC example which did exactly what I tried to do, so I tried it and it
works 95% (which of course is not good enough)
HWND pWnd = GetNextWindow(wnd, GW_HWNDPREV); // to get the window over
the parent window
//and then use it in SetWindowPos
SetWindowPos(hudWnd, pWnd, 0, 0, 0, 0,
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW );
this worked until I moved the window.
Maybe it is because the parent window belongs to a 3:rd party
application?
Oh! That makes a big difference. Have you made your window a child of
the other program's main window? Doing this may cause problems because some
messages will get sent to the other program and may cause problems.

If you can't make your window a child of the program's main window,
placing your window behind the first child window should be the way to go. If
moving it changes the z-order, set it back with SetWindowPos in WM_MOVE (after
any other processing is complete).
--
-GJC [MS Windows SDK MVP]
-Software Consultant (Embedded systems and Real Time Controls)
- http://www.mvps.org/ArcaneIncantations/consulting.htm
-***@mvps.org
Continue reading on narkive:
Loading...