Files
envi-code/SourceCode/Code2026/EarthWormMain/KTMenuPopup.cpp
T
2026-09-28 15:28:50 +08:00

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