GPaterson
asked on
Setting the window Z Order
Okay, an interesting one here. I need to set a toolbar application to be a topmost window. HOWEVER! I need to start menu/taskbar to stay absolutely top most. Is there any way to set a window to be always second topmost so that it remains above all other windows apart from the taskbar/startmenu.
I've tried playing with SetWindowPos and HWND_TOPMOST e.t.c. including getting a handle for the taskbar using FindWindow(_T("Shell_TrayW nd"), NULL); and then setting the taskbar to be topmost immediately after setting my toolbar to topmost.
I've also tried playing with WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED but to no avail.
If anyone knows how to do this I'd appreciate your help.
Thanks
I've tried playing with SetWindowPos and HWND_TOPMOST e.t.c. including getting a handle for the taskbar using FindWindow(_T("Shell_TrayW
I've also tried playing with WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED but to no avail.
If anyone knows how to do this I'd appreciate your help.
Thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
No comment has been added lately, so it's time to clean up this TA.
I will leave the following recommendation for this question in the Cleanup topic area:
Accept: Axter {http:#10190259}
Please leave any comments here within the next four days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
Tinchos
EE Cleanup Volunteer
I will leave the following recommendation for this question in the Cleanup topic area:
Accept: Axter {http:#10190259}
Please leave any comments here within the next four days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
Tinchos
EE Cleanup Volunteer
ASKER
Neither of the solutions provided worked.
If the solution didn't work, you should have provided some feedback so that we could further assist you.
How did the solution not work?
And can you provide the code you use to implement the solution?
How did the solution not work?
And can you provide the code you use to implement the solution?
ASKER
Hi,
I guess it's a bit late for any of you to answer now anyway, the code is as follows:
BOOL ScreenResX::SetOptions(DWO RD dwOptions)
{
HWND hWndRB = GetDlgItem(m_hWnd, ID_REBAR);
RECT rcWindow, rcDesktop;
UINT nWidthBar, nHeightBar;
GetWindowRect(m_hWnd,&rcWi ndow);
nWidthBar = rcWindow.right - rcWindow.left;
nHeightBar = rcWindow.bottom - rcWindow.top;
SystemParametersInfo(SPI_G ETWORKAREA ,0,&rcDesk top,0);
// Readjust our desktop area if Always on Top
if(m_dwOptions & SRX_SET_ALWAYSONTOP)
{
switch(ISDOCKED(m_dwOption s))
{
case SRX_DOCK_TOP|SRX_DOCK_HORZ :
{
rcDesktop.top -= nHeightBar;
}
break;
case SRX_DOCK_LEFT|SRX_DOCK_VER T:
{
rcDesktop.left -= nWidthBar;
}
break;
case SRX_DOCK_RIGHT|SRX_DOCK_VE RT:
{
rcDesktop.right += nWidthBar;
}
break;
case SRX_DOCK_BOTTOM|SRX_DOCK_H ORZ:
{
rcDesktop.bottom += nHeightBar;
}
break;
default:
break;
}
}
// If our new setting does not have Always on Top
// Or if we have undocked a bar which did have always on top.
// Reset out desktop area
if(~dwOptions & SRX_SET_ALWAYSONTOP || ((!ISDOCKED(dwOptions)) && m_dwOptions & SRX_SET_ALWAYSONTOP))
{
SystemParametersInfo(SPI_S ETWORKAREA ,0, &rcDesktop,SPIF_SENDCHANGE );
EnumWindows(EnumWindowsPro c,(LPARAM) &rcDesktop );
}
// If auto hide is enabled, disable and place bar back on screen.
if(m_dwOptions & SRX_SET_INACTIVEHIDE)
{
// Disable mouse tracking if it is on
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE|TME_CANCEL;
tme.hwndTrack = m_hWnd;
tme.dwHoverTime = 0;
CustomTrackMouseEvent(&tme );
// Unhide the bar if hidden
switch(ISHIDDEN(m_dwOption s))
{
case SRX_SET_HIDDEN_TOP:
{
SetWindowPos(m_hWnd,0,rcWi ndow.left, rcDesktop. top,0,0,SW P_NOSIZE|S WP_NOZORDE R);
m_dwOptions &= ~SRX_SET_HIDDEN_TOP;
}
break;
case SRX_SET_HIDDEN_LEFT:
{
SetWindowPos(m_hWnd,0,rcDe sktop.left ,rcWindow. top,0,0,SW P_NOSIZE|S WP_NOZORDE R);
m_dwOptions &= ~SRX_SET_HIDDEN_LEFT;
}
break;
case SRX_SET_HIDDEN_RIGHT:
{
SetWindowPos(m_hWnd,0,rcDe sktop.righ t-nWidthBa r,rcWindow .top,0,0,S WP_NOSIZE| SWP_NOZORD ER);
m_dwOptions &= ~SRX_SET_HIDDEN_RIGHT;
}
break;
case SRX_SET_HIDDEN_BOTTOM:
{
SetWindowPos(m_hWnd,0,rcWi ndow.left, rcDesktop. bottom-nHe ightBar,0, 0,SWP_NOSI ZE|SWP_NOZ ORDER);
m_dwOptions &= ~SRX_SET_HIDDEN_BOTTOM;
}
break;
default:
break;
}
}
// Undocking
if((~dwOptions & SRX_SET_DOCKING) && (m_dwOptions & SRX_SET_DOCKING))
{
// Undock m_dwOptions also or else everything else will run
// Undock here
SetWindowPos(m_hWnd,0,100, 100,0,0,SW P_NOSIZE|S WP_NOZORDE R);
// Undock
UNDOCK(m_dwOptions);
}
// Apply new settings
// Show title is setting enabled and not docked, otherwise hide
if(dwOptions & SRX_SET_NOTITLE || ISDOCKED(m_dwOptions))
{
ShowTitle(m_hWnd,FALSE);
FitWindowToBar(m_hWnd);
}
else
{
ShowTitle(m_hWnd,TRUE);
FitWindowToBar(m_hWnd);
}
// If bar is docked and new vertical state is set, change this to a pending state
// SRX_STATE_VERTICAL
if((dwOptions&SRX_SET_VERT ICAL) && (m_dwOptions&SRX_DOCK_HORZ ))
{
dwOptions &= ~SRX_SET_VERTICAL;
dwOptions |= SRX_STATE_VERTICAL;
}
if((~m_dwOptions&SRX_SET_V ERTICAL) && (m_dwOptions&SRX_DOCK_VERT ))
{
dwOptions |= SRX_SET_VERTICAL;
dwOptions &= ~SRX_STATE_VERTICAL;
}
// Set our new options to member variable
m_dwOptions = (m_dwOptions & 0x7F000000L)|dwOptions;
// Create a rebar
BarIsVertical(hWndRB,(m_dw Options&SR X_SET_VERT ICAL)?TRUE :FALSE, TRUE);
// Fit our window to our bar
FitWindowToBar(m_hWnd);
RECT rcNewWnd;
GetWindowRect(m_hWnd,&rcNe wWnd);
// Reposition the bar
if(ISDOCKED(m_dwOptions))
{
switch(ISDOCKED(m_dwOption s))
{
case SRX_DOCK_TOP|SRX_DOCK_HORZ :
{
SetWindowPos(m_hWnd,0,rcDe sktop.left ,rcDesktop .top,0,0,S WP_NOSIZE| SWP_NOZORD ER);
}
break;
case SRX_DOCK_LEFT|SRX_DOCK_VER T:
{
SetWindowPos(m_hWnd,0,rcDe sktop.left ,rcDesktop .top,0,0,S WP_NOSIZE| SWP_NOZORD ER);
}
break;
case SRX_DOCK_RIGHT|SRX_DOCK_VE RT:
{
SetWindowPos(m_hWnd,0,rcDe sktop.righ t - (rcNewWnd.right-rcNewWnd.l eft),rcDes ktop.top,0 ,0,SWP_NOS IZE|SWP_NO ZORDER);
}
break;
case SRX_DOCK_BOTTOM|SRX_DOCK_H ORZ:
{
SetWindowPos(m_hWnd,0,rcDe sktop.left ,rcDesktop .bottom - (rcNewWnd.bottom-rcNewWnd. top),0,0,S WP_NOSIZE| SWP_NOZORD ER);
}
break;
default:
break;
}
}
// Reset our desktop area if always on top selected
if(m_dwOptions & SRX_SET_ALWAYSONTOP)
{
switch(ISDOCKED(m_dwOption s))
{
case SRX_DOCK_TOP|SRX_DOCK_HORZ :
{
rcDesktop.top += (rcNewWnd.bottom-rcNewWnd. top);
SystemParametersInfo(SPI_S ETWORKAREA ,0, &rcDesktop,SPIF_SENDCHANGE );
EnumWindows(EnumWindowsPro c,(LPARAM) &rcDesktop );
}
break;
case SRX_DOCK_LEFT|SRX_DOCK_VER T:
{
rcDesktop.left += (rcNewWnd.right-rcNewWnd.l eft);
SystemParametersInfo(SPI_S ETWORKAREA ,0, &rcDesktop,SPIF_SENDCHANGE );
EnumWindows(EnumWindowsPro c,(LPARAM) &rcDesktop );
}
break;
case SRX_DOCK_RIGHT|SRX_DOCK_VE RT:
{
rcDesktop.right -= (rcNewWnd.right-rcNewWnd.l eft);
SystemParametersInfo(SPI_S ETWORKAREA ,0, &rcDesktop,SPIF_SENDCHANGE );
EnumWindows(EnumWindowsPro c,(LPARAM) &rcDesktop );
}
break;
case SRX_DOCK_BOTTOM|SRX_DOCK_H ORZ:
{
rcDesktop.bottom -= (rcNewWnd.bottom-rcNewWnd. top);
SystemParametersInfo(SPI_S ETWORKAREA ,0, &rcDesktop,SPIF_SENDCHANGE );
EnumWindows(EnumWindowsPro c,(LPARAM) &rcDesktop );
}
break;
default:
break;
}
}
// Settings go in here for placing it second topmost.....
SetRegSettings();
return TRUE;
}
It is part of a toolbar I have been making. Basically, if the toolbar is set NOT to always be on top but to enable docking and hiding between uses (it slides off the edge of the screen) I need it to be the Second Topmost window. It MUST be one position in the z-order below the taskbar so that when it slides down it goes behind the start menu. However it MUST also remain a topmost window because otherwise if you maximize another window you lose the edge of the toolbar and have to bring it to the top before you can move the mouse over it and bring it back (slides back out) onto the screen.
The problem is using any of the tactics described above the window either goes above the taskbar covering it which is no use or it does not stay top most, i.e. another window can maximise over it.
For the record for anyone reading this question at a later date looking for an answer forget the accepted answer this question/answer is null and void unless someone answers after this.
I guess it's a bit late for any of you to answer now anyway, the code is as follows:
BOOL ScreenResX::SetOptions(DWO
{
HWND hWndRB = GetDlgItem(m_hWnd, ID_REBAR);
RECT rcWindow, rcDesktop;
UINT nWidthBar, nHeightBar;
GetWindowRect(m_hWnd,&rcWi
nWidthBar = rcWindow.right - rcWindow.left;
nHeightBar = rcWindow.bottom - rcWindow.top;
SystemParametersInfo(SPI_G
// Readjust our desktop area if Always on Top
if(m_dwOptions & SRX_SET_ALWAYSONTOP)
{
switch(ISDOCKED(m_dwOption
{
case SRX_DOCK_TOP|SRX_DOCK_HORZ
{
rcDesktop.top -= nHeightBar;
}
break;
case SRX_DOCK_LEFT|SRX_DOCK_VER
{
rcDesktop.left -= nWidthBar;
}
break;
case SRX_DOCK_RIGHT|SRX_DOCK_VE
{
rcDesktop.right += nWidthBar;
}
break;
case SRX_DOCK_BOTTOM|SRX_DOCK_H
{
rcDesktop.bottom += nHeightBar;
}
break;
default:
break;
}
}
// If our new setting does not have Always on Top
// Or if we have undocked a bar which did have always on top.
// Reset out desktop area
if(~dwOptions & SRX_SET_ALWAYSONTOP || ((!ISDOCKED(dwOptions)) && m_dwOptions & SRX_SET_ALWAYSONTOP))
{
SystemParametersInfo(SPI_S
EnumWindows(EnumWindowsPro
}
// If auto hide is enabled, disable and place bar back on screen.
if(m_dwOptions & SRX_SET_INACTIVEHIDE)
{
// Disable mouse tracking if it is on
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE|TME_CANCEL;
tme.hwndTrack = m_hWnd;
tme.dwHoverTime = 0;
CustomTrackMouseEvent(&tme
// Unhide the bar if hidden
switch(ISHIDDEN(m_dwOption
{
case SRX_SET_HIDDEN_TOP:
{
SetWindowPos(m_hWnd,0,rcWi
m_dwOptions &= ~SRX_SET_HIDDEN_TOP;
}
break;
case SRX_SET_HIDDEN_LEFT:
{
SetWindowPos(m_hWnd,0,rcDe
m_dwOptions &= ~SRX_SET_HIDDEN_LEFT;
}
break;
case SRX_SET_HIDDEN_RIGHT:
{
SetWindowPos(m_hWnd,0,rcDe
m_dwOptions &= ~SRX_SET_HIDDEN_RIGHT;
}
break;
case SRX_SET_HIDDEN_BOTTOM:
{
SetWindowPos(m_hWnd,0,rcWi
m_dwOptions &= ~SRX_SET_HIDDEN_BOTTOM;
}
break;
default:
break;
}
}
// Undocking
if((~dwOptions & SRX_SET_DOCKING) && (m_dwOptions & SRX_SET_DOCKING))
{
// Undock m_dwOptions also or else everything else will run
// Undock here
SetWindowPos(m_hWnd,0,100,
// Undock
UNDOCK(m_dwOptions);
}
// Apply new settings
// Show title is setting enabled and not docked, otherwise hide
if(dwOptions & SRX_SET_NOTITLE || ISDOCKED(m_dwOptions))
{
ShowTitle(m_hWnd,FALSE);
FitWindowToBar(m_hWnd);
}
else
{
ShowTitle(m_hWnd,TRUE);
FitWindowToBar(m_hWnd);
}
// If bar is docked and new vertical state is set, change this to a pending state
// SRX_STATE_VERTICAL
if((dwOptions&SRX_SET_VERT
{
dwOptions &= ~SRX_SET_VERTICAL;
dwOptions |= SRX_STATE_VERTICAL;
}
if((~m_dwOptions&SRX_SET_V
{
dwOptions |= SRX_SET_VERTICAL;
dwOptions &= ~SRX_STATE_VERTICAL;
}
// Set our new options to member variable
m_dwOptions = (m_dwOptions & 0x7F000000L)|dwOptions;
// Create a rebar
BarIsVertical(hWndRB,(m_dw
// Fit our window to our bar
FitWindowToBar(m_hWnd);
RECT rcNewWnd;
GetWindowRect(m_hWnd,&rcNe
// Reposition the bar
if(ISDOCKED(m_dwOptions))
{
switch(ISDOCKED(m_dwOption
{
case SRX_DOCK_TOP|SRX_DOCK_HORZ
{
SetWindowPos(m_hWnd,0,rcDe
}
break;
case SRX_DOCK_LEFT|SRX_DOCK_VER
{
SetWindowPos(m_hWnd,0,rcDe
}
break;
case SRX_DOCK_RIGHT|SRX_DOCK_VE
{
SetWindowPos(m_hWnd,0,rcDe
}
break;
case SRX_DOCK_BOTTOM|SRX_DOCK_H
{
SetWindowPos(m_hWnd,0,rcDe
}
break;
default:
break;
}
}
// Reset our desktop area if always on top selected
if(m_dwOptions & SRX_SET_ALWAYSONTOP)
{
switch(ISDOCKED(m_dwOption
{
case SRX_DOCK_TOP|SRX_DOCK_HORZ
{
rcDesktop.top += (rcNewWnd.bottom-rcNewWnd.
SystemParametersInfo(SPI_S
EnumWindows(EnumWindowsPro
}
break;
case SRX_DOCK_LEFT|SRX_DOCK_VER
{
rcDesktop.left += (rcNewWnd.right-rcNewWnd.l
SystemParametersInfo(SPI_S
EnumWindows(EnumWindowsPro
}
break;
case SRX_DOCK_RIGHT|SRX_DOCK_VE
{
rcDesktop.right -= (rcNewWnd.right-rcNewWnd.l
SystemParametersInfo(SPI_S
EnumWindows(EnumWindowsPro
}
break;
case SRX_DOCK_BOTTOM|SRX_DOCK_H
{
rcDesktop.bottom -= (rcNewWnd.bottom-rcNewWnd.
SystemParametersInfo(SPI_S
EnumWindows(EnumWindowsPro
}
break;
default:
break;
}
}
// Settings go in here for placing it second topmost.....
SetRegSettings();
return TRUE;
}
It is part of a toolbar I have been making. Basically, if the toolbar is set NOT to always be on top but to enable docking and hiding between uses (it slides off the edge of the screen) I need it to be the Second Topmost window. It MUST be one position in the z-order below the taskbar so that when it slides down it goes behind the start menu. However it MUST also remain a topmost window because otherwise if you maximize another window you lose the edge of the toolbar and have to bring it to the top before you can move the mouse over it and bring it back (slides back out) onto the screen.
The problem is using any of the tactics described above the window either goes above the taskbar covering it which is no use or it does not stay top most, i.e. another window can maximise over it.
For the record for anyone reading this question at a later date looking for an answer forget the accepted answer this question/answer is null and void unless someone answers after this.
::SetWindowPos( Second_hWnd, GetDesktopWindow() , 0,0,0,0,SWP_NOMOVE|SWP_NOS
::SetWindowPos( taskbar_hWnd , Second_hWnd, 0,0,0,0,SWP_NOMOVE|SWP_NOS
Or -------
::SetWindowPos( Second_hWnd, HWND_TOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOS
::SetWindowPos( taskbar_hWnd , Second_hWnd, 0,0,0,0,SWP_NOMOVE|SWP_NOS