📄 wg_menu.cpp
字号:
iWidth += 9; } else { CPoint Dims; iter->second.first.GetMetrics(&Dims, 0, 0); CRect TextRect(SubRect.Left() + iWidth, SubRect.Top() + 2, SubRect.Left() + iWidth + Dims.XPos(), SubRect.Bottom() - 2); TextRect.Grow(2); iter->second.second = TextRect; iWidth += Dims.XPos() + 8; } } m_bCachedRectsValid = true; }}void CMenu::ShowActivePopup(const CRect& ParentRect, const CRect& BoundingRect){ // TODO: Add bounds checking for all edges. Apply this same bounds checking logic to the popup root menu too. if (!m_pActivePopup) { throw(Wg_Ex_App("CMenu::ShowActivePopup() : Trying to show active popup menu when pActivePopup is NULL!")); } CRect MenuRect = m_pActivePopup->GetWindowRect(); if (BoundingRect.HitTest(ParentRect.BottomLeft() + CPoint(MenuRect.Width(), 0)) & CRect::RELPOS_RIGHT) { int xDelta = BoundingRect.Right() - ParentRect.Left() + MenuRect.Width(); if (!(BoundingRect.HitTest(ParentRect.BottomLeft() + CPoint(xDelta, 0)) & CRect::RELPOS_LEFT)) { m_pActivePopup->Show(ParentRect.BottomLeft() + CPoint(xDelta, 5)); } } else { m_pActivePopup->Show(ParentRect.BottomLeft() + CPoint(0, 5)); } // Pop the popup to the top of the draw order and everything m_pActivePopup->SetNewParent(m_pActivePopup->GetAncestor(PARENT));}// CPopupMenuCPopupMenu::CPopupMenu(const CRect& WindowRect, CWindow* pParent, CFontEngine* pFontEngine) : CMenuBase(WindowRect, pParent, pFontEngine), m_pParentMenu(0){ m_sClassName = "CPopupMenu"; m_bVisible = false; CMessageServer::Instance().RegisterMessageClient(this, CMessage::MOUSE_BUTTONDOWN);}CPopupMenu::~CPopupMenu(void){}void CPopupMenu::Show(CPoint Position){ if (m_bVisible) { Hide(); } int iHeight = 4; for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (iter->first.bSpacer) iHeight += 6; else { CPoint Dims; iter->second.first.GetMetrics(&Dims, 0, 0); iHeight += Dims.YPos() + 5; } } SetWindowRect(CRect(Position, Position + CPoint(m_WindowRect.Width() - 1, iHeight + 2))); m_bVisible = true; StartDrawProc();}void CPopupMenu::Hide(void){ HideActivePopup(); m_bVisible = false; m_bCachedRectsValid = false; CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_PAINT, 0, this)); m_pHighlightedItem = 0;}void CPopupMenu::HideAll(void){ CPopupMenu* pParentPopup = dynamic_cast<CPopupMenu*>(m_pParentWindow); if (pParentPopup) { pParentPopup->HideAll(); } else { CMenu* pRootMenu = dynamic_cast<CMenu*>(m_pParentWindow); if (pRootMenu) { pRootMenu->HideActivePopup(); } else { Hide(); } }}bool CPopupMenu::IsInsideChild(CPoint& Point){ if (m_WindowRect.HitTest(Point) == CRect::RELPOS_INSIDE) { return true; } if (!m_pActivePopup) { return false; } return m_pActivePopup->IsInsideChild(Point);}void CPopupMenu::Draw(void) const{ CWindow::Draw(); CPainter Painter(m_pSDLSurface); Painter.DrawRect(m_WindowRect, false, COLOR_LIGHTGRAY); Painter.DrawHLine(m_WindowRect.Left(), m_WindowRect.Right(), m_WindowRect.Bottom(), COLOR_DARKGRAY); Painter.DrawVLine(m_WindowRect.Top(), m_WindowRect.Bottom(), m_WindowRect.Right(), COLOR_DARKGRAY); UpdateCachedRects(); for (t_MenuItemVector::const_iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (m_pHighlightedItem == &(iter->first)) { Painter.DrawRect(iter->second.second, true, m_HighlightColor, m_HighlightColor); } CRect TextRect(iter->second.second); TextRect.Grow(-2); if (iter->first.bSpacer) { Painter.DrawHLine(TextRect.Left(), TextRect.Right(), TextRect.Top(), COLOR_LIGHTGRAY); Painter.DrawHLine(TextRect.Left(), TextRect.Right(), TextRect.Bottom(), COLOR_DARKGRAY); } else iter->second.first.Draw(m_pSDLSurface, TextRect, TextRect.TopLeft()); if (iter->first.pPopup) { CRect ArrowRect(iter->second.second); ArrowRect.SetLeft(ArrowRect.Right() - m_hRightArrowBitmap.Bitmap()->w); SDL_Rect SourceRect; SourceRect.x = static_cast<short int>(0); SourceRect.y = static_cast<short int>((m_hRightArrowBitmap.Bitmap()->h - ArrowRect.Height()) / 2 < 0 ? 0 : (m_hRightArrowBitmap.Bitmap()->h - ArrowRect.Height()) / 2); SourceRect.w = static_cast<short int>(m_hRightArrowBitmap.Bitmap()->w); SourceRect.h = static_cast<short int>(std::min(ArrowRect.Height(), m_hRightArrowBitmap.Bitmap()->h)); SDL_Rect DestRect; DestRect.x = static_cast<short int>(ArrowRect.Left()); DestRect.y = static_cast<short int>((ArrowRect.Height() - m_hRightArrowBitmap.Bitmap()->h) / 2 < 0 ? ArrowRect.Top() : ArrowRect.Top() + (ArrowRect.Height() - m_hRightArrowBitmap.Bitmap()->h) / 2); DestRect.w = static_cast<short int>(m_hRightArrowBitmap.Bitmap()->w); DestRect.h = static_cast<short int>(std::min(ArrowRect.Height(), m_hRightArrowBitmap.Bitmap()->h)); SDL_BlitSurface(m_hRightArrowBitmap.Bitmap(), &SourceRect, m_pSDLSurface, &DestRect); } }}bool CPopupMenu::OnMouseButtonDown(CPoint Point, unsigned int Button){ bool bResult = false; if (! CMenuBase::OnMouseButtonDown(Point, Button) && m_bVisible && (m_WindowRect.HitTest(Point) == CRect::RELPOS_INSIDE)) { UpdateCachedRects(); for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (iter->second.second.HitTest(Point) == CRect::RELPOS_INSIDE && !iter->first.bSpacer) { if (!iter->first.pPopup) { CMessageClient* pDestination = m_pParentWindow; if (m_pParentMenu) { pDestination = m_pParentMenu; } CMessageServer::Instance().QueueMessage(new TIntMessage(CMessage::CTRL_LCLICK, pDestination, this, iter->first.iItemId)); HideAll(); } else { HideActivePopup(); m_pActivePopup = iter->first.pPopup; ShowActivePopup(iter->second.second, GetAncestor(ROOT)->GetClientRect()); } break; } } bResult = true; } return bResult;}bool CPopupMenu::HandleMessage(CMessage* pMessage){ bool bHandled = false; if (pMessage) { switch(pMessage->MessageType()) { case CMessage::MOUSE_BUTTONDOWN: { CMouseMessage* pMouseMessage = dynamic_cast<CMouseMessage*>(pMessage); if (m_bVisible && pMouseMessage && (m_WindowRect.HitTest(pMouseMessage->Point) != CRect::RELPOS_INSIDE)) { // If the user clicked outside the window, we just want to hide the window, // and then pass the message on (bHandled = false) // But we only want the root popup to do this, and only if none of it's children were hit if (!dynamic_cast<CPopupMenu*>(m_pParentWindow) && !IsInsideChild(pMouseMessage->Point) && !(m_pParentMenu && m_pParentMenu->GetWindowRect().HitTest(pMouseMessage->Point) == CRect::RELPOS_INSIDE)) { HideAll(); } } break; } case CMessage::CTRL_TIMER: { if (pMessage->Destination() == this) { CRect ItemRect; for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (m_pHighlightedItem == &(iter->first)) { ItemRect = iter->second.second; break; } } if (m_pHighlightedItem && m_pHighlightedItem->pPopup) { HideActivePopup(); m_pActivePopup = m_pHighlightedItem->pPopup; ShowActivePopup(ItemRect, GetAncestor(ROOT)->GetClientRect()); } bHandled = true; } break; } default : bHandled = CMenuBase::HandleMessage(pMessage); break; } } return bHandled;}void CPopupMenu::UpdateCachedRects(void) const{ if (!m_bCachedRectsValid) { CRect SubRect(m_WindowRect); SubRect.Grow(-2); int iHeight = 4; for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (iter->first.bSpacer) { CRect TextRect(SubRect.Left() + 3, SubRect.Top() + iHeight, SubRect.Right() - 3, SubRect.Top() + iHeight + 1); TextRect.Grow(2); iter->second.second = TextRect; iHeight += 6; } else { CPoint Dims; iter->second.first.GetMetrics(&Dims, 0, 0); CRect TextRect(SubRect.Left() + 3, SubRect.Top() + iHeight, SubRect.Right() - 3, SubRect.Top() + iHeight + Dims.YPos()); TextRect.Grow(2); iter->second.second = TextRect; iHeight += Dims.YPos() + 5; } } m_bCachedRectsValid = true; }}void CPopupMenu::ShowActivePopup(const CRect& ParentRect, const CRect& BoundingRect){ // TODO: Add bounds checking for all edges. Apply this same bounds checking logic to the popup root menu too. if (!m_pActivePopup) { throw(Wg_Ex_App("CPopupMenu::ShowActivePopup() : Trying to show active popup menu when pActivePopup is NULL!")); } CRect MenuRect = m_pActivePopup->GetWindowRect(); if (BoundingRect.HitTest(ParentRect.TopRight() + CPoint(5, 0) + CPoint(MenuRect.Width(), 0)) & CRect::RELPOS_RIGHT) { m_pActivePopup->Show(ParentRect.TopLeft() - CPoint(MenuRect.Width() + 5, 0)); } else { m_pActivePopup->Show(ParentRect.TopRight() + CPoint(5, 0)); }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -