From 036da5e37479c4e2bc3493d3a7a37ac629757515 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 11 May 2002 22:31:05 +0000 Subject: [PATCH] changed the handling of the default buttons to be more logical git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15516 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/containr.h | 32 +++++++++++--- include/wx/msw/button.h | 7 ++++ include/wx/window.h | 3 ++ src/common/containr.cpp | 4 ++ src/msw/button.cpp | 92 +++++++++++++++++++++++++++++++---------- src/msw/window.cpp | 9 +--- 7 files changed, 114 insertions(+), 34 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index bdeb238c76..fc25ee8c8d 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -191,6 +191,7 @@ wxMSW: - Implemented wxMouseCaptureChangedEvent and made wxGenericDragImage check it has the capture before release it. - fixed bugs in multiple selection wxCheckListBox +- default button handling is now closer to expected wxGTK: diff --git a/include/wx/containr.h b/include/wx/containr.h index b74b2c2a8f..d6df418e25 100644 --- a/include/wx/containr.h +++ b/include/wx/containr.h @@ -37,18 +37,29 @@ class WXDLLEXPORT wxWindowBase; class WXDLLEXPORT wxControlContainer { - DECLARE_NO_COPY_CLASS(wxControlContainer) - public: // ctors and such wxControlContainer(wxWindow *winParent = NULL); void SetContainerWindow(wxWindow *winParent) { m_winParent = winParent; } - // default item access - wxWindow *GetDefaultItem() const { return m_winDefault; } + // default item access: we have a permanent default item which is the one + // set by the user code but we may also have a temporary default item which + // would be chosen if the user pressed "Enter" now but the default action + // reverts to the "permanent" default as soon as this temporary default + // item lsoes focus + + // get the default item, temporary or permanent + wxWindow *GetDefaultItem() const + { return m_winTmpDefault ? m_winTmpDefault : m_winDefault; } + + // set the permanent default item, return its old value wxWindow *SetDefaultItem(wxWindow *win) { wxWindow *winOld = m_winDefault; m_winDefault = win; return winOld; } + // set a temporary default item, SetTmpDefaultItem(NULL) should be called + // soon after a call to SetTmpDefaultItem(window) + void SetTmpDefaultItem(wxWindow *win) { m_winTmpDefault = win; } + // the methods to be called from the window event handlers void HandleOnNavigationKey(wxNavigationKeyEvent& event); void HandleOnFocus(wxFocusEvent& event); @@ -72,8 +83,13 @@ protected: // the child which had the focus last time this panel was activated wxWindow *m_winLastFocused; - // a default window (e.g. a button) or NULL + // a default window (usually a button) or NULL wxWindow *m_winDefault; + + // a temporary override of m_winDefault, use the latter if NULL + wxWindow *m_winTmpDefault; + + DECLARE_NO_COPY_CLASS(wxControlContainer) }; // this function is for wxWindows internal use only @@ -94,6 +110,7 @@ public: \ virtual void RemoveChild(wxWindowBase *child); \ virtual wxWindow *GetDefaultItem() const; \ virtual wxWindow *SetDefaultItem(wxWindow *child); \ + virtual void SetTmpDefaultItem(wxWindow *win); \ \ protected: \ wxControlContainer m_container @@ -111,6 +128,11 @@ wxWindow *classname::SetDefaultItem(wxWindow *child) \ return m_container.SetDefaultItem(child); \ } \ \ +void classname::SetTmpDefaultItem(wxWindow *child) \ +{ \ + m_container.SetTmpDefaultItem(child); \ +} \ + \ wxWindow *classname::GetDefaultItem() const \ { \ return m_container.GetDefaultItem(); \ diff --git a/include/wx/msw/button.h b/include/wx/msw/button.h index 70f51f6fa5..77986f7e87 100644 --- a/include/wx/msw/button.h +++ b/include/wx/msw/button.h @@ -69,6 +69,13 @@ protected: // send a notification event, return TRUE if processed bool SendClickEvent(); + // default button handling + void SetTmpDefault(); + void UnsetTmpDefault(); + + static void UpdateDefaultStyle(wxWindow *winDefault, + wxWindow *winOldDefault); + // usually overridden base class virtuals virtual wxSize DoGetBestSize() const; virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const; diff --git a/include/wx/window.h b/include/wx/window.h index 94f9919e5d..e048a84744 100644 --- a/include/wx/window.h +++ b/include/wx/window.h @@ -400,6 +400,9 @@ public: virtual wxWindow *SetDefaultItem(wxWindow * WXUNUSED(child)) { return NULL; } + // set this child as temporary default + virtual void SetTmpDefaultItem(wxWindow * WXUNUSED(win)) { } + // parent/children relations // ------------------------- diff --git a/src/common/containr.cpp b/src/common/containr.cpp index 90a20eb833..624382ff28 100644 --- a/src/common/containr.cpp +++ b/src/common/containr.cpp @@ -45,6 +45,7 @@ wxControlContainer::wxControlContainer(wxWindow *winParent) m_winParent = winParent; m_winLastFocused = + m_winTmpDefault = m_winDefault = NULL; } @@ -263,6 +264,9 @@ void wxControlContainer::HandleOnWindowDestroy(wxWindowBase *child) if ( child == m_winDefault ) m_winDefault = NULL; + + if ( child == m_winTmpDefault ) + m_winTmpDefault = NULL; } // ---------------------------------------------------------------------------- diff --git a/src/msw/button.cpp b/src/msw/button.cpp index 2cafeca17e..c00c3d11d0 100644 --- a/src/msw/button.cpp +++ b/src/msw/button.cpp @@ -180,36 +180,71 @@ wxSize wxButtonBase::GetDefaultSize() } // ---------------------------------------------------------------------------- -// set this button as the default one in its panel +// default button handling // ---------------------------------------------------------------------------- +// set this button as the (permanently) default one in its panel void wxButton::SetDefault() { wxWindow *parent = GetParent(); - wxButton *btnOldDefault; - if ( parent ) - { - wxWindow *winOldDefault = parent->SetDefaultItem(this); - btnOldDefault = wxDynamicCast(winOldDefault, wxButton); - ::SendMessage(GetWinHwnd(parent), DM_SETDEFID, m_windowId, 0L); + wxCHECK_RET( parent, _T("button without parent?") ); + + // set this one as the default button both for wxWindows and Windows + wxWindow *winOldDefault = parent->SetDefaultItem(this); + ::SendMessage(GetWinHwnd(parent), DM_SETDEFID, m_windowId, 0L); + + UpdateDefaultStyle(this, winOldDefault); +} + +void wxButton::SetTmpDefault() +{ + wxWindow *parent = GetParent(); + + wxCHECK_RET( parent, _T("button without parent?") ); + + wxWindow *winOldDefault = parent->GetDefaultItem(); + parent->SetTmpDefaultItem(this); + if ( winOldDefault != this ) + { + UpdateDefaultStyle(this, winOldDefault); } - else // is a button without parent really normal? + //else: no styles to update +} + +void wxButton::UnsetTmpDefault() +{ + wxWindow *parent = GetParent(); + + wxCHECK_RET( parent, _T("button without parent?") ); + + parent->SetTmpDefaultItem(NULL); + + wxWindow *winOldDefault = parent->GetDefaultItem(); + if ( winOldDefault != this ) { - btnOldDefault = NULL; + UpdateDefaultStyle(winOldDefault, this); } + //else: we had been default before anyhow +} - if ( btnOldDefault && btnOldDefault != this ) +/* static */ +void +wxButton::UpdateDefaultStyle(wxWindow *winDefault, wxWindow *winOldDefault) +{ + // clear the BS_DEFPUSHBUTTON for the old default button + wxButton *btnOldDefault = wxDynamicCast(winOldDefault, wxButton); + if ( btnOldDefault && btnOldDefault != winDefault ) { // remove the BS_DEFPUSHBUTTON style from the other button - long style = GetWindowLong(GetHwndOf(btnOldDefault), GWL_STYLE); + long style = ::GetWindowLong(GetHwndOf(btnOldDefault), GWL_STYLE); // don't do it with the owner drawn buttons because it will reset // BS_OWNERDRAW style bit too (BS_OWNERDRAW & BS_DEFPUSHBUTTON != 0)! if ( (style & BS_OWNERDRAW) != BS_OWNERDRAW ) { style &= ~BS_DEFPUSHBUTTON; - SendMessage(GetHwndOf(btnOldDefault), BM_SETSTYLE, style, 1L); + ::SendMessage(GetHwndOf(btnOldDefault), BM_SETSTYLE, style, 1L); } else { @@ -219,12 +254,20 @@ void wxButton::SetDefault() } } - // set this button as the default - long style = GetWindowLong(GetHwnd(), GWL_STYLE); - if ( (style & BS_OWNERDRAW) != BS_OWNERDRAW ) + // and set BS_DEFPUSHBUTTON for this button + wxButton *btnDefault = wxDynamicCast(winDefault, wxButton); + if ( btnDefault ) { - style |= BS_DEFPUSHBUTTON; - SendMessage(GetHwnd(), BM_SETSTYLE, style, 1L); + long style = ::GetWindowLong(GetHwndOf(btnDefault), GWL_STYLE); + if ( (style & BS_OWNERDRAW) != BS_OWNERDRAW ) + { + style |= BS_DEFPUSHBUTTON; + ::SendMessage(GetHwndOf(btnDefault), BM_SETSTYLE, style, 1L); + } + else + { + btnDefault->Refresh(); + } } } @@ -266,13 +309,18 @@ bool wxButton::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) long wxButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { - // when we receive focus, we want to become the default button in our - // parent panel + // when we receive focus, we want to temporary become the default button in + // our parent panel so that pressing "Enter" would activate us -- and when + // losing it we should restore the previous default button as well if ( nMsg == WM_SETFOCUS ) { - SetDefault(); + SetTmpDefault(); - // let the default processign take place too + // let the default processing take place too + } + else if ( nMsg == WM_KILLFOCUS ) + { + UnsetTmpDefault(); } else if ( nMsg == WM_LBUTTONDBLCLK ) { @@ -280,7 +328,7 @@ long wxButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) // appearance - without this, it won't do it (void)wxControl::MSWWindowProc(WM_LBUTTONDOWN, wParam, lParam); - // and conitnue with processing the message normally as well + // and continue with processing the message normally as well } // let the base class do all real processing diff --git a/src/msw/window.cpp b/src/msw/window.cpp index c633426aba..b99b966f66 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -1995,14 +1995,9 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) return TRUE; } - else // no default button + //else: no default button #endif // wxUSE_BUTTON - { - // no special function for enter and don't even - // let IsDialogMessage() have it: it seems to - // do something really strange with it - return FALSE; - } + // treat Enter as TAB: pass to the next control } } break; -- 2.45.2