check for m_parentMenu being NULL in IsChecked/Checked/Enable() too (closes #10460)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58590 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2009-02-01 12:30:27 +00:00
parent 64894596ea
commit 654c223bc7

View File

@@ -203,12 +203,20 @@ WXWPARAM wxMenuItem::GetMSWId() const
bool wxMenuItem::IsChecked() const bool wxMenuItem::IsChecked() const
{ {
// fix that RTTI is always getting the correct state (separators cannot be checked, but the call below // fix that RTTI is always getting the correct state (separators cannot be
// returns true // checked, but the Windows call below returns true
if ( IsSeparator() ) if ( IsSeparator() )
return false ; return false;
int flag = ::GetMenuState(GetHMenuOf(m_parentMenu), GetMSWId(), MF_BYCOMMAND); // the item might not be attached to a menu yet
//
// TODO: shouldn't we just always call the base class version? It seems
// like it ought to always be in sync
if ( !m_parentMenu )
return wxMenuItemBase::IsChecked();
HMENU hmenu = GetHMenuOf(m_parentMenu);
int flag = ::GetMenuState(hmenu, GetMSWId(), MF_BYCOMMAND);
return (flag & MF_CHECKED) != 0; return (flag & MF_CHECKED) != 0;
} }
@@ -245,13 +253,17 @@ void wxMenuItem::Enable(bool enable)
if ( m_isEnabled == enable ) if ( m_isEnabled == enable )
return; return;
long rc = EnableMenuItem(GetHMenuOf(m_parentMenu), if ( m_parentMenu )
GetMSWId(), {
MF_BYCOMMAND | long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
(enable ? MF_ENABLED : MF_GRAYED)); GetMSWId(),
MF_BYCOMMAND |
(enable ? MF_ENABLED : MF_GRAYED));
if ( rc == -1 ) { if ( rc == -1 )
wxLogLastError(wxT("EnableMenuItem")); {
wxLogLastError(wxT("EnableMenuItem"));
}
} }
wxMenuItemBase::Enable(enable); wxMenuItemBase::Enable(enable);
@@ -264,74 +276,78 @@ void wxMenuItem::Check(bool check)
if ( m_isChecked == check ) if ( m_isChecked == check )
return; return;
int flags = check ? MF_CHECKED : MF_UNCHECKED; if ( m_parentMenu )
HMENU hmenu = GetHMenuOf(m_parentMenu);
if ( GetKind() == wxITEM_RADIO )
{ {
// it doesn't make sense to uncheck a radio item - what would this do? int flags = check ? MF_CHECKED : MF_UNCHECKED;
if ( !check ) HMENU hmenu = GetHMenuOf(m_parentMenu);
return;
// get the index of this item in the menu if ( GetKind() == wxITEM_RADIO )
const wxMenuItemList& items = m_parentMenu->GetMenuItems();
int pos = items.IndexOf(this);
wxCHECK_RET( pos != wxNOT_FOUND,
_T("menuitem not found in the menu items list?") );
// get the radio group range
int start,
end;
if ( m_isRadioGroupStart )
{ {
// we already have all information we need // it doesn't make sense to uncheck a radio item -- what would this
start = pos; // do?
end = m_radioGroup.end; if ( !check )
} return;
else // next radio group item
{
// get the radio group end from the start item
start = m_radioGroup.start;
end = items.Item(start)->GetData()->m_radioGroup.end;
}
#ifdef __WIN32__ // get the index of this item in the menu
// calling CheckMenuRadioItem() with such parameters hangs my system const wxMenuItemList& items = m_parentMenu->GetMenuItems();
// (NT4 SP6) and I suspect this could happen to the others as well - so int pos = items.IndexOf(this);
// don't do it! wxCHECK_RET( pos != wxNOT_FOUND,
wxCHECK_RET( start != -1 && end != -1, _T("menuitem not found in the menu items list?") );
_T("invalid ::CheckMenuRadioItem() parameter(s)") );
if ( !::CheckMenuRadioItem(hmenu, // get the radio group range
start, // the first radio group item int start,
end, // the last one end;
pos, // the one to check
MF_BYPOSITION) )
{
wxLogLastError(_T("CheckMenuRadioItem"));
}
#endif // __WIN32__
// also uncheck all the other items in this radio group if ( m_isRadioGroupStart )
wxMenuItemList::compatibility_iterator node = items.Item(start);
for ( int n = start; n <= end && node; n++ )
{
if ( n != pos )
{ {
node->GetData()->m_isChecked = false; // we already have all information we need
start = pos;
end = m_radioGroup.end;
}
else // next radio group item
{
// get the radio group end from the start item
start = m_radioGroup.start;
end = items.Item(start)->GetData()->m_radioGroup.end;
} }
node = node->GetNext(); #ifdef __WIN32__
// calling CheckMenuRadioItem() with such parameters hangs my system
// (NT4 SP6) and I suspect this could happen to the others as well,
// so don't do it!
wxCHECK_RET( start != -1 && end != -1,
_T("invalid ::CheckMenuRadioItem() parameter(s)") );
if ( !::CheckMenuRadioItem(hmenu,
start, // the first radio group item
end, // the last one
pos, // the one to check
MF_BYPOSITION) )
{
wxLogLastError(_T("CheckMenuRadioItem"));
}
#endif // __WIN32__
// also uncheck all the other items in this radio group
wxMenuItemList::compatibility_iterator node = items.Item(start);
for ( int n = start; n <= end && node; n++ )
{
if ( n != pos )
{
node->GetData()->m_isChecked = false;
}
node = node->GetNext();
}
} }
} else // check item
else // check item
{
if ( ::CheckMenuItem(hmenu,
GetMSWId(),
MF_BYCOMMAND | flags) == (DWORD)-1 )
{ {
wxFAIL_MSG( _T("CheckMenuItem() failed, item not in the menu?") ); if ( ::CheckMenuItem(hmenu,
GetMSWId(),
MF_BYCOMMAND | flags) == (DWORD)-1 )
{
wxFAIL_MSG(_T("CheckMenuItem() failed, item not in the menu?"));
}
} }
} }
@@ -358,16 +374,15 @@ void wxMenuItem::SetItemLabel(const wxString& txt)
SetAccelString(m_text.AfterFirst(_T('\t'))); SetAccelString(m_text.AfterFirst(_T('\t')));
#endif #endif
#if wxUSE_ACCEL
if ( m_parentMenu )
m_parentMenu->UpdateAccel(this);
#endif // wxUSE_ACCEL
// the item can be not attached to any menu yet and SetItemLabel() is still // the item can be not attached to any menu yet and SetItemLabel() is still
// valid to call in this case and should do nothing else // valid to call in this case and should do nothing else
if ( !m_parentMenu ) if ( !m_parentMenu )
return; return;
#if wxUSE_ACCEL
m_parentMenu->UpdateAccel(this);
#endif // wxUSE_ACCEL
const UINT id = GetMSWId(); const UINT id = GetMSWId();
HMENU hMenu = GetHMenuOf(m_parentMenu); HMENU hMenu = GetHMenuOf(m_parentMenu);
if ( !hMenu || ::GetMenuState(hMenu, id, MF_BYCOMMAND) == (UINT)-1 ) if ( !hMenu || ::GetMenuState(hMenu, id, MF_BYCOMMAND) == (UINT)-1 )