Reputation: 630
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 CWnd
s 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 CWnd
s 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 CWnd
s 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 CWnd
s 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
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