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:
@@ -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 )
|
||||||
|
Reference in New Issue
Block a user