This article describes how to modify a modal dialog's styles and position at run-time so it can work both as a child of a
CPropertySheet as well as a pop-up window on its own.
CPropertyPage is added to a
CPropertySheet, it has to be a child of that property sheet. Also, the property page has to be disabled and not visible initially. What if the same property page has to be run independent of the property sheet, as a modal dialog? In that case, the styles have to be changed at run-time. When do we change the styles? It turns out that doing so in
OnInitDialog() is too late. Besides, the repositioning of the popup dialog requires some specific options which may not be apparent from the MSDN documentation. This article shows how to do both.
Using the code
DialogStyleModificationExample project is a very simple dialog based MFC app with two buttons. The "Open Dialog With Default Styles" button adds the property page
CPropertyPageFirst, without changing its style or position, to a
CPropertySheet and opens the property sheet.
The "Open Dialog With Modified Styles" sets the modify flag for the property page and starts it up as a modal dialog on its own. We override
PreSubclassWindow to change the property page's styles.
if (m_bModifyDlgStylesAndPos == true)
if(m_hWnd != NULL)
LONG lStyle = GetWindowLong(m_hWnd, GWL_STYLE);
lStyle &= ~WS_CHILD; lStyle &= ~WS_DISABLED;
lStyle |= WS_POPUP; lStyle |= WS_VISIBLE; lStyle |= WS_SYSMENU;
SetWindowLong(m_hWnd, GWL_STYLE, lStyle);
We set the dialog's position by overriding
if((m_bModifyDlgStylesAndPos == true) && m_hWnd)
SetWindowText("Modified Property Page");
CRect rectFrame, rectDlg;
CWnd* pMainWnd = AfxGetMainWnd();
if(pMainWnd != NULL)
int nXPos = rectFrame.left + (rectFrame.Width() / 2)
- (rectDlg.Width() / 2);
int nYPos = rectFrame.top + (rectFrame.Height() / 2)
- (rectDlg.Height() / 2);
::SetWindowPos(m_hWnd, HWND_TOP, nXPos, nYPos,
rectDlg.Width(), rectDlg.Height(), SWP_NOCOPYBITS);
Points of Interest
The main task here was to use the same property page in two different environments:
- As a child of a
- As an independent pop-up dialog.
It was apparent that I would have to modify the dialog's style in case #2. I tried doing this in
ModifyStyle(...) but that did not work as it is too late to change a child window to a pop-up in
PreCreateWindow(...) thinking I could change the
CREATESTRUCT in this function to change both the styles and position in one go. But it turns out that
PreCreateWindow(...) doesn't get called at all for modal dialogs.
I could try instantiating the dialog as modeless but there were two problems with this approach:
PreCreateWindow(...) still didn't get called.
- Memory management problems occurred as one instance of the dialog was modal and the other was modeless.
I could get around a) above by calling
CreateEx(...) as doing so would call
PreCreateWindow(...) but at this point we would be creating the styles for the dialog from scratch instead of modifying them which is not what we intended. So the solution was to modify the styles in
PreSubclassWindow(). Now you may be tempted to re-position the dialog here as well but no matter how you try it, the dialog does not move from the left corner of the screen. Additionally, the dialog is drawn with some areas as transparent. So you have to re-position it in
There is one more catch though: when using
::SetWindowPos(...), you have to specify
SWP_NOCOPYBITS as the window sizing and positioning flag, otherwise all valid contents of the client area of the previous window position are copied into the client area after the window is sized or repositioned, resulting in a strange looking dialog with some unexpected graphics.
That's it! Please go ahead and experiment, suggest other ways to accomplish the same. Enjoy!