527 lines
12 KiB
C++
527 lines
12 KiB
C++
#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
|