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

View File

@ -70,6 +70,13 @@ public:
// 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:
// common part of all ctors
void Init();
@ -89,10 +96,6 @@ protected:
// common part of Iconize(), Maximize() and Restore()
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
virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const;
@ -113,9 +116,14 @@ protected:
bool m_fsIsMaximized;
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
// taskbar
static wxWindow *ms_hiddenParent;
DECLARE_EVENT_TABLE()
};
// 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?
if ( !parent )
{

View File

@ -72,7 +72,6 @@
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
EVT_ACTIVATE(wxFrame::OnActivate)
EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
END_EVENT_TABLE()
@ -108,11 +107,8 @@ void wxFrame::Init()
m_fsStatusBarFields = 0;
m_fsStatusBarHeight = 0;
m_fsToolBarHeight = 0;
// m_fsMenu = 0;
m_wasMinimized = FALSE;
m_winLastFocused = (wxWindow *)NULL;
}
bool wxFrame::Create(wxWindow *parent,
@ -324,7 +320,7 @@ void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
// Pass TRUE to show full screen, FALSE to restore.
bool wxFrame::ShowFullScreen(bool show, long style)
{
if ( IsFullScreen() == show )
if ( IsFullScreen() == show )
return FALSE;
if (show)
@ -395,60 +391,10 @@ bool wxFrame::ShowFullScreen(bool show, long style)
SetMenu((HWND)GetHWND(), (HMENU)m_hMenu);
#endif
}
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
// ----------------------------------------------------------------------------

View File

@ -77,6 +77,10 @@ wxWindow *wxTopLevelWindowMSW::ms_hiddenParent = NULL;
// wxTopLevelWindowMSW implementation
// ============================================================================
BEGIN_EVENT_TABLE(wxTopLevelWindowMSW, wxTopLevelWindowBase)
EVT_ACTIVATE(wxTopLevelWindowMSW::OnActivate)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// wxDialog helpers
// ----------------------------------------------------------------------------
@ -116,6 +120,8 @@ void wxTopLevelWindowMSW::Init()
m_fsOldWindowStyle = 0;
m_fsIsMaximized = FALSE;
m_fsIsShowing = FALSE;
m_winLastFocused = (wxWindow *)NULL;
}
WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const
@ -740,3 +746,57 @@ bool wxTopLevelWindowMSW::EnableCloseButton(bool enable)
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:
for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
{
wxFrame *frame = wxDynamicCast(win, wxFrame);
wxTopLevelWindow *frame = wxDynamicCast(win, wxTopLevelWindow);
if ( frame )
{
if ( frame->GetLastFocus() == this )
{
frame->SetLastFocus((wxWindow*)NULL);
frame->SetLastFocus(NULL);
}
break;
}
@ -2083,15 +2083,27 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
// ::IsDialogMessage() can enter in an infinite loop when
// WS_EX_CONTROLPARENT is specified and the currently focused
// window is disabled or hidden, so don't call it in this case
bool canSafelyCallIsDlgMsg = TRUE;
HWND hwndFocus = ::GetFocus();
if ( !hwndFocus ||
::IsWindowEnabled(hwndFocus) && ::IsWindowVisible(hwndFocus) )
while ( hwndFocus )
{
if ( ::IsDialogMessage(GetHwnd(), msg) )
if ( !::IsWindowEnabled(hwndFocus) ||
!::IsWindowVisible(hwndFocus) )
{
// IsDialogMessage() did something...
return TRUE;
// it would enter an infinite loop if we do this!
canSafelyCallIsDlgMsg = FALSE;
break;
}
hwndFocus = ::GetParent(hwndFocus);
}
if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
{
// IsDialogMessage() did something...
return TRUE;
}
}
}