#include "StdAfx.h" #include "UIMenu.h" namespace DuiLib { ///////////////////////////////////////////////////////////////////////////////////// // IMPLEMENT_DUICONTROL(CMenuUI) CMenuUI::CMenuUI(): m_pWindow(NULL) { if (GetHeader() != NULL) GetHeader()->SetVisible(false); } CMenuUI::~CMenuUI() { } LPCTSTR CMenuUI::GetClass() const { return _T("MenuUI"); } LPVOID CMenuUI::GetInterface(LPCTSTR pstrName) { if( _tcsicmp(pstrName, _T("Menu")) == 0 ) return static_cast(this); return CListUI::GetInterface(pstrName); } UINT CMenuUI::GetListType() { return LT_MENU; } void CMenuUI::DoEvent(TEventUI& event) { return __super::DoEvent(event); } bool CMenuUI::Add(CControlUI* pControl) { CMenuElementUI* pMenuItem = static_cast(pControl->GetInterface(_T("MenuElement"))); if (pMenuItem == NULL) return false; for (int i = 0; i < pMenuItem->GetCount(); ++i) { if (pMenuItem->GetItemAt(i)->GetInterface(_T("MenuElement")) != NULL) { (static_cast(pMenuItem->GetItemAt(i)->GetInterface(_T("MenuElement"))))->SetInternVisible(false); } } return CListUI::Add(pControl); } bool CMenuUI::AddAt(CControlUI* pControl, int iIndex) { CMenuElementUI* pMenuItem = static_cast(pControl->GetInterface(_T("MenuElement"))); if (pMenuItem == NULL) return false; for (int i = 0; i < pMenuItem->GetCount(); ++i) { if (pMenuItem->GetItemAt(i)->GetInterface(_T("MenuElement")) != NULL) { (static_cast(pMenuItem->GetItemAt(i)->GetInterface(_T("MenuElement"))))->SetInternVisible(false); } } return CListUI::AddAt(pControl, iIndex); } int CMenuUI::GetItemIndex(CControlUI* pControl) const { CMenuElementUI* pMenuItem = static_cast(pControl->GetInterface(_T("MenuElement"))); if (pMenuItem == NULL) return -1; return __super::GetItemIndex(pControl); } bool CMenuUI::SetItemIndex(CControlUI* pControl, int iIndex) { CMenuElementUI* pMenuItem = static_cast(pControl->GetInterface(_T("MenuElement"))); if (pMenuItem == NULL) return false; return __super::SetItemIndex(pControl, iIndex); } bool CMenuUI::Remove(CControlUI* pControl) { CMenuElementUI* pMenuItem = static_cast(pControl->GetInterface(_T("MenuElement"))); if (pMenuItem == NULL) return false; return __super::Remove(pControl); } SIZE CMenuUI::EstimateSize(SIZE szAvailable) { int cxFixed = 0; int cyFixed = 0; for( int it = 0; it < GetCount(); it++ ) { CControlUI* pControl = static_cast(GetItemAt(it)); if( !pControl->IsVisible() ) continue; SIZE sz = pControl->EstimateSize(szAvailable); cyFixed += sz.cy; if( cxFixed < sz.cx ) cxFixed = sz.cx; } for (int it = 0; it < GetCount(); it++) { CControlUI* pControl = static_cast(GetItemAt(it)); if (!pControl->IsVisible()) continue; pControl->SetFixedWidth(MulDiv(cxFixed, 100, GetManager()->GetDPIObj()->GetScale())); } return CDuiSize(cxFixed, cyFixed); } void CMenuUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) { CListUI::SetAttribute(pstrName, pstrValue); } ///////////////////////////////////////////////////////////////////////////////////// // CMenuWnd::CMenuWnd(): m_pOwner(NULL), m_pLayout(), m_xml(_T("")), isClosing(false) { m_dwAlignment = eMenuAlignment_Left | eMenuAlignment_Top; } CMenuWnd::~CMenuWnd() { } void CMenuWnd::Close(UINT nRet) { ASSERT(::IsWindow(m_hWnd)); if (!::IsWindow(m_hWnd)) return; PostMessage(WM_CLOSE, (WPARAM)nRet, 0L); isClosing = true; } BOOL CMenuWnd::Receive(ContextMenuParam param) { switch (param.wParam) { case 1: Close(); break; case 2: { HWND hParent = GetParent(m_hWnd); while (hParent != NULL) { if (hParent == param.hWnd) { Close(); break; } hParent = GetParent(hParent); } } break; default: break; } return TRUE; } CMenuWnd* CMenuWnd::CreateMenu(CMenuElementUI* pOwner, STRINGorID xml, POINT point, CPaintManagerUI* pMainPaintManager, CStdStringPtrMap* pMenuCheckInfo /*= NULL*/, DWORD dwAlignment /*= eMenuAlignment_Left | eMenuAlignment_Top*/) { CMenuWnd* pMenu = new CMenuWnd; pMenu->Init(pOwner, xml, point, pMainPaintManager, pMenuCheckInfo, dwAlignment); return pMenu; } void CMenuWnd::DestroyMenu() { CStdStringPtrMap* mCheckInfos = CMenuWnd::GetGlobalContextMenuObserver().GetMenuCheckInfo(); if (mCheckInfos != NULL) { for(int i = 0; i < mCheckInfos->GetSize(); i++) { MenuItemInfo* pItemInfo = (MenuItemInfo*)mCheckInfos->Find(mCheckInfos->GetAt(i)); if(pItemInfo != NULL) { delete pItemInfo; pItemInfo = NULL; } } mCheckInfos->Resize(0); } } MenuItemInfo* CMenuWnd::SetMenuItemInfo(LPCTSTR pstrName, bool bChecked) { if(pstrName == NULL || lstrlen(pstrName) <= 0) return NULL; CStdStringPtrMap* mCheckInfos = CMenuWnd::GetGlobalContextMenuObserver().GetMenuCheckInfo(); if (mCheckInfos != NULL) { MenuItemInfo* pItemInfo = (MenuItemInfo*)mCheckInfos->Find(pstrName); if(pItemInfo == NULL) { pItemInfo = new MenuItemInfo; lstrcpy(pItemInfo->szName, pstrName); pItemInfo->bChecked = bChecked; mCheckInfos->Insert(pstrName, pItemInfo); } else { pItemInfo->bChecked = bChecked; } return pItemInfo; } return NULL; } void CMenuWnd::Init(CMenuElementUI* pOwner, STRINGorID xml, POINT point, CPaintManagerUI* pMainPaintManager, CStdStringPtrMap* pMenuCheckInfo/* = NULL*/, DWORD dwAlignment/* = eMenuAlignment_Left | eMenuAlignment_Top*/) { m_BasedPoint = point; m_pOwner = pOwner; m_pLayout = NULL; m_xml = xml; m_dwAlignment = dwAlignment; // 如果是一级菜单的创建 if (pOwner == NULL) { ASSERT(pMainPaintManager != NULL); CMenuWnd::GetGlobalContextMenuObserver().SetManger(pMainPaintManager); if (pMenuCheckInfo != NULL) CMenuWnd::GetGlobalContextMenuObserver().SetMenuCheckInfo(pMenuCheckInfo); } CMenuWnd::GetGlobalContextMenuObserver().AddReceiver(this); Create((m_pOwner == NULL) ? pMainPaintManager->GetPaintWindow() : m_pOwner->GetManager()->GetPaintWindow(), NULL, WS_POPUP , WS_EX_TOOLWINDOW | WS_EX_TOPMOST, CDuiRect()); // HACK: Don't deselect the parent's caption HWND hWndParent = m_hWnd; while( ::GetParent(hWndParent) != NULL ) hWndParent = ::GetParent(hWndParent); ::ShowWindow(m_hWnd, SW_SHOW); ::SendMessage(hWndParent, WM_NCACTIVATE, TRUE, 0L); } LPCTSTR CMenuWnd::GetWindowClassName() const { return _T("DuiMenuWnd"); } void CMenuWnd::Notify(TNotifyUI& msg) { if( CMenuWnd::GetGlobalContextMenuObserver().GetManager() != NULL) { if( msg.sType == _T("click") || msg.sType == _T("valuechanged") ) { CMenuWnd::GetGlobalContextMenuObserver().GetManager()->SendNotify(msg, false); } } } CControlUI* CMenuWnd::CreateControl( LPCTSTR pstrClassName ) { if (_tcsicmp(pstrClassName, _T("Menu")) == 0) { return new CMenuUI(); } else if (_tcsicmp(pstrClassName, _T("MenuElement")) == 0) { return new CMenuElementUI(); } return NULL; } void CMenuWnd::OnFinalMessage(HWND hWnd) { RemoveObserver(); if( m_pOwner != NULL ) { for( int i = 0; i < m_pOwner->GetCount(); i++ ) { if( static_cast(m_pOwner->GetItemAt(i)->GetInterface(_T("MenuElement"))) != NULL ) { (static_cast(m_pOwner->GetItemAt(i)))->SetOwner(m_pOwner->GetParent()); (static_cast(m_pOwner->GetItemAt(i)))->SetVisible(false); (static_cast(m_pOwner->GetItemAt(i)->GetInterface(_T("MenuElement"))))->SetInternVisible(false); } } m_pOwner->m_pWindow = NULL; m_pOwner->m_uButtonState &= ~ UISTATE_PUSHED; m_pOwner->Invalidate(); // 内部创建的内部删除 delete this; } } LRESULT CMenuWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bool bShowShadow = false; if( m_pOwner != NULL) { LONG styleValue = ::GetWindowLong(*this, GWL_STYLE); styleValue &= ~WS_CAPTION; ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); RECT rcClient; ::GetClientRect(*this, &rcClient); ::SetWindowPos(*this, NULL, rcClient.left, rcClient.top, rcClient.right - rcClient.left, \ rcClient.bottom - rcClient.top, SWP_FRAMECHANGED); m_pm.Init(m_hWnd); m_pm.GetDPIObj()->SetScale(m_pOwner->GetManager()->GetDPIObj()->GetDPI()); // The trick is to add the items to the new container. Their owner gets // reassigned by this operation - which is why it is important to reassign // the items back to the righfull owner/manager when the window closes. m_pLayout = new CMenuUI(); m_pm.SetForceUseSharedRes(true); m_pLayout->SetManager(&m_pm, NULL, true); LPCTSTR pDefaultAttributes = m_pOwner->GetManager()->GetDefaultAttributeList(_T("Menu")); if( pDefaultAttributes ) { m_pLayout->ApplyAttributeList(pDefaultAttributes); } m_pLayout->GetList()->SetAutoDestroy(false); for( int i = 0; i < m_pOwner->GetCount(); i++ ) { if(m_pOwner->GetItemAt(i)->GetInterface(_T("MenuElement")) != NULL ){ (static_cast(m_pOwner->GetItemAt(i)))->SetOwner(m_pLayout); m_pLayout->Add(static_cast(m_pOwner->GetItemAt(i))); } } CShadowUI *pShadow = m_pOwner->GetManager()->GetShadow(); pShadow->CopyShadow(m_pm.GetShadow()); bShowShadow = m_pm.GetShadow()->IsShowShadow(); m_pm.GetShadow()->ShowShadow(false); m_pm.SetLayered(m_pOwner->GetManager()->IsLayered()); m_pm.AttachDialog(m_pLayout); m_pm.AddNotifier(this); ResizeSubMenu(); } else { m_pm.Init(m_hWnd); m_pm.GetDPIObj()->SetScale(CMenuWnd::GetGlobalContextMenuObserver().GetManager()->GetDPIObj()->GetDPI()); CDialogBuilder builder; CControlUI* pRoot = builder.Create(m_xml,UINT(0), this, &m_pm); bShowShadow = m_pm.GetShadow()->IsShowShadow(); m_pm.GetShadow()->ShowShadow(false); m_pm.AttachDialog(pRoot); m_pm.AddNotifier(this); ResizeMenu(); } GetMenuUI()->m_pWindow = this; m_pm.GetShadow()->ShowShadow(bShowShadow); m_pm.GetShadow()->Create(&m_pm); return 0; } CMenuUI* CMenuWnd::GetMenuUI() { return static_cast(m_pm.GetRoot()); } void CMenuWnd::ResizeMenu() { CControlUI* pRoot = m_pm.GetRoot(); #if defined(WIN32) && !defined(UNDER_CE) MONITORINFO oMonitor = {}; oMonitor.cbSize = sizeof(oMonitor); ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor); CDuiRect rcWork = oMonitor.rcWork; #else CDuiRect rcWork; GetWindowRect(m_pOwner->GetManager()->GetPaintWindow(), &rcWork); #endif SIZE szAvailable = { rcWork.right - rcWork.left, rcWork.bottom - rcWork.top }; szAvailable = pRoot->EstimateSize(szAvailable); m_pm.SetInitSize(szAvailable.cx, szAvailable.cy); //必须是Menu标签作为xml的根节点 CMenuUI *pMenuRoot = static_cast(pRoot); ASSERT(pMenuRoot); SIZE szInit = m_pm.GetInitSize(); CDuiRect rc; CDuiPoint point = m_BasedPoint; rc.left = point.x; rc.top = point.y; rc.right = rc.left + szInit.cx; rc.bottom = rc.top + szInit.cy; int nWidth = rc.GetWidth(); int nHeight = rc.GetHeight(); if (m_dwAlignment & eMenuAlignment_Right) { rc.right = point.x; rc.left = rc.right - nWidth; } if (m_dwAlignment & eMenuAlignment_Bottom) { rc.bottom = point.y; rc.top = rc.bottom - nHeight; } SetForegroundWindow(m_hWnd); MoveWindow(m_hWnd, rc.left, rc.top, rc.GetWidth(), rc.GetHeight(), FALSE); SetWindowPos(m_hWnd, HWND_TOPMOST, rc.left, rc.top, rc.GetWidth(), rc.GetHeight() + pMenuRoot->GetInset().bottom + pMenuRoot->GetInset().top, SWP_SHOWWINDOW); } void CMenuWnd::ResizeSubMenu() { // Position the popup window in absolute space RECT rcOwner = m_pOwner->GetPos(); RECT rc = rcOwner; int cxFixed = 0; int cyFixed = 0; #if defined(WIN32) && !defined(UNDER_CE) MONITORINFO oMonitor = {}; oMonitor.cbSize = sizeof(oMonitor); ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor); CDuiRect rcWork = oMonitor.rcWork; #else CDuiRect rcWork; GetWindowRect(m_pOwner->GetManager()->GetPaintWindow(), &rcWork); #endif SIZE szAvailable = { rcWork.right - rcWork.left, rcWork.bottom - rcWork.top }; for( int it = 0; it < m_pOwner->GetCount(); it++ ) { if(m_pOwner->GetItemAt(it)->GetInterface(_T("MenuElement")) != NULL ){ CControlUI* pControl = static_cast(m_pOwner->GetItemAt(it)); SIZE sz = pControl->EstimateSize(szAvailable); cyFixed += sz.cy; if( cxFixed < sz.cx ) cxFixed = sz.cx; } } RECT rcWindow; GetWindowRect(m_pOwner->GetManager()->GetPaintWindow(), &rcWindow); rc.top = rcOwner.top; rc.bottom = rc.top + cyFixed; ::MapWindowRect(m_pOwner->GetManager()->GetPaintWindow(), HWND_DESKTOP, &rc); rc.left = rcWindow.right; rc.right = rc.left + cxFixed; rc.right += 2; bool bReachBottom = false; bool bReachRight = false; LONG chRightAlgin = 0; LONG chBottomAlgin = 0; RECT rcPreWindow = {0}; MenuObserverImpl::Iterator iterator(CMenuWnd::GetGlobalContextMenuObserver()); MenuMenuReceiverImplBase* pReceiver = iterator.next(); while( pReceiver != NULL ) { CMenuWnd* pContextMenu = dynamic_cast(pReceiver); if( pContextMenu != NULL ) { GetWindowRect(pContextMenu->GetHWND(), &rcPreWindow); bReachRight = rcPreWindow.left >= rcWindow.right; bReachBottom = rcPreWindow.top >= rcWindow.bottom; if( pContextMenu->GetHWND() == m_pOwner->GetManager()->GetPaintWindow() || bReachBottom || bReachRight ) break; } pReceiver = iterator.next(); } if (bReachBottom) { rc.bottom = rcWindow.top; rc.top = rc.bottom - cyFixed; } if (bReachRight) { rc.right = rcWindow.left; rc.left = rc.right - cxFixed; } if( rc.bottom > rcWork.bottom ) { rc.bottom = rc.top; rc.top = rc.bottom - cyFixed; } if (rc.right > rcWork.right) { rc.right = rcWindow.left; rc.left = rc.right - cxFixed; } if( rc.top < rcWork.top ) { rc.top = rcOwner.top; rc.bottom = rc.top + cyFixed; } if (rc.left < rcWork.left) { rc.left = rcWindow.right; rc.right = rc.left + cxFixed; } MoveWindow(m_hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top + m_pLayout->GetInset().top + m_pLayout->GetInset().bottom, FALSE); } void CMenuWnd::setDPI(int DPI) { m_pm.SetDPI(DPI); } LRESULT CMenuWnd::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { HWND hFocusWnd = (HWND)wParam; BOOL bInMenuWindowList = FALSE; ContextMenuParam param; param.hWnd = GetHWND(); MenuObserverImpl::Iterator iterator(CMenuWnd::GetGlobalContextMenuObserver()); MenuMenuReceiverImplBase* pReceiver = iterator.next(); while( pReceiver != NULL ) { CMenuWnd* pContextMenu = dynamic_cast(pReceiver); if( pContextMenu != NULL && pContextMenu->GetHWND() == hFocusWnd ) { bInMenuWindowList = TRUE; break; } pReceiver = iterator.next(); } if( !bInMenuWindowList ) { param.wParam = 1; CMenuWnd::GetGlobalContextMenuObserver().RBroadcast(param); return 0; } return 0; } LRESULT CMenuWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { SIZE szRoundCorner = m_pm.GetRoundCorner(); if( !::IsIconic(*this) ) { CDuiRect rcWnd; ::GetWindowRect(*this, &rcWnd); rcWnd.Offset(-rcWnd.left, -rcWnd.top); rcWnd.right++; rcWnd.bottom++; HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy); ::SetWindowRgn(*this, hRgn, TRUE); ::DeleteObject(hRgn); } bHandled = FALSE; return 0; } LRESULT CMenuWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = 0; BOOL bHandled = TRUE; switch( uMsg ) { case WM_CREATE: lRes = OnCreate(uMsg, wParam, lParam, bHandled); break; case WM_KILLFOCUS: lRes = OnKillFocus(uMsg, wParam, lParam, bHandled); break; case WM_KEYDOWN: if( wParam == VK_ESCAPE || wParam == VK_LEFT) Close(); break; case WM_SIZE: lRes = OnSize(uMsg, wParam, lParam, bHandled); break; case WM_CLOSE: if( m_pOwner != NULL ) { m_pOwner->SetManager(m_pOwner->GetManager(), m_pOwner->GetParent(), false); m_pOwner->SetPos(m_pOwner->GetPos()); m_pOwner->SetFocus(); } break; case WM_RBUTTONDOWN: case WM_CONTEXTMENU: case WM_RBUTTONUP: case WM_RBUTTONDBLCLK: return 0L; break; default: bHandled = FALSE; break; } if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes; return CWindowWnd::HandleMessage(uMsg, wParam, lParam); } ///////////////////////////////////////////////////////////////////////////////////// // IMPLEMENT_DUICONTROL(CMenuElementUI) CMenuElementUI::CMenuElementUI(): m_pWindow(NULL), m_bDrawLine(false), m_dwLineColor(DEFAULT_LINE_COLOR), m_bCheckItem(false), m_bShowExplandIcon(false) { m_cxyFixed.cy = ITEM_DEFAULT_HEIGHT; m_cxyFixed.cx = ITEM_DEFAULT_WIDTH; m_szIconSize.cy = ITEM_DEFAULT_ICON_SIZE; m_szIconSize.cx = ITEM_DEFAULT_ICON_SIZE; m_rcLinePadding.top = m_rcLinePadding.bottom = 0; m_rcLinePadding.left = DEFAULT_LINE_LEFT_INSET; m_rcLinePadding.right = DEFAULT_LINE_RIGHT_INSET; } CMenuElementUI::~CMenuElementUI() {} LPCTSTR CMenuElementUI::GetClass() const { return _T("MenuElementUI"); } LPVOID CMenuElementUI::GetInterface(LPCTSTR pstrName) { if( _tcsicmp(pstrName, _T("MenuElement")) == 0 ) return static_cast(this); return CListContainerElementUI::GetInterface(pstrName); } bool CMenuElementUI::DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl) { SIZE cxyFixed = GetFixedSize(); RECT rcLinePadding = GetLinePadding(); RECT rcTemp = { 0 }; if( !::IntersectRect(&rcTemp, &rcPaint, &m_rcItem) ) return true; if(m_bDrawLine) { RECT rcLine = { m_rcItem.left + rcLinePadding.left, m_rcItem.top + cxyFixed.cy/2, m_rcItem.right - rcLinePadding.right, m_rcItem.top + cxyFixed.cy/2 }; CRenderEngine::DrawLine(hDC, rcLine, 1, m_dwLineColor); } else { CRenderClip clip; CRenderClip::GenerateClip(hDC, rcTemp, clip); CMenuElementUI::DrawItemBk(hDC, m_rcItem); DrawItemText(hDC, m_rcItem); DrawItemIcon(hDC, m_rcItem); DrawItemExpland(hDC, m_rcItem); if( m_items.GetSize() > 0 ) { RECT rc = m_rcItem; RECT rcInset = GetInset(); rc.left += rcInset.left; rc.top += rcInset.top; rc.right -= rcInset.right; rc.bottom -= rcInset.bottom; if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) rc.right -= m_pVerticalScrollBar->GetFixedWidth(); if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight(); if( !::IntersectRect(&rcTemp, &rcPaint, &rc) ) { for( int it = 0; it < m_items.GetSize(); it++ ) { CControlUI* pControl = static_cast(m_items[it]); if( pControl == pStopControl ) return false; if( !pControl->IsVisible() ) continue; if( pControl->GetInterface(_T("MenuElement")) != NULL ) continue; if( !::IntersectRect(&rcTemp, &rcPaint, &pControl->GetPos()) ) continue; if( pControl->IsFloat() ) { if( !::IntersectRect(&rcTemp, &m_rcItem, &pControl->GetPos()) ) continue; if( !pControl->Paint(hDC, rcPaint, pStopControl) ) return false; } } } else { CRenderClip childClip; CRenderClip::GenerateClip(hDC, rcTemp, childClip); for( int it = 0; it < m_items.GetSize(); it++ ) { CControlUI* pControl = static_cast(m_items[it]); if( pControl == pStopControl ) return false; if( !pControl->IsVisible() ) continue; if( pControl->GetInterface(_T("MenuElement")) != NULL ) continue; if( !::IntersectRect(&rcTemp, &rcPaint, &pControl->GetPos()) ) continue; if( pControl->IsFloat() ) { if( !::IntersectRect(&rcTemp, &m_rcItem, &pControl->GetPos()) ) continue; CRenderClip::UseOldClipBegin(hDC, childClip); if( !pControl->Paint(hDC, rcPaint, pStopControl) ) return false; CRenderClip::UseOldClipEnd(hDC, childClip); } else { if( !::IntersectRect(&rcTemp, &rc, &pControl->GetPos()) ) continue; if( !pControl->Paint(hDC, rcPaint, pStopControl) ) return false; } } } } } if( m_pVerticalScrollBar != NULL ) { if( m_pVerticalScrollBar == pStopControl ) return false; if (m_pVerticalScrollBar->IsVisible()) { if( ::IntersectRect(&rcTemp, &rcPaint, &m_pVerticalScrollBar->GetPos()) ) { if( !m_pVerticalScrollBar->Paint(hDC, rcPaint, pStopControl) ) return false; } } } if( m_pHorizontalScrollBar != NULL ) { if( m_pHorizontalScrollBar == pStopControl ) return false; if (m_pHorizontalScrollBar->IsVisible()) { if( ::IntersectRect(&rcTemp, &rcPaint, &m_pHorizontalScrollBar->GetPos()) ) { if( !m_pHorizontalScrollBar->Paint(hDC, rcPaint, pStopControl) ) return false; } } } return true; } void CMenuElementUI::DrawItemIcon(HDC hDC, const RECT& rcItem) { if (!m_strIcon.IsEmpty() && !(m_bCheckItem && !GetChecked())) { SIZE cxyFixed = GetFixedSize(); SIZE szIconSize = GetIconSize(); TListInfoUI* pInfo = m_pOwner->GetListInfo(); RECT rcTextPadding = GetManager()->GetDPIObj()->Scale(pInfo->rcTextPadding); RECT rcDest = { (rcTextPadding.left - szIconSize.cx) / 2, (cxyFixed.cy - szIconSize.cy) / 2, (rcTextPadding.left - szIconSize.cx) / 2 + szIconSize.cx, (cxyFixed.cy - szIconSize.cy) / 2 + szIconSize.cy }; CDuiString pStrImage; pStrImage.Format(_T("dest='%d,%d,%d,%d'"), rcDest.left, rcDest.top, rcDest.right, rcDest.bottom); DrawImage(hDC, m_strIcon, pStrImage); } } void CMenuElementUI::DrawItemExpland(HDC hDC, const RECT& rcItem) { if (m_bShowExplandIcon) { CDuiString strExplandIcon; strExplandIcon = GetManager()->GetDefaultAttributeList(_T("ExplandIcon")); if (strExplandIcon.IsEmpty()) { return; } SIZE cxyFixed = GetManager()->GetDPIObj()->Scale(m_cxyFixed); int padding = GetManager()->GetDPIObj()->Scale(ITEM_DEFAULT_EXPLAND_ICON_WIDTH) / 3; const TDrawInfo* pDrawInfo = GetManager()->GetDrawInfo((LPCTSTR)strExplandIcon, NULL); const TImageInfo *pImageInfo = GetManager()->GetImageEx(pDrawInfo->sImageName, NULL, 0, false, pDrawInfo->bGdiplus); if (!pImageInfo) { return; } RECT rcDest = { cxyFixed.cx - pImageInfo->nX - padding, (cxyFixed.cy - pImageInfo->nY) / 2, cxyFixed.cx - pImageInfo->nX - padding + pImageInfo->nX, (cxyFixed.cy - pImageInfo->nY) / 2 + pImageInfo->nY }; GetManager()->GetDPIObj()->ScaleBack(&rcDest); CDuiString pStrImage; pStrImage.Format(_T("dest='%d,%d,%d,%d'"), rcDest.left, rcDest.top, rcDest.right, rcDest.bottom); DrawImage(hDC, strExplandIcon, pStrImage); } } void CMenuElementUI::DrawItemText(HDC hDC, const RECT& rcItem) { CDuiString sText = GetText(); if( sText.IsEmpty() ) return; if( m_pOwner == NULL ) return; TListInfoUI* pInfo = m_pOwner->GetListInfo(); DWORD iTextColor = pInfo->dwTextColor; if( (m_uButtonState & UISTATE_HOT) != 0 ) { iTextColor = pInfo->dwHotTextColor; } if( IsSelected() ) { iTextColor = pInfo->dwSelectedTextColor; } if( !IsEnabled() ) { iTextColor = pInfo->dwDisabledTextColor; } int nLinks = 0; RECT rcText = rcItem; RECT rcTextPadding = GetManager()->GetDPIObj()->Scale(pInfo->rcTextPadding); rcText.left += rcTextPadding.left; rcText.right -= rcTextPadding.right; rcText.top += rcTextPadding.top; rcText.bottom -= rcTextPadding.bottom; if( pInfo->bShowHtml ) CRenderEngine::DrawHtmlText(hDC, m_pManager, rcText, sText, iTextColor, \ NULL, NULL, nLinks, pInfo->nFont, DT_SINGLELINE | pInfo->uTextStyle); else CRenderEngine::DrawText(hDC, m_pManager, rcText, sText, iTextColor, \ pInfo->nFont, DT_SINGLELINE | pInfo->uTextStyle); } SIZE CMenuElementUI::EstimateSize(SIZE szAvailable) { SIZE cxyFixed = GetManager()->GetDPIObj()->Scale(m_cxyFixed); SIZE cXY = {0}; for( int it = 0; it < GetCount(); it++ ) { CControlUI* pControl = static_cast(GetItemAt(it)); if( !pControl->IsVisible() ) continue; SIZE sz = pControl->EstimateSize(szAvailable); cXY.cy += sz.cy; if( cXY.cx < sz.cx ) cXY.cx = sz.cx; } if(cXY.cy == 0) { CDuiString sText = GetText(); TListInfoUI* pInfo = m_pOwner->GetListInfo(); DWORD iTextColor = pInfo->dwTextColor; RECT rcText = { 0, 0, MAX(szAvailable.cx, m_cxyFixed.cx), 9999 }; RECT rcTextPadding = GetManager()->GetDPIObj()->Scale(pInfo->rcTextPadding); rcText.left += rcTextPadding.left; rcText.right -= rcTextPadding.right; if( pInfo->bShowHtml ) { int nLinks = 0; CRenderEngine::DrawHtmlText(m_pManager->GetPaintDC(), m_pManager, rcText, sText, iTextColor, NULL, NULL, nLinks, pInfo->nFont, DT_CALCRECT | pInfo->uTextStyle); } else { CRenderEngine::DrawText(m_pManager->GetPaintDC(), m_pManager, rcText, sText, iTextColor, pInfo->nFont, DT_CALCRECT | pInfo->uTextStyle); } cXY.cx = rcText.right - rcText.left + rcTextPadding.left + rcTextPadding.right ; cXY.cy = rcText.bottom - rcText.top + rcTextPadding.top + rcTextPadding.bottom; } if( cxyFixed.cy != 0 ) cXY.cy = cxyFixed.cy; if ( cXY.cx < m_cxyFixed.cx ) cXY.cx = m_cxyFixed.cx; return cXY; } void CMenuElementUI::DoEvent(TEventUI& event) { if( event.Type == UIEVENT_MOUSEENTER ) { CListContainerElementUI::DoEvent(event); if( m_pWindow ) return; bool hasSubMenu = false; for( int i = 0; i < GetCount(); ++i ) { if( GetItemAt(i)->GetInterface(_T("MenuElement")) != NULL ) { (static_cast(GetItemAt(i)->GetInterface(_T("MenuElement"))))->SetVisible(true); (static_cast(GetItemAt(i)->GetInterface(_T("MenuElement"))))->SetInternVisible(true); hasSubMenu = true; } } if( hasSubMenu ) { m_pOwner->SelectItem(GetIndex(), true); CreateMenuWnd(); } else { ContextMenuParam param; param.hWnd = m_pManager->GetPaintWindow(); param.wParam = 2; CMenuWnd::GetGlobalContextMenuObserver().RBroadcast(param); m_pOwner->SelectItem(GetIndex(), true); } return; } if (event.Type == UIEVENT_MOUSELEAVE) { bool hasSubMenu = false; for (int i = 0; i < GetCount(); ++i) { if (GetItemAt(i)->GetInterface(_T("MenuElement")) != NULL) { hasSubMenu = true; } } if (!hasSubMenu) { m_pOwner->SelectItem(-1, true); } } if( event.Type == UIEVENT_BUTTONUP ) { if( IsEnabled() ){ CListContainerElementUI::DoEvent(event); if( m_pWindow ) return; bool hasSubMenu = false; for( int i = 0; i < GetCount(); ++i ) { if( GetItemAt(i)->GetInterface(_T("MenuElement")) != NULL ) { (static_cast(GetItemAt(i)->GetInterface(_T("MenuElement"))))->SetVisible(true); (static_cast(GetItemAt(i)->GetInterface(_T("MenuElement"))))->SetInternVisible(true); hasSubMenu = true; } } if( hasSubMenu ) { CreateMenuWnd(); } else { SetChecked(!GetChecked()); bool isClosing = false; CMenuUI* menuUI=static_cast(GetManager()->GetRoot()); isClosing = (menuUI->m_pWindow->isClosing); if (IsWindow(GetManager()->GetPaintWindow()) && !isClosing) { if (CMenuWnd::GetGlobalContextMenuObserver().GetManager() != NULL) { MenuCmd* pMenuCmd = new MenuCmd(); lstrcpy(pMenuCmd->szName, GetName().GetData()); lstrcpy(pMenuCmd->szUserData, GetUserData().GetData()); lstrcpy(pMenuCmd->szText, GetText().GetData()); pMenuCmd->bChecked = GetChecked(); if (!PostMessage(CMenuWnd::GetGlobalContextMenuObserver().GetManager()->GetPaintWindow(), WM_MENUCLICK, (WPARAM)pMenuCmd, (LPARAM)this)) { delete pMenuCmd; pMenuCmd = NULL; } } } ContextMenuParam param; param.hWnd = m_pManager->GetPaintWindow(); param.wParam = 1; CMenuWnd::GetGlobalContextMenuObserver().RBroadcast(param); } } return; } if ( event.Type == UIEVENT_KEYDOWN && event.chKey == VK_RIGHT ) { if( m_pWindow ) return; bool hasSubMenu = false; for( int i = 0; i < GetCount(); ++i ) { if( GetItemAt(i)->GetInterface(_T("MenuElement")) != NULL ) { (static_cast(GetItemAt(i)->GetInterface(_T("MenuElement"))))->SetVisible(true); (static_cast(GetItemAt(i)->GetInterface(_T("MenuElement"))))->SetInternVisible(true); hasSubMenu = true; } } if( hasSubMenu ) { m_pOwner->SelectItem(GetIndex(), true); CreateMenuWnd(); } else { ContextMenuParam param; param.hWnd = m_pManager->GetPaintWindow(); param.wParam = 2; CMenuWnd::GetGlobalContextMenuObserver().RBroadcast(param); m_pOwner->SelectItem(GetIndex(), true); } return; } CListContainerElementUI::DoEvent(event); } CMenuWnd* CMenuElementUI::GetMenuWnd() { return m_pWindow; } void CMenuElementUI::CreateMenuWnd() { if( m_pWindow ) return; m_pWindow = new CMenuWnd(); ASSERT(m_pWindow); ContextMenuParam param; param.hWnd = m_pManager->GetPaintWindow(); param.wParam = 2; CMenuWnd::GetGlobalContextMenuObserver().RBroadcast(param); m_pWindow->Init(static_cast(this), _T(""), CDuiPoint(), NULL); } void CMenuElementUI::SetLineType() { m_bDrawLine = true; if (m_cxyFixed.cy == 0 || m_cxyFixed.cy == ITEM_DEFAULT_HEIGHT) SetFixedHeight(DEFAULT_LINE_HEIGHT); SetMouseChildEnabled(false); SetMouseEnabled(false); SetEnabled(false); } void CMenuElementUI::SetLineColor(DWORD color) { m_dwLineColor = color; } DWORD CMenuElementUI::GetLineColor() const { return m_dwLineColor; } void CMenuElementUI::SetLinePadding(RECT rcPadding) { m_rcLinePadding = rcPadding; } RECT CMenuElementUI::GetLinePadding() const { RECT rcLinePadding = m_rcLinePadding; if(m_pManager != NULL) m_pManager->GetDPIObj()->Scale(&rcLinePadding); return rcLinePadding; } void CMenuElementUI::SetIcon(LPCTSTR strIcon) { m_strIcon = strIcon; } void CMenuElementUI::SetIconSize(LONG cx, LONG cy) { m_szIconSize.cx = cx; m_szIconSize.cy = cy; } SIZE CMenuElementUI::GetIconSize() { SIZE szIconSize = m_szIconSize; if(m_pManager != NULL) m_pManager->GetDPIObj()->Scale(&szIconSize); return szIconSize; } void CMenuElementUI::SetChecked(bool bCheck/* = true*/) { SetItemInfo(GetName(), bCheck); } bool CMenuElementUI::GetChecked() const { LPCTSTR pstrName = GetName(); if(pstrName == NULL || lstrlen(pstrName) <= 0) return false; CStdStringPtrMap* mCheckInfos = CMenuWnd::GetGlobalContextMenuObserver().GetMenuCheckInfo(); if (mCheckInfos != NULL) { MenuItemInfo* pItemInfo = (MenuItemInfo*)mCheckInfos->Find(pstrName); if(pItemInfo != NULL) { return pItemInfo->bChecked; } } return false; } void CMenuElementUI::SetCheckItem(bool bCheckItem/* = false*/) { m_bCheckItem = bCheckItem; } bool CMenuElementUI::GetCheckItem() const { return m_bCheckItem; } void CMenuElementUI::SetShowExplandIcon(bool bShow) { m_bShowExplandIcon = bShow; } void CMenuElementUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) { if( _tcsicmp(pstrName, _T("icon")) == 0){ SetIcon(pstrValue); } else if( _tcsicmp(pstrName, _T("iconsize")) == 0 ) { LPTSTR pstr = NULL; LONG cx = 0, cy = 0; cx = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr); cy = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr); SetIconSize(cx, cy); } else if( _tcsicmp(pstrName, _T("checkitem")) == 0 ) { SetCheckItem(_tcsicmp(pstrValue, _T("true")) == 0 ? true : false); } else if( _tcsicmp(pstrName, _T("ischeck")) == 0 ) { CStdStringPtrMap* mCheckInfos = CMenuWnd::GetGlobalContextMenuObserver().GetMenuCheckInfo(); if (mCheckInfos != NULL) { bool bFind = false; for(int i = 0; i < mCheckInfos->GetSize(); i++) { MenuItemInfo* itemInfo = (MenuItemInfo*)mCheckInfos->GetAt(i); if(lstrcmpi(itemInfo->szName, GetName()) == 0) { bFind = true; break; } } if(!bFind) SetChecked(_tcsicmp(pstrValue, _T("true")) == 0 ? true : false); } } else if( _tcsicmp(pstrName, _T("linetype")) == 0){ if (_tcsicmp(pstrValue, _T("true")) == 0) SetLineType(); } else if( _tcsicmp(pstrName, _T("expland")) == 0 ) { SetShowExplandIcon(_tcsicmp(pstrValue, _T("true")) == 0 ? true : false); } else if( _tcsicmp(pstrName, _T("linecolor")) == 0){ if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue); LPTSTR pstr = NULL; SetLineColor(_tcstoul(pstrValue, &pstr, 16)); } else if( _tcsicmp(pstrName, _T("linepadding")) == 0 ) { RECT rcInset = { 0 }; LPTSTR pstr = NULL; rcInset.left = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr); rcInset.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr); rcInset.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr); rcInset.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr); SetLinePadding(rcInset); } else if ( _tcsicmp(pstrName, _T("height")) == 0){ SetFixedHeight(_ttoi(pstrValue)); } else CListContainerElementUI::SetAttribute(pstrName, pstrValue); } MenuItemInfo* CMenuElementUI::GetItemInfo(LPCTSTR pstrName) { if(pstrName == NULL || lstrlen(pstrName) <= 0) return NULL; CStdStringPtrMap* mCheckInfos = CMenuWnd::GetGlobalContextMenuObserver().GetMenuCheckInfo(); if (mCheckInfos != NULL) { MenuItemInfo* pItemInfo = (MenuItemInfo*)mCheckInfos->Find(pstrName); if(pItemInfo != NULL) { return pItemInfo; } } return NULL; } MenuItemInfo* CMenuElementUI::SetItemInfo(LPCTSTR pstrName, bool bChecked) { if(pstrName == NULL || lstrlen(pstrName) <= 0) return NULL; CStdStringPtrMap* mCheckInfos = CMenuWnd::GetGlobalContextMenuObserver().GetMenuCheckInfo(); if (mCheckInfos != NULL) { MenuItemInfo* pItemInfo = (MenuItemInfo*)mCheckInfos->Find(pstrName); if(pItemInfo == NULL) { pItemInfo = new MenuItemInfo; lstrcpy(pItemInfo->szName, pstrName); pItemInfo->bChecked = bChecked; mCheckInfos->Insert(pstrName, pItemInfo); } else { pItemInfo->bChecked = bChecked; } return pItemInfo; } return NULL; } } // namespace DuiLib