attempt to fix another occurence of WS_EX_CONTROLPARENT-related infinite loop

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23573 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2003-09-14 10:58:11 +00:00
parent 874d12cff7
commit ee47181777

View File

@@ -221,6 +221,38 @@ static inline void wxBringWindowToTop(HWND hwnd)
} }
} }
// ensure that all our parent windows have WS_EX_CONTROLPARENT style
static void EnsureParentHasControlParentStyle(wxWindow *parent)
{
/*
If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
parent as well as otherwise several Win32 functions using
GetNextDlgTabItem() to iterate over all controls such as
IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
all of them iterate over all the controls starting from the currently
focused one and stop iterating when they get back to the focus but
unless all parents have WS_EX_CONTROLPARENT bit set, they would never
get back to the initial (focused) window: as we do have this style,
GetNextDlgTabItem() will leave this window and continue in its parent,
but if the parent doesn't have it, it wouldn't recurse inside it later
on and so wouldn't have a chance of getting back to this window neither.
*/
#ifndef __WXWINCE__
while ( parent && !parent->IsTopLevel() )
{
LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
if ( !(exStyle & WS_EX_CONTROLPARENT) )
{
// force the parent to have this style
::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
exStyle | WS_EX_CONTROLPARENT);
}
parent = parent->GetParent();
}
#endif // !__WXWINCE__
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// event tables // event tables
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -1290,6 +1322,13 @@ bool wxWindowMSW::Reparent(wxWindowBase *parent)
::SetParent(hWndChild, hWndParent); ::SetParent(hWndChild, hWndParent);
#ifndef __WXWINCE__
if ( ::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
{
EnsureParentHasControlParentStyle(GetParent());
}
#endif // !__WXWINCE__
return TRUE; return TRUE;
} }
@@ -3229,32 +3268,13 @@ bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate) bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate)
{ {
// if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our // VZ: why is this commented out for WinCE? If it doesn't support
// parent as well as otherwise several Win32 functions using // WS_EX_CONTROLPARENT at all it should be somehow handled globally,
// GetNextDlgTabItem() to iterate over all controls such as // not with multiple #ifdef's!
// IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
// all of them iterate over all the controls starting from the focus and
// stop iterating when they get back to the focus but unless all parents
// have WS_EX_CONTROLPARENT bit set, they would never get back to focus
#ifndef __WXWINCE__ #ifndef __WXWINCE__
if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT ) if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT )
{ EnsureParentHasControlParentStyle(GetParent());
// there is no need to do anything for the top level windows #endif // !__WXWINCE__
const wxWindow *parent = GetParent();
while ( parent && !parent->IsTopLevel() )
{
LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
if ( !(exStyle & WS_EX_CONTROLPARENT) )
{
// force the parent to have this style
::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
exStyle | WS_EX_CONTROLPARENT);
}
parent = parent->GetParent();
}
}
#endif
// TODO: should generate this event from WM_NCCREATE // TODO: should generate this event from WM_NCCREATE
wxWindowCreateEvent event((wxWindow *)this); wxWindowCreateEvent event((wxWindow *)this);