nagates
nagates

Reputation: 630

MFC Child Dialog that behaves like a popup (upgrade From VC6 change)

I have a MFC project I maintain, that recently got upgraded from VC6->2013, and apparently some core Windows code become stricter with regards WS_POPUP and WS_CHILD, can no longer be mixed. I have a program that crates a child dialog to alter some settings (of an image for example), the child dialog would have top level focus, and this child dialog would also spin off 2 new CWnd of it's own a essentially preview and result window, with the following dwStyle flags set WS_POPUP | WS_CAPTION | WS_CHILD which worked in VC6, but now is a no no. The full window create logic,

m_wndDst = new CWnd;
m_wndDst->CreateEx(WS_EX_CONTROLPARENT , NULL,
                             szTitle, WS_POPUP | WS_CHILD | WS_BORDER | WS_CAPTION, 
                             10, 10, 10, 10, m_hWnd, NULL, NULL);

This child dialog will often destroy and re-create these child CWnds it's perhaps not the best solution, but it's a fairly large legacy project, that I wish to disturbe the least amount as possible.

So I remove the WS_POPUP per another S.O QA, but that isn't quite right either, because now my CWnds are now being renderws within my initial child dialog,clipped and have z-order issues with regards to controls, this is no good, even if it makes sense, If I change the hWndParent param in CrateEx to the top level Parent hWnd, this is closer to what I want, but my initial child dialog still has focus, and the contents of my 2 sub windows does not get rendered (essentially transparent), the title is there, the border is there, but no content, and the CWnds can not be selected and freely moving around.

I've tried removing the WS_CHILD style, and leaving the WS_POPUP, but that is no good either, as in wincore.cpp the PreCreateWindow does a check to ensure that it is a child window,

    if (cs.lpszClass == NULL)
    {
        // make sure the default window class is registered
        VERIFY(AfxDeferRegisterClass(AFX_WND_REG));

        // no WNDCLASS provided - use child window default
        ASSERT(cs.style & WS_CHILD);
        cs.lpszClass = _afxWnd;
    }

So in essence what I am trying to achieve is, I need my initial child dialog to be able to spin up to CWnds that act more like popup windows, titlebar, and a border, and really nothing else. They has need to be at the same focus level as the child dialog that created them (the main frame is untouchable until the child dialog is closed), if the child dialog closes, it would close the 2 CWnds as well, and like before should be able to move out side of the main frame.

Any help, articles, suggestions would be greatly appreciated.

EDIT 1 based on comments --- this gets me close really close, just have re-draw issues.

//auto dwStyle = WS_POPUP | WS_CHILD | WS_BORDER | WS_CAPTION; // original
    auto dwStyle = WS_BORDER | WS_CAPTION | WS_VISIBLE;
    //auto dwStyle = WS_CHILD | WS_BORDER | WS_CAPTION | WS_VISIBLE;

    CString sClass = AfxRegisterWndClass(
            CS_VREDRAW | CS_HREDRAW,
            ::LoadCursor(nullptr, IDC_ARROW),
            static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH)),
            ::LoadIcon(nullptr, IDI_APPLICATION));

    auto result = pWndSrcOrDest->CreateEx(WS_EX_CONTROLPARENT, sClass,
        sWindowTitle, dwStyle, 10, 10, 10, 10, this->m_hWnd, nullptr, nullptr);

Upvotes: 1

Views: 2147

Answers (1)

VuVirt
VuVirt

Reputation: 1917

You can do it like this:

LPCTSTR strClassNameDlgOwner = AfxRegisterWndClass(NULL);

pWndOwner->CreateEx(WS_EX_CONTROLPARENT, strClassNameDlgOwner,
    sWindowTitleOwner, WS_POPUP | WS_BORDER | WS_CAPTION | WS_VISIBLE, 10, 10, 10, 10, this->m_hWnd, nullptr, nullptr); // this->m_hWnd is the handle to the Main application window

LPCTSTR strClassNameDlgOwned = AfxRegisterWndClass(NULL);

pWndOwned->CreateEx(WS_EX_CONTROLPARENT, strClassNameDlgOwned,
    sWindowTitleOwned, WS_POPUP | WS_BORDER | WS_CAPTION | WS_VISIBLE, 10, 10, 10, 10, pWndOwner->GetSafeHwnd(), nullptr, nullptr);

The first dialog is the Owner window, while the second level dialogs that the first one creates are the Owned windows.

Upvotes: 2

Related Questions