#include "StdAfx.h" #include "..\include\skinmenuitem.h" #include "..\include\Skin.h" #include "..\include\WindowSkin.h" // common resources static CFont _fontHorzMenu, _fontVertMenu; static int _cyHorzFont, _cyMenuOnBar, _cyTextMargin; const int CXTEXTMARGIN = 5; BOOL _InitCommonResources(BOOL bForce) { if (bForce == FALSE && _fontHorzMenu.m_hObject != NULL) return TRUE; _fontHorzMenu.DeleteObject(); _fontVertMenu.DeleteObject(); NONCLIENTMETRICS info; info.cbSize = sizeof(info); ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0); if (!_fontHorzMenu.CreateFontIndirect(&info.lfMenuFont)) return FALSE; info.lfMenuFont.lfEscapement = -900; info.lfMenuFont.lfOrientation = -900; strcpy(info.lfMenuFont.lfFaceName,"verdana"); if (!_fontVertMenu.CreateFontIndirect(&info.lfMenuFont)) return FALSE; // get font height _cyHorzFont = abs(info.lfMenuFont.lfHeight); // calc Y text margin _cyMenuOnBar = info.iMenuHeight; _cyMenuOnBar = max(_cyMenuOnBar, ::GetSystemMetrics(SM_CYSMICON)); _cyTextMargin = (_cyMenuOnBar - _cyHorzFont) / 2; return TRUE; } static int _CalcTextWidth(const CString& strText) { CWindowDC dc(NULL); CRect rcText(0, 0, 0, 0); CFont* pOldFont = dc.SelectObject(&_fontHorzMenu); dc.DrawText(strText, &rcText, DT_SINGLELINE | DT_CALCRECT); dc.SelectObject(pOldFont); return rcText.Width(); } /****************************************** * 函数名 : CMenuItem * 功能 : *******************************************/ CMenuItem::CMenuItem() { m_fsStyle = 0; m_fsState = 0; m_rcItem.SetRectEmpty(); m_sizeHorz = CSize(0, 0); m_cAccessKey = 0; } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuItem::ModifyState(BYTE fsRemove, BYTE fsAdd) { m_fsState = (m_fsState & ~fsRemove) | fsAdd; } /****************************************** * 函数名 : GetHorizontalSize * 功能 : *******************************************/ CSize CMenuItem::GetHorizontalSize() const { if (m_fsState & MISTATE_HIDDEN) return CSize(0, 0); else return m_sizeHorz; } /****************************************** * 函数名 : CMenuButton * 功能 : *******************************************/ CMenuButton::CMenuButton(HMENU hMenu, int nIndex) { ASSERT(::IsMenu(hMenu)); ASSERT(nIndex >= 0); m_fsStyle |= (MISTYLE_TRACKABLE | MISTYLE_WRAPPABLE); InitButtonStringAndSubMenuHandle(hMenu, nIndex); InitHorizontalButtonSize(); InitAccessKeyAndVerticalLinePoint(); } /****************************************** * 函数名 : SetText * 功能 : *******************************************/ void CMenuButton::SetText(TCHAR *szText) { m_strBtn = szText; InitHorizontalButtonSize(); InitAccessKeyAndVerticalLinePoint(); } /****************************************** * 函数名 : InitButtonStringAndSubMenuHandle * 功能 : *******************************************/ void CMenuButton::InitButtonStringAndSubMenuHandle(HMENU hMenu, int nIndex) { // get menu button Text TCHAR szText[256]; MENUITEMINFO info; ::memset(&info, 0, sizeof(MENUITEMINFO)); info.cbSize = sizeof(MENUITEMINFO); info.fMask = MIIM_ID | MIIM_TYPE; info.dwTypeData = szText; info.cch = sizeof(szText); ::GetMenuItemInfo(hMenu, nIndex, TRUE, &info); m_strBtn = CString(szText); m_hSubMenu = ::GetSubMenu(hMenu, nIndex); if (!m_hSubMenu) { m_nID = ::GetMenuItemID(hMenu, nIndex); ASSERT(m_nID != -1); } else { m_nID = -1; } } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuButton::InitHorizontalButtonSize() { // get menu button Text size ASSERT(m_strBtn.IsEmpty() == FALSE); m_sizeHorz.cx = (_CalcTextWidth(m_strBtn) + CXTEXTMARGIN*2)+8; m_sizeHorz.cy = (_cyHorzFont + _cyTextMargin*2)+1; } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuButton::InitAccessKeyAndVerticalLinePoint() { int nIndex = m_strBtn.Find('&'); if (nIndex + 1 == m_strBtn.GetLength()) { TRACE(_T("warning : & is bad position, access key is invalid.\n")); m_cAccessKey = 0; m_ptLineFrom = m_ptLineTo = CPoint(0, 0); return; } m_cAccessKey = m_strBtn[nIndex + 1];// -1 + 1 = 0; it's ok if (nIndex == -1) { m_ptLineFrom = m_ptLineTo = CPoint(0, 0); } else if (nIndex == 0) { m_ptLineFrom = CPoint(_cyTextMargin, CXTEXTMARGIN); m_ptLineTo = CPoint(_cyTextMargin, CXTEXTMARGIN + _CalcTextWidth(m_strBtn.Left(nIndex+2))); } else { m_ptLineFrom = CPoint(_cyTextMargin, CXTEXTMARGIN + _CalcTextWidth(m_strBtn.Left(nIndex))); m_ptLineTo = CPoint(_cyTextMargin, CXTEXTMARGIN + _CalcTextWidth(m_strBtn.Left(nIndex+2))); } } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuButton::Layout(CPoint point, BOOL bHorz) { if (bHorz) m_fsState |= MISTATE_HORZ; else m_fsState &= ~MISTATE_HORZ; if (m_fsState & MISTATE_HIDDEN) { m_rcItem.SetRectEmpty(); return; } if (bHorz) { m_rcItem = CRect(point, m_sizeHorz); } else { m_rcItem = CRect(point, CSize(m_sizeHorz.cy, m_sizeHorz.cx)); } } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuButton::Update(CDC* pDC) { if (m_fsState & MISTATE_HIDDEN) return; if (m_fsState & MISTATE_HOT) DrawHot(pDC); else if (m_fsState & MISTATE_PRESSED) DrawPressed(pDC); else DrawNone(pDC); } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuButton::TrackPopup(CWnd* pBar, CWnd* pWndSentCmd) { // "! menu" (no sub menu) if (!m_hSubMenu) { ASSERT(m_nID != -1); pWndSentCmd->SendMessage(WM_COMMAND, (WPARAM)m_nID, (LPARAM)pBar->GetSafeHwnd()); return; } } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuButton::DrawHorzText(CDC* pDC, CPoint ptOffset) { CWindowSkin *pWin = GetSkin().GetWindowSkin(); COLORREF colorActive,colorInactive; if(pWin) { colorActive = pWin->m_skinMenuBar.colorNormalText; colorInactive = pWin->m_skinMenuBar.colorGrayText; } else { colorActive = ::GetSysColor(COLOR_MENUTEXT); colorInactive = ::GetSysColor(COLOR_GRAYTEXT) ; } COLORREF clr = (m_fsState & MISTATE_INACTIVE) ? colorActive : colorInactive; pDC->SetTextColor(clr); CRect rcBtn = m_rcItem; rcBtn.right-=1; pDC->SetBkMode(TRANSPARENT); CFont* pOldFont = pDC->SelectObject(&_fontHorzMenu); ptOffset.y-=1; ptOffset.x+=2; pDC->DrawText(m_strBtn, rcBtn + ptOffset, DT_SINGLELINE | DT_CENTER | DT_VCENTER); pDC->SelectObject(pOldFont); } /****************************************** * 函数名 : DrawVertText * 功能 : *******************************************/ void CMenuButton::DrawVertText(CDC* pDC, CPoint ptOffset) { CWindowSkin *pWin = GetSkin().GetWindowSkin(); COLORREF colorActive,colorInactive; if(pWin) { colorActive = pWin->m_skinMenuBar.colorNormalText; colorInactive = pWin->m_skinMenuBar.colorGrayText; } else { colorActive = ::GetSysColor(COLOR_MENUTEXT); colorInactive = ::GetSysColor(COLOR_GRAYTEXT) ; } COLORREF clr = (m_fsState & MISTATE_INACTIVE) ? colorActive : colorInactive; pDC->SetTextColor(clr); CRect rcBtn = m_rcItem; int nLength = m_strBtn.GetLength(); int nIndex = m_strBtn.Find('&'); CString strBtn = m_strBtn.Left(nIndex) + m_strBtn.Right(nLength - (nIndex+1)); int iGraphicsMode = ::GetGraphicsMode(pDC->m_hDC); ::SetGraphicsMode(pDC->m_hDC, GM_ADVANCED); pDC->SetBkMode(TRANSPARENT); CFont* pOldFont = pDC->SelectObject(&_fontVertMenu); // I know precise text size CRect rcString = CRect( CPoint(rcBtn.right - _cyTextMargin, rcBtn.top + CXTEXTMARGIN), m_sizeHorz); pDC->DrawText(strBtn, rcString + ptOffset, DT_SINGLELINE | DT_NOCLIP | DT_NOPREFIX);// don't forget DT_NOCLIP pDC->SelectObject(pOldFont); // CDC::DrawText is poor, so we have to draw vertical line by ourselves CPen pen(PS_SOLID, 0, clr); CPen* pOldPen = pDC->SelectObject(&pen); rcBtn.left-=2; pDC->MoveTo(rcBtn.TopLeft() + m_ptLineFrom + ptOffset); pDC->LineTo(rcBtn.TopLeft() + m_ptLineTo + ptOffset); pDC->SelectObject(pOldPen); ::SetGraphicsMode( pDC->m_hDC, iGraphicsMode ); } /****************************************** * 函数名 : DrawButton * 功能 : *******************************************/ void CMenuButton::DrawButton(CDC* pDC,WORD wState) { } /****************************************** * 函数名 : DrawHot * 功能 : *******************************************/ void CMenuButton::DrawHot(CDC* pDC) { CWindowSkin *pWin = GetSkin().GetWindowSkin(); COLORREF colorBack; colorBack = pWin->m_skinMenuBar.colorActive; if (m_fsState & MISTATE_HORZ) { if(!pWin->DrawImageSection(pDC,m_rcItem,pWin->m_skinMenuBar.imageActive)) { pDC->Draw3dRect(m_rcItem,colorBack,colorBack); CBrush brush(colorBack); pDC->FillRect(m_rcItem,&brush); } DrawHorzText(pDC,CPoint(-1, 1)); } else { if(!pWin->DrawImageSection(pDC,m_rcItem,pWin->m_skinMenuBar.imageActive)) { pDC->Draw3dRect(m_rcItem,colorBack,colorBack); CBrush brush(colorBack); pDC->FillRect(m_rcItem,&brush); } DrawVertText(pDC); } } /****************************************** * 函数名 : DrawPressed * 功能 : *******************************************/ void CMenuButton::DrawPressed(CDC* pDC) { CWindowSkin *pWin = GetSkin().GetWindowSkin(); COLORREF colorBack; colorBack = pWin->m_skinMenuBar.colorPressed; if (m_fsState & MISTATE_HORZ) { if(!pWin->DrawImageSection(pDC,m_rcItem,pWin->m_skinMenuBar.imagePressed)) { pDC->Draw3dRect(m_rcItem,colorBack,colorBack); CBrush brush(colorBack); pDC->FillRect(m_rcItem,&brush); } DrawHorzText(pDC, CPoint(-1, 1)); } else { if(!pWin->DrawImageSection(pDC,m_rcItem,pWin->m_skinMenuBar.imagePressed)) { pDC->Draw3dRect(m_rcItem,colorBack,colorBack); CBrush brush(colorBack); pDC->FillRect(m_rcItem,&brush); } DrawVertText(pDC, CPoint(1, 1)); } } /****************************************** * 函数名 : DrawNone * 功能 : *******************************************/ void CMenuButton::DrawNone(CDC* pDC) { if (m_fsState & MISTATE_HORZ) { DrawHorzText(pDC, CPoint(-1, 1)); } else { DrawVertText(pDC, CPoint(1, 1)); } } void CMenuButton::UpdateButtons() { } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ CMenuIcon::CMenuIcon(CSkinMenuBar* pMenuBar) { m_pMenuBar = pMenuBar; m_hIconWinLogo = AfxGetApp()->LoadStandardIcon(IDI_WINLOGO); ASSERT(m_hIconWinLogo); m_fsStyle |= MISTYLE_TRACKABLE; m_fsState |= MISTATE_HIDDEN; m_sizeHorz = CSize(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON)); } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ CMenuIcon::~CMenuIcon() { if (m_hIconWinLogo != NULL) ::FreeResource(m_hIconWinLogo); } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuIcon::OnActivateChildWnd() { //LTRACE(_T("CMenuIcon::OnActivateChildWnd\n")); //CWnd* pFrame = m_pMenuBar->GetTopLevelFrame(); //ASSERT_VALID(pFrame); //CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame); //HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient; //ASSERT(::IsWindow(hWndMDIClient)); //BOOL bMaximized = FALSE; //HWND hWndChild = (HWND)::SendMessage(hWndMDIClient, // WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); //if (bMaximized == FALSE) { // //LTRACE(_T(" not maximized\n")); // m_fsState |= MISTATE_HIDDEN; // m_btnIcon.ShowWindow(SW_HIDE); //} //else { // //LTRACE(_T(" maximized\n")); // m_fsState &= ~MISTATE_HIDDEN; // m_btnIcon.SethIcon(m_hDocIcon); // m_btnIcon.ShowWindow(SW_SHOW); //} //m_hDocIcon = (HICON)::GetClassLong(hWndChild, GCL_HICONSM); //if (m_hDocIcon == NULL) // if hWndChild doesn't have own icon // m_hDocIcon = m_hIconWinLogo; } /****************************************** * 函数名 : Update * 功能 : *******************************************/ void CMenuIcon::Update(CDC* pDC) { if (m_fsState & MISTATE_HIDDEN) return; ASSERT(m_hDocIcon); ASSERT(m_rcItem.IsRectEmpty() == FALSE); ::DrawIconEx(pDC->m_hDC, m_rcItem.left, m_rcItem.top, m_hDocIcon, m_rcItem.Width(), m_rcItem.Height(), 0, NULL, DI_NORMAL); } /****************************************** * 函数名 : UpdateButtons * 功能 : *******************************************/ void CMenuIcon::UpdateButtons() { } /****************************************** * 函数名 : TrackPopup * 功能 : *******************************************/ void CMenuIcon::TrackPopup(CWnd* pBar, CWnd* pWndSentCmd) { /*ASSERT(!(m_fsState & MISTATE_HIDDEN)); ASSERT_VALID(m_pMenuBar); CWnd* pFrame = m_pMenuBar->GetTopLevelFrame(); ASSERT_VALID(pFrame); CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame); HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient; ASSERT(::IsWindow(hWndMDIClient)); BOOL bMaximized = FALSE; HWND hWndChild = (HWND)::SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); ASSERT(bMaximized); HMENU hSysMenu = ::GetSystemMenu(hWndChild, FALSE); ASSERT(::IsMenu(hSysMenu)); CControlBar* pControlBar = STATIC_DOWNCAST(CControlBar, m_pMenuBar); ASSERT_VALID(pControlBar); CRect rcItem(m_rcItem); m_pMenuBar->ClientToScreen(rcItem); UINT fuFlags; TPMPARAMS tpm; bActivSystemMenu=TRUE; CPoint pt = _ComputeMenuTrackPoint(rcItem, pControlBar->GetBarStyle(), fuFlags, tpm); gbintHorz=-1; CRect rcBtn=CRect(0,0,0,0); CRect rcMenu=rcBtn; ::TrackPopupMenuEx(hSysMenu, fuFlags, pt.x, pt.y,m_pMenuBar->GetSafeHwnd(), &tpm); bActivSystemMenu=FALSE;*/ } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuIcon::Layout(CPoint point, BOOL bHorz) { if (bHorz) m_fsState |= MISTATE_HORZ; else m_fsState &= ~MISTATE_HORZ; if (m_fsState & MISTATE_HIDDEN) { m_rcItem.SetRectEmpty(); return; } m_rcItem = CRect(point, CSize(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON))); } //****************************************************************** ////////////////////////////////////////////////////////////////////// // CMenuControl class #define CX_GAP_CAPTION 2 /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ CMenuControl::CMenuControl(CWnd* pMenuBar) { /*ASSERT_VALID(pMenuBar); m_pMenuBar = pMenuBar;*/ m_bDown = FALSE; m_nTracking = -1; m_fsState |= MISTATE_HIDDEN; // m_sizeHorz = CSize(sizeCaption.cx*3 + CX_GAP_CAPTION + 1, sizeCaption.cy + 2); } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuControl::SetColorButton(COLORREF clrBtn) { } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuControl::Update(CDC* pDC) { // do nothing } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuControl::UpdateButtons() { } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuControl::Layout(CPoint point, BOOL bHorz) { //LTRACE(_T("CMenuControl::Layout bHorz:%d\n"), bHorz); if (bHorz) m_fsState |= MISTATE_HORZ; else m_fsState &= ~MISTATE_HORZ; if (m_fsState & MISTATE_HIDDEN) { m_rcItem.SetRectEmpty(); return; } // just layout easily if (bHorz) { m_rcItem = CRect(point, m_sizeHorz); } else { m_rcItem = CRect(point, CSize(m_sizeHorz.cy, m_sizeHorz.cx)); } } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuControl::DelayLayoutAndDraw(CDC* pDC, CSize sizeBar,BOOL bFlota) { CSize sizeCaption = GetCaptionSize(); int cxCaption = sizeCaption.cx; int cyCaption = sizeCaption.cy; if (m_fsState & MISTATE_HORZ) { CRect rcCaption; rcCaption.right = !bFlota?sizeBar.cx-5:sizeBar.cx; rcCaption.bottom = sizeBar.cy-3; rcCaption.left = rcCaption.right - cxCaption; rcCaption.top = (rcCaption.bottom - cyCaption); m_arrCaption[0] = rcCaption; rcCaption -= CPoint(cxCaption+CX_GAP_CAPTION, 0); m_arrCaption[1] = rcCaption; rcCaption -= CPoint(cxCaption, 0); m_arrCaption[2] = rcCaption; m_rcItem = CRect(m_arrCaption[2].left, m_arrCaption[2].top, m_arrCaption[0].right, m_arrCaption[0].bottom); } else { CRect rcCaption; rcCaption.left = 0; rcCaption.bottom = sizeBar.cy-5; rcCaption.right = rcCaption.left + cxCaption; rcCaption.top = rcCaption.bottom - cyCaption; m_arrCaption[0] = rcCaption; rcCaption -= CPoint(0, cyCaption+CX_GAP_CAPTION); m_arrCaption[1] = rcCaption; rcCaption -= CPoint(0, cyCaption); m_arrCaption[2] = rcCaption; m_rcItem = CRect(m_arrCaption[2].left, m_arrCaption[2].top, m_arrCaption[0].right, m_arrCaption[0].bottom); } if (m_fsState & MISTATE_HIDDEN) { //LTRACE(_T(" hidden\n")); return; } // draw frame controls DrawControl(); } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuControl::DrawControl() { /*CWnd* pFrame = m_pMenuBar->GetTopLevelFrame(); ASSERT_VALID(pFrame); CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame); HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient; ASSERT(::IsWindow(hWndMDIClient)); BOOL bMaximized = FALSE; HWND hWndChild = (HWND)::SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);*/ } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ void CMenuControl::OnActivateChildWnd() { //LTRACE(_T("CMenuControl::OnActivateChildWnd\n")); // ASSERT_VALID(m_pMenuBar); // CWnd* pFrame = m_pMenuBar->GetTopLevelFrame(); /*ASSERT_VALID(pFrame); CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame); HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient; ASSERT(::IsWindow(hWndMDIClient)); BOOL bMaximized = FALSE; HWND hWndChild = (HWND)::SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); if (bMaximized == FALSE) { m_fsState |= MISTATE_HIDDEN; } else { m_fsState &= ~MISTATE_HIDDEN; }*/ } /****************************************** * 函数名 : ModifyState * 功能 : *******************************************/ CSize CMenuControl::GetCaptionSize() { NONCLIENTMETRICS info; info.cbSize = sizeof(info); ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0); // due to my own feeling return CSize(info.iMenuHeight - info.iBorderWidth*2, info.iMenuHeight - info.iBorderWidth*4); }