#include "StdAfx.h" #include "KTMenuPopup.h" #include "KTMenuCtrl.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #define KTICON_GAP 2 IMPLEMENT_SERIAL(KTMenuItem, CObject,0) UINT KTMenuPopup::m_nLastID = KTMENU_ITEM_STARTID; BOOL KTMenuItem::TrackPopupMenu(UINT nFlags, int iX, int iY, CWnd* pWnd) { if (!IsPopupItem()) return FALSE; UINT nStartId = KTMENU_ITEM_STARTID; if (m_pPopup->OnCreateMenu(nStartId) == NULL) return FALSE; return m_pPopup->m_menuPopup.TrackPopupMenu(nFlags, iX, iY, pWnd); } BOOL KTMenuItem::GetStatusProc(CString& sStatus) { sStatus = (m_sStatus.Find(_T('=')) == 1 ? m_sStatus.Mid(2) : m_sStatus); sStatus.TrimLeft(); return TRUE; } BOOL KTMenuItem::GetToolBarState(BOOL& bShow, UINT& nDockType, CPoint& ptPos, UINT& nRow) { // 显示状态:TRUE--显示,FALSE--隐藏 bShow = FALSE; // 停靠类型:0--浮动,1--上边,2--下边,3--左边,4--右边 nDockType = 0; // 浮动位置 ptPos.x = 100; ptPos.y = 100; // 显示行数 nRow = 1; if (!IsToolBarItem()) return FALSE; CString sState; GetStatusProc(sState); bShow = _ttoi(sState); int iFind = sState.Find(_T(',')) + 1; if (iFind < 1) return TRUE; sState = sState.Mid(iFind); sState.TrimLeft(); nDockType = _ttoi(sState); iFind = sState.Find(_T(',')) + 1; if (iFind < 1) return TRUE; sState = sState.Mid(iFind); sState.TrimLeft(); ptPos.x = _ttoi(sState); iFind = sState.Find(_T(',')) + 1; if (iFind < 1) return TRUE; sState = sState.Mid(iFind); sState.TrimLeft(); ptPos.y = _ttoi(sState); iFind = sState.Find(_T(',')) + 1; if (iFind < 1) return TRUE; sState = sState.Mid(iFind); sState.TrimLeft(); nRow = _ttoi(sState); return TRUE; } void KTMenuItem::GetToolBarState(CString& sState, BOOL bShow, UINT nDockType, CPoint ptPos, UINT nRow) { if (nDockType != 0) sState.Format(_T("%d, %d, %d, %d"), bShow, nDockType, ptPos.x, ptPos.y); else sState.Format(_T("%d, %d, %d, %d, %d"), bShow, nDockType, ptPos.x, ptPos.y, nRow); } BOOL KTMenuItem::GetCtrlName(CString& sCtrl) { int iFind = m_sAction.Find(_T(',')); if (iFind >= 0) { sCtrl = m_sAction.Left(iFind); sCtrl.TrimRight(); } else { sCtrl = m_sAction; } return TRUE; } CSize KTMenuItem::GetCtrlSize() { CSize sz(60, 60); int iFind = m_sAction.Find(_T(',')) + 1; if (iFind > 0) { CString sSize = m_sAction.Mid(iFind); sSize.TrimLeft(); sz.cx = _ttoi(sSize); if (sz.cx <= 0) sz.cx = 60; if ((iFind = sSize.Find(_T(',')) + 1) > 0) { sSize = sSize.Mid(iFind); sSize.TrimLeft(); sz.cy = _ttoi(sSize); if (sz.cy <= 0) sz.cy = 60; } } return sz; } CString KTMenuItem::GetBareText() { if (m_sAccel.IsEmpty()) return m_sText; int iFind = m_sText.ReverseFind(_T('\t')); if (iFind >= 0) return m_sText.Left(iFind); return m_sText; } BOOL KTMenuItem::GetAccelerator() { int iFind = m_sText.ReverseFind(_T('\t')); if (iFind < 0) return FALSE; m_sAccel = m_sText.Mid(iFind + 1); m_sAccel.TrimLeft(); if (m_sAccel.IsEmpty()) return FALSE; return FALSE;//KTMenuAccel::GetAccelerator(m_sAccel, m_accel); } IMPLEMENT_SERIAL(KTMenuPopup, KTMenuBase,0) KTMenuPopup::KTMenuPopup() : m_pParent(NULL), m_pMenuCtrl(NULL) { } KTMenuPopup::~KTMenuPopup() { Clean(); } void KTMenuPopup::Clean() { int iSize = (int)m_arpItem.GetSize(); for (int i = 0; i < iSize; i++) { KTMenuItem* pItem = (KTMenuItem*)m_arpItem.GetAt(i); ASSERT(pItem != NULL); delete pItem; } m_arpItem.RemoveAll(); } void KTMenuPopup::Serialize(CArchive& ar) { if (ar.IsStoring()) { ar << m_sName; int iSize = (int)m_arpItem.GetSize(); ar << iSize; for (int i = 0; i < iSize; i++) { KTMenuItem* pItem = (KTMenuItem*)m_arpItem.GetAt(i); ASSERT(pItem != NULL); ar << pItem->m_sResource; ar << pItem->m_sText; ar << pItem->m_sStatus; ar << pItem->m_sAction; BOOL bPopup = pItem->IsPopupItem(); ar << bPopup; if (bPopup) { pItem->m_pPopup->Serialize(ar); } } } else { ar >> m_sName; int iSize; ar >> iSize; for (int i = 0; i < iSize; i++) { KTMenuItem* pItem = new KTMenuItem; ASSERT(pItem != NULL); pItem->m_pParent = this; m_arpItem.Add(pItem); ar >> pItem->m_sResource; ar >> pItem->m_sText; ar >> pItem->m_sStatus; ar >> pItem->m_sAction; pItem->GetAccelerator(); BOOL bPopup; ar >> bPopup; if (bPopup) { pItem->m_pPopup = new KTMenuPopup; ASSERT(pItem->m_pPopup != NULL); pItem->m_pPopup->m_pParent = this; pItem->m_pPopup->Serialize(ar); } } } } KTMenuBase* KTMenuPopup::CreateItem(CString& sLine) { return CreateItem(sLine, NULL); } KTMenuBase* KTMenuPopup::CreateItem(CString& sLine, LPCTSTR pszName) { int iFind1 = sLine.Find(_T('[')); if (iFind1 < 0) return NULL; int iFind2 = sLine.ReverseFind(_T(']')); if (iFind2 < 0) return NULL; KTMenuItem* pItem = new KTMenuItem; ASSERT(pItem != NULL); pItem->m_pParent = this; m_arpItem.Add(pItem); pItem->m_sResource = sLine.Left(iFind1); pItem->m_sResource.TrimRight(); iFind1++; pItem->m_sText = sLine.Mid(iFind1, iFind2 - iFind1); pItem->m_sText.Replace(_T("\\t"), _T("\t")); iFind2++; pItem->m_sAction = sLine.Mid(iFind2); pItem->m_sAction.TrimLeft(); pItem->m_sAction.TrimRight(); KTMenuPopup* pRet = this; if (pszName != NULL) { pItem->m_pPopup = new KTMenuPopup; ASSERT(pItem->m_pPopup != NULL); pItem->m_pPopup->m_sName = pszName; pItem->m_pPopup->m_pParent = this; pRet = pItem->m_pPopup; } else if (pItem->m_sText.Find(_T("<>")) == 0) { pItem->m_sText.Delete(0, 2); pItem->m_pPopup = new KTMenuPopup; ASSERT(pItem->m_pPopup != NULL); pItem->m_pPopup->m_pParent = this; } else if (pItem->m_sText.Find(_T("->")) == 0) { pItem->m_sText.Delete(0, 2); pItem->m_pPopup = new KTMenuPopup; ASSERT(pItem->m_pPopup != NULL); pItem->m_pPopup->m_pParent = this; pRet = pItem->m_pPopup; } else if ((iFind1 = pItem->m_sText.Find(_T("<-"))) == 0) { while (iFind1 == 0) { pItem->m_sText.Delete(0, 2); if (pRet != NULL) pRet = pRet->m_pParent; iFind1 = pItem->m_sText.Find(_T("<-")); } } iFind1 = pItem->m_sText.Find(_T('{')) + 1; iFind2 = pItem->m_sText.Find(_T('}'), iFind1); if (iFind1 == 1 && iFind2 > 0) { pItem->m_sStatus = pItem->m_sText.Mid(iFind1, iFind2 - iFind1); pItem->m_sStatus.TrimLeft(); pItem->m_sStatus.TrimRight(); pItem->m_sText.Delete(0, iFind2 + 1); } pItem->GetAccelerator(); return pRet; } KTMenuCtrl* KTMenuPopup::GetMenuCtrl() { if (m_pParent == NULL) return m_pMenuCtrl; else return m_pParent->GetMenuCtrl(); } void KTMenuPopup::OnUpdateCmdID(HMENU hMenu) { ASSERT(hMenu != NULL); UINT& nCmdID = KTMENU_ITEM_LASTID; MENUITEMINFO info = {sizeof(MENUITEMINFO), MIIM_ID, 0}; int iCount = ::GetMenuItemCount(hMenu); for (int i = 0; i < iCount; i++) { switch (::GetMenuItemID(hMenu, i)) { case 0: break; case -1: OnUpdateCmdID(::GetSubMenu(hMenu, i)); break; default: ::GetMenuItemInfo(hMenu, i, TRUE, &info); info.wID = nCmdID++; ::SetMenuItemInfo(hMenu, i, TRUE, &info); break; } } } const CMenu* KTMenuPopup::OnCreateMenu(UINT& nStartId) { // 菜单已经存在,修改菜单ID if (m_menuPopup.GetSafeHmenu() != NULL) { OnUpdateCmdID(m_menuPopup.m_hMenu); return &m_menuPopup; } // 菜单不存在,创建菜单 if (!m_menuPopup.CreatePopupMenu()) return NULL; int iSize = (int)m_arpItem.GetSize(); for (int i = 0; i < iSize; i++) { KTMenuItem* pItem = (KTMenuItem*)m_arpItem.GetAt(i); ASSERT(pItem != NULL); BOOL bAppend = FALSE; if (pItem->IsPopupItem()) { HMENU hSub = pItem->m_pPopup->OnCreateMenu(nStartId)->GetSafeHmenu(); if (hSub != NULL) #ifdef KTMENU_OWNERDRAW bAppend = m_menuPopup.AppendMenu(MF_POPUP | MF_OWNERDRAW, (UINT)hSub, (LPCTSTR)pItem); #else bAppend = m_menuPopup.AppendMenu(MF_POPUP, (UINT)hSub, pItem->m_sText); #endif // KTMENU_OWNERDRAW } else { if (pItem->IsSeparator()) bAppend = m_menuPopup.AppendMenu(MF_SEPARATOR); else #ifdef KTMENU_OWNERDRAW bAppend = m_menuPopup.AppendMenu(MF_STRING | MF_OWNERDRAW, nStartId++, (LPCTSTR)pItem); #else bAppend = m_menuPopup.AppendMenu(MF_STRING, nStartId++, pItem->m_sText); #endif // KTMENU_OWNERDRAW ASSERT(nStartId <= KTMENU_ITEM_ENDID); } if (bAppend) { MENUITEMINFO info; info.cbSize = sizeof (MENUITEMINFO); info.fMask = MIIM_DATA; info.dwItemData = (DWORD_PTR)pItem; ::SetMenuItemInfo(m_menuPopup.m_hMenu, m_menuPopup.GetMenuItemCount() - 1, TRUE, &info); } } return &m_menuPopup; } #ifdef KTMENU_OWNERDRAW void KTMenuPopup::KTMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { ASSERT(lpDrawItemStruct->CtlType == ODT_MENU); KTMenuItem* pItem = (KTMenuItem*)lpDrawItemStruct->itemData; ASSERT(pItem != NULL); BOOL bCheck = (lpDrawItemStruct->itemState & ODS_CHECKED); BOOL bSelect = (lpDrawItemStruct->itemState & ODS_SELECTED); BOOL bDisable = FALSE; // ligend //(lpDrawItemStruct->itemState & ODS_GRAYED); CRect rcItem(lpDrawItemStruct->rcItem); CRect rcIcon(rcItem.left + KTICON_GAP, rcItem.top + KTICON_GAP, rcItem.left + KTICON_GAP + KTICON_SIZE_X, rcItem.bottom); CRect rcText(rcIcon.right + KTICON_GAP, rcItem.top, rcItem.right, rcItem.bottom); CRect* pRcFill = &rcItem; CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); if (bCheck) { HBITMAP hBmp = LoadBitmap (NULL, MAKEINTRESOURCE(32760)); if (hBmp != NULL) { pRcFill = &rcText; pDC->DrawState(CPoint(rcIcon.left, rcIcon.top + 3), CSize(rcIcon.Size()), hBmp, (bDisable ? DSS_DISABLED : DSS_NORMAL), (HBRUSH)NULL); DeleteObject (hBmp); } } else if (pItem->m_pParent != NULL) { KTMenuCtrl* pMenuCtrl = pItem->m_pParent->GetMenuCtrl(); ASSERT(pMenuCtrl != NULL); HBITMAP hBmp = pMenuCtrl->GetResourceIcon(pItem->m_sResource); if (hBmp != NULL) { pRcFill = &rcText; CImageList imglst; imglst.Create(KTICON_SIZE_X, KTICON_SIZE_Y, ILC_COLOR16|ILC_MASK, 1, 0); ImageList_AddMasked(imglst.m_hImageList, hBmp, KTICON_BKCOLOR); DeleteObject(hBmp); HICON hIcon = imglst.ExtractIcon(0); pDC->DrawState(CPoint(rcIcon.left, rcIcon.top), CSize(rcIcon.Size()), hIcon, (bDisable ? DSS_DISABLED : DSS_NORMAL), (HBRUSH)NULL); DestroyIcon (hIcon); } } pDC->FillSolidRect(pRcFill, ::GetSysColor(bSelect ? COLOR_HIGHLIGHT : COLOR_MENU)); pDC->SetTextColor(::GetSysColor(bDisable ? COLOR_GRAYTEXT : (bSelect ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT))); if (!pItem->m_sText.IsEmpty()) { rcText.left += KTICON_GAP; pDC->DrawText(pItem->GetBareText(), rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE); if (!pItem->m_sAccel.IsEmpty()) { rcText.right -= KTICON_SIZE_X; pDC->DrawText(pItem->m_sAccel, rcText, DT_RIGHT | DT_VCENTER | DT_SINGLELINE); //最右侧绘制 视频帮助 和 文字帮助 按钮, 如果有 } } } void KTMenuPopup::KTMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { ASSERT(lpMeasureItemStruct->CtlType == ODT_MENU); KTMenuItem* pItem = (KTMenuItem*)lpMeasureItemStruct->itemData; ASSERT(pItem != NULL); SIZE sz; if (pItem->m_sText.IsEmpty()) { sz.cx = -::GetSystemMetrics(SM_CXMENUCHECK); } else { CMDIFrameWnd* pFrame = acedGetAcadFrame(); CDC* pDC = pFrame->GetDC(); #if ARX>15 CFont* pFont = pDC->SelectObject(pFrame->GetMessageBar()->GetFont()); #else NONCLIENTMETRICS nm; nm.cbSize = sizeof (NONCLIENTMETRICS); VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize, &nm, 0)); CFont fontMenu; fontMenu.CreateFontIndirect(&nm.lfMenuFont); CFont* pFont = pDC->SelectObject(&fontMenu); #endif // ARX>15 sz = pDC->GetTextExtent(pItem->m_sText); pDC->SelectObject (pFont); pFrame->ReleaseDC(pDC); sz.cx += KTICON_GAP; if (pItem->m_sText.Find(_T('\t')) >= 0) sz.cx += KTICON_SIZE_X; } lpMeasureItemStruct->itemWidth = KTICON_SIZE_X + KTICON_GAP + KTICON_GAP + sz.cx; sz.cy = GetSystemMetrics(SM_CYMENU); lpMeasureItemStruct->itemHeight = max(sz.cy, KTICON_SIZE_Y + KTICON_GAP + KTICON_GAP); } #endif // KTMENU_OWNERDRAW