menu.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,300 行 · 第 1/5 页
CPP
2,300 行
m_popupMenu->SelectFirst();
}
// the geometry might have changed since the last time we were shown, so
// always resize
m_popupMenu->SetClientSize(GetGeometryInfo().GetSize());
// position it as specified
m_popupMenu->Position(pos, size);
// the menu can't have the focus itself (it is a Windows limitation), so
// always keep the focus at the originating window
wxWindow *focus = GetRootWindow();
wxASSERT_MSG( focus, _T("no window to keep focus on?") );
// and show it
m_popupMenu->Popup(focus);
}
void wxMenu::Dismiss()
{
wxCHECK_RET( IsShown(), _T("can't dismiss hidden menu") );
m_popupMenu->Dismiss();
}
// ----------------------------------------------------------------------------
// wxMenu event processing
// ----------------------------------------------------------------------------
bool wxMenu::ProcessKeyDown(int key)
{
wxCHECK_MSG( m_popupMenu, false,
_T("can't process key events if not shown") );
return m_popupMenu->ProcessKeyDown(key);
}
bool wxMenu::ClickItem(wxMenuItem *item)
{
int isChecked;
if ( item->IsCheckable() )
{
// update the item state
isChecked = !item->IsChecked();
item->Check(isChecked != 0);
}
else
{
// not applicabled
isChecked = -1;
}
return SendEvent(item->GetId(), isChecked);
}
// ----------------------------------------------------------------------------
// wxMenu accel support
// ----------------------------------------------------------------------------
#if wxUSE_ACCEL
bool wxMenu::ProcessAccelEvent(const wxKeyEvent& event)
{
// do we have an item for this accel?
wxMenuItem *item = m_accelTable.GetMenuItem(event);
if ( item && item->IsEnabled() )
{
return ClickItem(item);
}
// try our submenus
for ( wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
node;
node = node->GetNext() )
{
const wxMenuItem *item = node->GetData();
if ( item->IsSubMenu() && item->IsEnabled() )
{
// try its elements
if ( item->GetSubMenu()->ProcessAccelEvent(event) )
{
return true;
}
}
}
return false;
}
void wxMenu::AddAccelFor(wxMenuItem *item)
{
wxAcceleratorEntry *accel = item->GetAccel();
if ( accel )
{
accel->SetMenuItem(item);
m_accelTable.Add(*accel);
delete accel;
}
}
void wxMenu::RemoveAccelFor(wxMenuItem *item)
{
wxAcceleratorEntry *accel = item->GetAccel();
if ( accel )
{
m_accelTable.Remove(*accel);
delete accel;
}
}
#endif // wxUSE_ACCEL
// ----------------------------------------------------------------------------
// wxMenuItem construction
// ----------------------------------------------------------------------------
wxMenuItem::wxMenuItem(wxMenu *parentMenu,
int id,
const wxString& text,
const wxString& help,
wxItemKind kind,
wxMenu *subMenu)
: wxMenuItemBase(parentMenu, id, text, help, kind, subMenu)
{
m_posY =
m_height = wxDefaultCoord;
m_radioGroup.start = -1;
m_isRadioGroupStart = false;
m_bmpDisabled = wxNullBitmap;
UpdateAccelInfo();
}
wxMenuItem::~wxMenuItem()
{
}
// ----------------------------------------------------------------------------
// wxMenuItemBase methods implemented here
// ----------------------------------------------------------------------------
/* static */
wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
int id,
const wxString& name,
const wxString& help,
wxItemKind kind,
wxMenu *subMenu)
{
return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
}
/* static */
wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
{
return wxStripMenuCodes(text);
}
// ----------------------------------------------------------------------------
// wxMenuItem operations
// ----------------------------------------------------------------------------
void wxMenuItem::NotifyMenu()
{
m_parentMenu->RefreshItem(this);
}
void wxMenuItem::UpdateAccelInfo()
{
m_indexAccel = wxControl::FindAccelIndex(m_text);
// will be empty if the text contains no TABs - ok
m_strAccel = m_text.AfterFirst(_T('\t'));
}
void wxMenuItem::SetText(const wxString& text)
{
if ( text != m_text )
{
// first call the base class version to change m_text
wxMenuItemBase::SetText(text);
UpdateAccelInfo();
NotifyMenu();
}
}
void wxMenuItem::SetCheckable(bool checkable)
{
if ( checkable != IsCheckable() )
{
wxMenuItemBase::SetCheckable(checkable);
NotifyMenu();
}
}
void wxMenuItem::SetBitmaps(const wxBitmap& bmpChecked,
const wxBitmap& bmpUnchecked)
{
m_bmpChecked = bmpChecked;
m_bmpUnchecked = bmpUnchecked;
NotifyMenu();
}
void wxMenuItem::Enable(bool enable)
{
if ( enable != m_isEnabled )
{
wxMenuItemBase::Enable(enable);
NotifyMenu();
}
}
void wxMenuItem::Check(bool check)
{
wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
if ( m_isChecked == check )
return;
if ( GetKind() == wxITEM_RADIO )
{
// it doesn't make sense to uncheck a radio item - what would this do?
if ( !check )
return;
// get the index of this item in the menu
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
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;
}
// 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();
}
}
wxMenuItemBase::Check(check);
NotifyMenu();
}
// radio group stuff
// -----------------
void wxMenuItem::SetAsRadioGroupStart()
{
m_isRadioGroupStart = true;
}
void wxMenuItem::SetRadioGroupStart(int start)
{
wxASSERT_MSG( !m_isRadioGroupStart,
_T("should only be called for the next radio items") );
m_radioGroup.start = start;
}
void wxMenuItem::SetRadioGroupEnd(int end)
{
wxASSERT_MSG( m_isRadioGroupStart,
_T("should only be called for the first radio item") );
m_radioGroup.end = end;
}
// ----------------------------------------------------------------------------
// wxMenuBar creation
// ----------------------------------------------------------------------------
void wxMenuBar::Init()
{
m_frameLast = NULL;
m_current = -1;
m_menuShown = NULL;
m_shouldShowMenu = false;
}
wxMenuBar::wxMenuBar(size_t n, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
{
Init();
for (size_t i = 0; i < n; ++i )
Append(menus[i], titles[i]);
}
void wxMenuBar::Attach(wxFrame *frame)
{
// maybe you really wanted to call Detach()?
wxCHECK_RET( frame, _T("wxMenuBar::Attach(NULL) called") );
wxMenuBarBase::Attach(frame);
if ( IsCreated() )
{
// reparent if necessary
if ( m_frameLast != frame )
{
Reparent(frame);
}
// show it back - was hidden by Detach()
Show();
}
else // not created yet, do it now
{
// we have no way to return the error from here anyhow :-(
(void)Create(frame, wxID_ANY);
SetCursor(wxCURSOR_ARROW);
SetFont(wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT));
// calculate and set our height (it won't be changed any more)
SetSize(wxDefaultCoord, GetBestSize().y);
}
// remember the last frame which had us to avoid unnecessarily reparenting
// above
m_frameLast = frame;
}
void wxMenuBar::Detach()
{
// don't delete the window because we may be reattached later, just hide it
if ( m_frameLast )
{
Hide();
}
wxMenuBarBase::Detach();
}
wxMenuBar::~wxMenuBar()
{
}
// ----------------------------------------------------------------------------
// wxMenuBar adding/removing items
// ----------------------------------------------------------------------------
bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
{
return Insert(GetCount(), menu, title);
}
bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
{
if ( !wxMenuBarBase::Insert(pos, menu, title) )
return false;
wxMenuInfo *info = new wxMenuInfo(title);
m_menuInfos.Insert(info, pos);
RefreshAllItemsAfter(pos);
return true;
}
wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
{
wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
if ( menuOld )
{
wxMenuInfo& info = m_menuInfos[pos];
info.SetLabel(title);
// even if the old menu was disabled, the new one is not any more
info.SetEnabled();
// even if we change only this one, the new label has different width,
// so we need to refresh everything beyond this item as well
RefreshAllItemsAfter(pos);
}
return menuOld;
}
wxMenu *wxMenuBar::Remove(size_t pos)
{
wxMenu *menuOld = wxMenuBarBase::Remove(pos);
if ( menuOld )
{
m_menuInfos.RemoveAt(pos);
// this doesn't happen too often, so don't try to be too smart - just
// refresh everything
Refresh();
}
return menuOld;
}
// ----------------------------------------------------------------------------
// wxMenuBar top level menus access
// ----------------------------------------------------------------------------
wxCoord wxMenuBar::GetItemWidth(size_t pos) const
{
return m_menuInfos[pos].GetWidth(wxConstCast(this, wxMenuBar));
}
void wxMenuBar::EnableTop(size_t pos, bool enable)
{
wxCHECK_RET( pos < GetCount(), _T("invalid index in EnableTop") );
if ( enable != m_menuInfos[pos].IsEnabled() )
{
m_menuInfos[pos].SetEnabled(enable);
RefreshItem(pos);
}
//else: nothing to do
}
bool wxMenuBar::IsEnabledTop(size_t pos) const
{
wxCHECK_MSG( pos < GetCount(), false, _T("invalid index in IsEnabledTop") );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?