moved OnActivate() logic from wxFrame to wxDialog -- this fixes infinite loop when handling WM_ACTIVATE in DefDlgProc in some crazy situations

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15816 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2002-06-13 00:04:22 +00:00
parent 7cc3cec9a7
commit 085ad68651
6 changed files with 104 additions and 76 deletions

View File

@@ -52,7 +52,6 @@ public:
// ------------------------------- // -------------------------------
// event handlers // event handlers
void OnActivate(wxActivateEvent& event);
void OnSysColourChanged(wxSysColourChangedEvent& event); void OnSysColourChanged(wxSysColourChangedEvent& event);
// Toolbar // Toolbar
@@ -103,10 +102,6 @@ public:
// current size - this has an effect of refreshing the window layout // current size - this has an effect of refreshing the window layout
void SendSizeEvent(); void SendSizeEvent();
// called by wxWindow whenever it gets focus
void SetLastFocus(wxWindow *win) { m_winLastFocused = win; }
wxWindow *GetLastFocus() const { return m_winLastFocused; }
protected: protected:
// common part of all ctors // common part of all ctors
void Init(); void Init();
@@ -142,14 +137,10 @@ protected:
static bool m_useNativeStatusBar; static bool m_useNativeStatusBar;
#endif // wxUSE_STATUSBAR #endif // wxUSE_STATUSBAR
// the last focused child: we restore focus to it on activation
wxWindow *m_winLastFocused;
// Data to save/restore when calling ShowFullScreen // Data to save/restore when calling ShowFullScreen
int m_fsStatusBarFields; // 0 for no status bar int m_fsStatusBarFields; // 0 for no status bar
int m_fsStatusBarHeight; int m_fsStatusBarHeight;
int m_fsToolBarHeight; int m_fsToolBarHeight;
// WXHMENU m_fsMenu;
private: private:
#if wxUSE_TOOLTIPS #if wxUSE_TOOLTIPS

View File

@@ -70,6 +70,13 @@ public:
// implementation from now on // implementation from now on
// -------------------------- // --------------------------
// event handlers
void OnActivate(wxActivateEvent& event);
// called by wxWindow whenever it gets focus
void SetLastFocus(wxWindow *win) { m_winLastFocused = win; }
wxWindow *GetLastFocus() const { return m_winLastFocused; }
protected: protected:
// common part of all ctors // common part of all ctors
void Init(); void Init();
@@ -89,10 +96,6 @@ protected:
// common part of Iconize(), Maximize() and Restore() // common part of Iconize(), Maximize() and Restore()
void DoShowWindow(int nShowCmd); void DoShowWindow(int nShowCmd);
// prevent the window from being deactivated sometimes (see comments in the
// code)
long HandleNcActivate(bool activate);
// translate wxWindows flags to Windows ones // translate wxWindows flags to Windows ones
virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const; virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const;
@@ -113,9 +116,14 @@ protected:
bool m_fsIsMaximized; bool m_fsIsMaximized;
bool m_fsIsShowing; bool m_fsIsShowing;
// the last focused child: we restore focus to it on activation
wxWindow *m_winLastFocused;
// the hidden parent window for the frames which shouldn't appear in the // the hidden parent window for the frames which shouldn't appear in the
// taskbar // taskbar
static wxWindow *ms_hiddenParent; static wxWindow *ms_hiddenParent;
DECLARE_EVENT_TABLE()
}; };
// list of all frames and modeless dialogs // list of all frames and modeless dialogs

View File

@@ -364,6 +364,17 @@ void wxWindowBase::Centre(int direction)
} }
} }
// we shouldn't center the dialog on the iconized window: under
// Windows, for example, this places it completely off the screen
if ( parent )
{
wxTopLevelWindow *winTop = wxDynamicCast(parent, wxTopLevelWindow);
if ( winTop && winTop->IsIconized() )
{
parent = NULL;
}
}
// did we find the parent? // did we find the parent?
if ( !parent ) if ( !parent )
{ {

View File

@@ -72,7 +72,6 @@
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxFrame, wxFrameBase) BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
EVT_ACTIVATE(wxFrame::OnActivate)
EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged) EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
END_EVENT_TABLE() END_EVENT_TABLE()
@@ -108,11 +107,8 @@ void wxFrame::Init()
m_fsStatusBarFields = 0; m_fsStatusBarFields = 0;
m_fsStatusBarHeight = 0; m_fsStatusBarHeight = 0;
m_fsToolBarHeight = 0; m_fsToolBarHeight = 0;
// m_fsMenu = 0;
m_wasMinimized = FALSE; m_wasMinimized = FALSE;
m_winLastFocused = (wxWindow *)NULL;
} }
bool wxFrame::Create(wxWindow *parent, bool wxFrame::Create(wxWindow *parent,
@@ -324,7 +320,7 @@ void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
// Pass TRUE to show full screen, FALSE to restore. // Pass TRUE to show full screen, FALSE to restore.
bool wxFrame::ShowFullScreen(bool show, long style) bool wxFrame::ShowFullScreen(bool show, long style)
{ {
if ( IsFullScreen() == show ) if ( IsFullScreen() == show )
return FALSE; return FALSE;
if (show) if (show)
@@ -395,60 +391,10 @@ bool wxFrame::ShowFullScreen(bool show, long style)
SetMenu((HWND)GetHWND(), (HMENU)m_hMenu); SetMenu((HWND)GetHWND(), (HMENU)m_hMenu);
#endif #endif
} }
return wxFrameBase::ShowFullScreen(show, style); return wxFrameBase::ShowFullScreen(show, style);
} }
// Default activation behaviour - set the focus for the first child
// subwindow found.
void wxFrame::OnActivate(wxActivateEvent& event)
{
if ( event.GetActive() )
{
// restore focus to the child which was last focused
wxLogTrace(_T("focus"), _T("wxFrame %08x activated."), m_hWnd);
wxWindow *parent = m_winLastFocused ? m_winLastFocused->GetParent()
: NULL;
if ( !parent )
{
parent = this;
}
wxSetFocusToChild(parent, &m_winLastFocused);
}
else // deactivating
{
// remember the last focused child if it is our child
m_winLastFocused = FindFocus();
// so we NULL it out if it's a child from some other frame
wxWindow *win = m_winLastFocused;
while ( win )
{
if ( win->IsTopLevel() )
{
if ( win != this )
{
m_winLastFocused = NULL;
}
break;
}
win = win->GetParent();
}
wxLogTrace(_T("focus"),
_T("wxFrame %08x deactivated, last focused: %08x."),
m_hWnd,
m_winLastFocused ? GetHwndOf(m_winLastFocused)
: NULL);
event.Skip();
}
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// tool/status bar stuff // tool/status bar stuff
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -77,6 +77,10 @@ wxWindow *wxTopLevelWindowMSW::ms_hiddenParent = NULL;
// wxTopLevelWindowMSW implementation // wxTopLevelWindowMSW implementation
// ============================================================================ // ============================================================================
BEGIN_EVENT_TABLE(wxTopLevelWindowMSW, wxTopLevelWindowBase)
EVT_ACTIVATE(wxTopLevelWindowMSW::OnActivate)
END_EVENT_TABLE()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxDialog helpers // wxDialog helpers
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -116,6 +120,8 @@ void wxTopLevelWindowMSW::Init()
m_fsOldWindowStyle = 0; m_fsOldWindowStyle = 0;
m_fsIsMaximized = FALSE; m_fsIsMaximized = FALSE;
m_fsIsShowing = FALSE; m_fsIsShowing = FALSE;
m_winLastFocused = (wxWindow *)NULL;
} }
WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const
@@ -740,3 +746,57 @@ bool wxTopLevelWindowMSW::EnableCloseButton(bool enable)
return TRUE; return TRUE;
} }
// ----------------------------------------------------------------------------
// wxTopLevelWindow event handling
// ----------------------------------------------------------------------------
// Default activation behaviour - set the focus for the first child
// subwindow found.
void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event)
{
if ( event.GetActive() )
{
// restore focus to the child which was last focused
wxLogTrace(_T("focus"), _T("wxTLW %08x activated."), m_hWnd);
wxWindow *parent = m_winLastFocused ? m_winLastFocused->GetParent()
: NULL;
if ( !parent )
{
parent = this;
}
wxSetFocusToChild(parent, &m_winLastFocused);
}
else // deactivating
{
// remember the last focused child if it is our child
m_winLastFocused = FindFocus();
// so we NULL it out if it's a child from some other frame
wxWindow *win = m_winLastFocused;
while ( win )
{
if ( win->IsTopLevel() )
{
if ( win != this )
{
m_winLastFocused = NULL;
}
break;
}
win = win->GetParent();
}
wxLogTrace(_T("focus"),
_T("wxTLW %08x deactivated, last focused: %08x."),
m_hWnd,
m_winLastFocused ? GetHwndOf(m_winLastFocused)
: NULL);
event.Skip();
}
}

View File

@@ -348,12 +348,12 @@ wxWindowMSW::~wxWindowMSW()
// VS: make sure there's no wxFrame with last focus set to us: // VS: make sure there's no wxFrame with last focus set to us:
for ( wxWindow *win = GetParent(); win; win = win->GetParent() ) for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
{ {
wxFrame *frame = wxDynamicCast(win, wxFrame); wxTopLevelWindow *frame = wxDynamicCast(win, wxTopLevelWindow);
if ( frame ) if ( frame )
{ {
if ( frame->GetLastFocus() == this ) if ( frame->GetLastFocus() == this )
{ {
frame->SetLastFocus((wxWindow*)NULL); frame->SetLastFocus(NULL);
} }
break; break;
} }
@@ -2083,15 +2083,27 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
// ::IsDialogMessage() can enter in an infinite loop when // ::IsDialogMessage() can enter in an infinite loop when
// WS_EX_CONTROLPARENT is specified and the currently focused // WS_EX_CONTROLPARENT is specified and the currently focused
// window is disabled or hidden, so don't call it in this case // window is disabled or hidden, so don't call it in this case
bool canSafelyCallIsDlgMsg = TRUE;
HWND hwndFocus = ::GetFocus(); HWND hwndFocus = ::GetFocus();
if ( !hwndFocus || while ( hwndFocus )
::IsWindowEnabled(hwndFocus) && ::IsWindowVisible(hwndFocus) )
{ {
if ( ::IsDialogMessage(GetHwnd(), msg) ) if ( !::IsWindowEnabled(hwndFocus) ||
!::IsWindowVisible(hwndFocus) )
{ {
// IsDialogMessage() did something... // it would enter an infinite loop if we do this!
return TRUE; canSafelyCallIsDlgMsg = FALSE;
break;
} }
hwndFocus = ::GetParent(hwndFocus);
}
if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
{
// IsDialogMessage() did something...
return TRUE;
} }
} }
} }