fixed default button handling: don't keep BS_DEFPUSHBUTTON style when the app loses focus

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16689 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2002-08-22 20:34:29 +00:00
parent cdfb1ae1bc
commit 7fb1b2b4c4
2 changed files with 62 additions and 45 deletions

View File

@@ -73,8 +73,8 @@ protected:
void SetTmpDefault(); void SetTmpDefault();
void UnsetTmpDefault(); void UnsetTmpDefault();
static void UpdateDefaultStyle(wxWindow *winDefault, // set or unset BS_DEFPUSHBUTTON style
wxWindow *winOldDefault); static void SetDefaultStyle(wxButton *btn, bool on);
// usually overridden base class virtuals // usually overridden base class virtuals
virtual wxSize DoGetBestSize() const; virtual wxSize DoGetBestSize() const;

View File

@@ -201,7 +201,9 @@ wxSize wxButtonBase::GetDefaultSize()
handled by ::DefWindowProc() (or maybe ::DefDialogProc()) using DM_SETDEFID handled by ::DefWindowProc() (or maybe ::DefDialogProc()) using DM_SETDEFID
Another aspect of "defaultness" is that the default button has different Another aspect of "defaultness" is that the default button has different
appearance: this is due to BS_DEFPUSHBUTTON style which is completely appearance: this is due to BS_DEFPUSHBUTTON style which is completely
separate from DM_SETDEFID stuff (!). separate from DM_SETDEFID stuff (!). Also note that BS_DEFPUSHBUTTON should
be unset if our parent window is not active so it should be unset whenever
we lose activation and set back when we regain it.
Final complication is that when a button is active, it should be the default Final complication is that when a button is active, it should be the default
one, i.e. pressing Enter on a button always activates it and not another one, i.e. pressing Enter on a button always activates it and not another
@@ -215,9 +217,13 @@ wxSize wxButtonBase::GetDefaultSize()
the default item will be the permanent default -- that is the default button the default item will be the permanent default -- that is the default button
if any had been set or none otherwise, which is just what we want. if any had been set or none otherwise, which is just what we want.
Remark that we probably don't need to send DM_SETDEFID as we don't use NB: all this is quite complicated by now and the worst is that normally
::IsDialogMessage() (which relies on it) any longer but OTOH it probably it shouldn't be necessary at all as for the normal Windows programs
doesn't hurt neither. DefWindowProc() and IsDialogMessage() take care of all this
automatically -- however in wxWindows programs this doesn't work for
nested hierarchies (i.e. a notebook inside a notebook) for unknown
reason and so we have to reproduce all this code ourselves. It would be
very nice if we could avoid doing it.
*/ */
// set this button as the (permanently) default one in its panel // set this button as the (permanently) default one in its panel
@@ -227,13 +233,15 @@ void wxButton::SetDefault()
wxCHECK_RET( parent, _T("button without parent?") ); wxCHECK_RET( parent, _T("button without parent?") );
// set this one as the default button both for wxWindows and Windows // set this one as the default button both for wxWindows ...
wxWindow *winOldDefault = parent->SetDefaultItem(this); wxWindow *winOldDefault = parent->SetDefaultItem(this);
::SendMessage(GetWinHwnd(parent), DM_SETDEFID, m_windowId, 0L);
UpdateDefaultStyle(this, winOldDefault); // ... and Windows
SetDefaultStyle(wxDynamicCast(winOldDefault, wxButton), FALSE);
SetDefaultStyle(this, TRUE);
} }
// set this button as being currently default
void wxButton::SetTmpDefault() void wxButton::SetTmpDefault()
{ {
wxWindow *parent = GetParent(); wxWindow *parent = GetParent();
@@ -242,13 +250,12 @@ void wxButton::SetTmpDefault()
wxWindow *winOldDefault = parent->GetDefaultItem(); wxWindow *winOldDefault = parent->GetDefaultItem();
parent->SetTmpDefaultItem(this); parent->SetTmpDefaultItem(this);
if ( winOldDefault != this )
{ SetDefaultStyle(wxDynamicCast(winOldDefault, wxButton), FALSE);
UpdateDefaultStyle(this, winOldDefault); SetDefaultStyle(this, TRUE);
}
//else: no styles to update
} }
// unset this button as currently default, it may still stay permanent default
void wxButton::UnsetTmpDefault() void wxButton::UnsetTmpDefault()
{ {
wxWindow *parent = GetParent(); wxWindow *parent = GetParent();
@@ -258,54 +265,64 @@ void wxButton::UnsetTmpDefault()
parent->SetTmpDefaultItem(NULL); parent->SetTmpDefaultItem(NULL);
wxWindow *winOldDefault = parent->GetDefaultItem(); wxWindow *winOldDefault = parent->GetDefaultItem();
if ( winOldDefault != this )
{ SetDefaultStyle(this, FALSE);
UpdateDefaultStyle(winOldDefault, this); SetDefaultStyle(wxDynamicCast(winOldDefault, wxButton), TRUE);
}
//else: we had been default before anyhow
} }
/* static */ /* static */
void void
wxButton::UpdateDefaultStyle(wxWindow *winDefault, wxWindow *winOldDefault) wxButton::SetDefaultStyle(wxButton *btn, bool on)
{ {
// clear the BS_DEFPUSHBUTTON for the old default button // we may be called with NULL pointer -- simpler to do the check here than
wxButton *btnOldDefault = wxDynamicCast(winOldDefault, wxButton); // in the caller which does wxDynamicCast()
if ( btnOldDefault && btnOldDefault != winDefault ) if ( !btn )
{ return;
// remove the BS_DEFPUSHBUTTON style from the other button
long style = ::GetWindowLong(GetHwndOf(btnOldDefault), GWL_STYLE);
// don't do it with the owner drawn buttons because it will reset // first, let DefDlgProc() know about the new default button
// BS_OWNERDRAW style bit too (BS_OWNERDRAW & BS_DEFPUSHBUTTON != 0)! if ( on )
if ( (style & BS_OWNERDRAW) != BS_OWNERDRAW ) {
// we shouldn't set BS_DEFPUSHBUTTON for any button if we don't have
// focus at all any more
if ( !wxTheApp->IsActive() )
return;
// look for a panel-like window
wxWindow *win = btn->GetParent();
while ( win && !win->HasFlag(wxTAB_TRAVERSAL) )
win = win->GetParent();
if ( win )
{ {
style &= ~BS_DEFPUSHBUTTON; ::SendMessage(GetHwndOf(win), DM_SETDEFID, btn->GetId(), 0L);
::SendMessage(GetHwndOf(btnOldDefault), BM_SETSTYLE, style, 1L);
} // sending DM_SETDEFID also changes the button style to
else // BS_DEFPUSHBUTTON so there is nothing more to do
{
// redraw the button - it will notice itself that it's not the
// default one any longer
btnOldDefault->Refresh();
} }
} }
// and set BS_DEFPUSHBUTTON for this button // then also change the style as needed
wxButton *btnDefault = wxDynamicCast(winDefault, wxButton); long style = ::GetWindowLong(GetHwndOf(btn), GWL_STYLE);
if ( btnDefault ) if ( !(style & BS_DEFPUSHBUTTON) == on )
{ {
long style = ::GetWindowLong(GetHwndOf(btnDefault), GWL_STYLE); // don't do it with the owner drawn buttons because it will
// reset BS_OWNERDRAW style bit too (as BS_OWNERDRAW &
// BS_DEFPUSHBUTTON != 0)!
if ( (style & BS_OWNERDRAW) != BS_OWNERDRAW ) if ( (style & BS_OWNERDRAW) != BS_OWNERDRAW )
{ {
style |= BS_DEFPUSHBUTTON; ::SendMessage(GetHwndOf(btn), BM_SETSTYLE,
::SendMessage(GetHwndOf(btnDefault), BM_SETSTYLE, style, 1L); on ? style | BS_DEFPUSHBUTTON
: style & ~BS_DEFPUSHBUTTON,
1L /* redraw */);
} }
else else // owner drawn
{ {
btnDefault->Refresh(); // redraw the button - it will notice itself that it's
// [not] the default one [any longer]
btn->Refresh();
} }
} }
//else: already has correct style
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------