It is not possible to set a
style (like
WS_EX_TOPMOST
)
on an MDI child window so it
stays on top of other MDI
child windows. Instead, we
have to mark a window to be
the top most, and then
manually bring that window
to the top when another
window is activated.
Microsoft has provided a
nice article called
How To Keep an MDI Window
Always on Top (Q108315).
But the solution(s) in the
article are not implemented
using the MFC framework.
Implement a global variable
to remember the MDI window
with the top-most status:
Collapse
Copy Code
HWND CChildFrame::m_TopWindow = NULL;
Handle the
WM_WINDOWPOSCHANGED mesage:
The
WM_WINDOWPOSCHANGED
message is sent to a window,
when it changes size,
position, or z-order. It is
only sent to the window
being activated (not to the
window losing focus).
Collapse
Copy Code
BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
ON_WM_WINDOWPOSCHANGED()
END_MESSAGE_MAP()
void CChildFrame::OnWindowPosChanged(WINDOWPOS* lpwndpos)
{
if (m_TopWindow!=NULL && m_TopWindow!=m_hWnd && ::IsWindow(m_TopWindow))
{
::SetWindowPos(m_TopWindow, HWND_TOP, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
CMDIChildWnd::OnWindowPosChanged(lpwndpos);
}
Reset the global variable
when the top-most window
closes:
When the top-most window is
closed, we must reset the
global variable so other
windows will not try to
bring it up front.
Collapse
Copy Code
BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
ON_WM_CLOSE()
END_MESSAGE_MAP()
void CChildFrame::OnClose()
{
if (m_hWnd==m_TopWindow)
m_TopWindow = NULL;
CMDIChildWnd::OnClose();
}
Finally, we need to mark a
window as being the
top-most:
In this sample application,
the newly opened window will
get the status of being the
top-most, and other existing
windows will bring it to the
front when they are
activated.
Collapse
Copy Code
BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CMDIChildWnd::PreCreateWindow(cs) )
return FALSE;
m_TopWindow = m_hWnd;
return TRUE;
}