Modal MFC frame window






4.87/5 (20 votes)
Utility class that helps to implement a modal dialog's behavior for any CFrameWnd-derived window class in an easy way.
Introduction
Sometimes, it may be useful to have a modal window with Doc/View architecture, toolbars/statusbar support (i.e. base features implemented in MFC frame windows). How to get these without implementing all of these features in a CDialog
-derived class? The CModalFrame
utility class presented here helps you implement a modal dialog's behavior for any CFrameWnd
-derived window class in an easy way.
If you have to use it and have a bit of time, please add a comment at the bottom of this page and tell, in which context you decided to use this code. I would be interested.
Background
Some basic facts:
- All required features are already implemented in
CFrameWnd
-derived classes. - The basic support of modal message loop is already implemented in the
CWnd
class.
Brief implementation description:
- The utility code uses only the
CFrameWnd
class interface and does not make any suggestions about the internal implementation details of anyCFrameWnd
-derived classes. CModalFrame::Run
creates an instance of the internalCModalDialogLock
class which:- stores modal loop context,
- runs modal message loop and,
- supports multiple running modal frames.
CModalDialogLock
subclasses the created frame window to provide:- update command UI for the frame on
WM_KICKIDLE
message, - exit from modal message loop on
WM_NCDESTROY
message and, - restore standard modal window behavior on
WM_NCACTIVATE
message.
- update command UI for the frame on
- You should not use
WS_CHILD
window style for a frame. Because its parent window is disabled during modal loop. So child frame window also will be disabled (for example, MDI child frame)!
Using the code
- Files needed:
- ModalFrame.h
- ModalFrame.cpp
Sample of usage:
void CMyView::OnRunModalFrame() { CCreateContext context; context.m_pNewViewClass = RUNTIME_CLASS(CMyOtherView); context.m_pCurrentDoc = GetDocument(); context.m_pNewDocTemplate = GetDocument()->GetTemplate(); context.m_pLastView = this; context.m_pCurrentFrame = GetParentFrame(); CRuntimeClass * pFrameClass = RUNTIME_CLASS(CMyModalFrame); if (!CModalFrame::Run(*pFrameClass, false, IDR_MYFRAMERESOURCE, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, this, &context)) { AfxMessageBox(AFX_IDP_COMMAND_FAILURE); } } // don't forget close modal frame like a modal dialog box! void CMyModalFrame::OnClose() { int nModalResult = -1; CModalFrame::End(this, nModalResult); }
See demo project code for more details.
History
- Version 1.2
- Bug fixing.
- More accurate work with a stack of modal frames.
- Version 1.1
- Implemented support for multiple running modal frames.
- More accurate restoring active window after the end of the modal message loop.
- Version 1.0
- Initial version.