Files
envi-code/SourceCode/Code2026/EarthWormMain/KTMenuCtrl.cpp
T

1417 lines
32 KiB
C++
Raw Normal View History

2026-09-28 15:28:50 +08:00
#include "StdAfx.h"
#include "Resource.h"
#include "AfxPriv.h"
#include "KTMenuCtrl.h"
#include "CAcadApplication.h"
#include "CAcadMenuBar.h"
#include "CAcadMenuGroup.h"
#include "CAcadMenuGroups.h"
#include "CAcadPopupMenu.h"
#include "CAcadPopupMenus.h"
#include "tools.h"
#include "PlayGifDlg.h"
#include "wingdi.h"
#include "CoreTools.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define POP_ICON 12
#define KTICON_GAP 2
#define ICON_SZ 16
#define ODS_EXPAND 0x0001
#define ODS_T_EDGE 0x0002
#define ODS_B_EDGE 0x0004
#define DRAW_ITEM(iIndex, nState) \
if (iIndex >= 0 && iIndex < m_arpItems.GetSize()) \
{ \
ASSERT(iIndex >= 0 && iIndex < m_arpItems.GetSize()); \
UINT nSub, nFlag; \
nFlag = GetItemState(iIndex, &nSub); \
KTMenuCmdUI state(this, iIndex); \
state.DoUpdate(this, FALSE); \
CRect rc; \
GetItemRect(iIndex, rc); \
CClientDC dc(this); \
DRAWITEMSTRUCT di = {ODT_BUTTON, 0, 0, 0, nState | state.m_nState, \
(HWND)MAKELPARAM(nSub, nFlag), \
dc.m_hDC, {rc.left, rc.top, rc.right, rc.bottom}, \
(DWORD_PTR)m_arpItems[iIndex]}; \
SendMessage(WM_DRAWITEM, 0, (LPARAM)&di); \
} \
class KTMenuCmdUI : public CCmdUI
{
public:
KTMenuCmdUI(KTMenuCtrl* pCtrl, int iIndex, CMenu* pMenu = NULL) : m_nState(ODS_DISABLED|ODS_GRAYED)
{
m_pMenu = pMenu;
m_pOther = pCtrl;
m_nID = m_nIndex = iIndex;
}
virtual void Enable(BOOL bOn = TRUE)
{
if (bOn)
m_nState &= ~(ODS_DISABLED|ODS_GRAYED);
else
m_nState |= (ODS_DISABLED|ODS_GRAYED);
}
virtual void SetCheck(int nCheck = 1)
{
if (nCheck)
m_nState |= ODS_CHECKED;
else
m_nState &= ~ODS_CHECKED;
}
virtual void SetRadio(BOOL bOn = TRUE)
{
SetCheck(bOn);
}
virtual void SetText(LPCTSTR lpszText)
{
}
UINT m_nState;
};
IMPLEMENT_DYNAMIC(KTMenuCtrl, CWnd);
KTMenuCtrl::KTMenuCtrl()
: m_bLDown(FALSE), m_iCurSel(-1), m_iOffset(0), m_iHeight(0), m_pMenu(NULL), m_pTrack(NULL)
{
m_mnScreen.m_pMenuCtrl = this;
}
KTMenuCtrl::~KTMenuCtrl()
{
if (m_hResource != NULL)
{
FreeLibrary(m_hResource);
}
}
BEGIN_MESSAGE_MAP(KTMenuCtrl, CWnd)
//{{AFX_MSG_MAP(KTMenuCtrl)
ON_WM_SIZE()
ON_WM_PAINT()
ON_WM_MENUSELECT()
ON_WM_CAPTURECHANGED()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_MOUSEWHEEL()
ON_WM_MEASUREITEM()
ON_WM_DRAWITEM()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
long KTMenuCtrl::LoadMenu(LPCTSTR pszFile,LPCTSTR pszTitle,int nIndex)
{
ASSERT(pszFile != NULL);
CStdioFile file;
if (!file.Open(pszFile, CFile::modeRead))
return -1l;
long lCurLine = 0l;
KTMenuBase* pCurBase = NULL;
int iFind;
CString sLine;
CString sPopup;
BOOL bRem = FALSE;
BOOL bOther = FALSE;
while (file.ReadString(sLine))
{
lCurLine++;
sLine.Replace(_T('\t'), _T(' '));
sLine.TrimLeft();
iFind = sLine.Find(_T("//"));
if (iFind >= 0)
sLine = sLine.Left(iFind);
if ((iFind = sLine.Find(_T("//"))) == 0)
{
// 注释行跳过
continue;
}
else if ((iFind = sLine.Find(_T("/*"))) == 0)
{
// 注释行开始
bRem = TRUE;
continue;
}
else if ((iFind = sLine.Find(_T("*/"))) >= 0)
{
// 注释行结束
bRem = FALSE;
continue;
}
else if (bRem || bOther || sLine.IsEmpty())
{
// 注释行,空行或其它类别跳过
continue;
}
else if ((iFind = sLine.Find(_T("***"))) == 0)
{
// 大类
bOther = FALSE;
if ((iFind = sLine.Find(_T("SCREEN"), 3)) == 3)
{
// 菜单没有定义名称
sPopup = sLine.Mid(iFind);
sPopup.TrimRight();
if (sPopup.IsEmpty())
{
return lCurLine;
}
pCurBase = NULL;
}
else if ((iFind = sLine.Find(_T("RESOURCE"), 3)) == 3)
{
pCurBase = &m_mnRrc;
}
else
{
// 未知的类别
bOther = TRUE;
pCurBase = NULL;
}
}
else if (pCurBase == NULL && !sPopup.IsEmpty())
{
pCurBase = m_mnScreen.CreateItem(sLine, sPopup);
sPopup.Empty();
// 菜单资源无效
if (pCurBase == NULL)
{
return lCurLine;
}
}
else
{
// 菜单类别没有定义
if (pCurBase == NULL)
{
return lCurLine;
}
// 创建类别项
pCurBase = pCurBase->CreateItem(sLine);
// 菜单资源无效
if (pCurBase == NULL)
{
return lCurLine;
}
}
}
// 关闭文档
file.Close();
CString sResFile(pszFile);
sResFile.Delete(sResFile.GetLength()-3, 3);
sResFile += _T("dll");
if (_taccess(sResFile, 0x00) != 0x00)
{
sResFile = FilePath::GetSysDir() + _T("\\env-menu.dll");
}
m_hResource = LoadLibrary(sResFile);
ASSERT(m_hResource != NULL);
CBitmap bmp;
bmp.Attach(::LoadBitmap(_hdllInstance, MAKEINTRESOURCE(IDB_MENUSTATE)));
m_imglstIcon.Create(POP_ICON, POP_ICON, ILC_COLOR24|ILC_MASK, 0, 0);
m_imglstIcon.Add(&bmp, RGB(255, 0, 255));
CBitmap bmp2;
bmp2.Attach(::LoadBitmap(_hdllInstance, MAKEINTRESOURCE(IDB_BITMAPHELP)));
m_imgHelpIcon.Create(ICON_SZ, ICON_SZ, ILC_COLOR24 | ILC_MASK, 0, 0);
m_imgHelpIcon.Add(&bmp2, RGB(255, 0, 255));
if (m_mnScreen.m_arpItem.GetSize() > 0)
{
KTMenuItem* pItem = (KTMenuItem*)m_mnScreen.m_arpItem[0];
if (pItem->IsPopupItem())
SetMenu(pItem->m_pPopup);
}
//AddAutoCADMenu(pszTitle,nIndex);
return 1;
}
bool KTMenuCtrl::AddAutoCADSubMenu(KTMenuItem* pSubItem,CAcadPopupMenu* pIPopUpMenuSub,int j)
{
CString sCmdStr,sBarText,sSubBarText;
VARIANT index,indexSub;
sSubBarText = pSubItem->GetBareText();
VariantInit(&indexSub);
V_VT(&indexSub) = VT_I4;
V_I4(&indexSub) = j+1;
LPDISPATCH pDistSubSub = pIPopUpMenuSub->AddSubMenu(indexSub,sSubBarText);
CAcadPopupMenu IPopUpMenuSubSub(pDistSubSub);
KTMenuPopup* pSubPopup = pSubItem->m_pPopup;
for (int k = 0;k < pSubPopup->m_arpItem.GetSize();k++)
{
KTMenuItem* pSubSubItem = (KTMenuItem*)pSubPopup->m_arpItem[k];
if (pSubSubItem->IsSeparator())
{
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = j+1+k+1;
IPopUpMenuSubSub.AddSeparator(index);
continue;
}
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = j+1+k+1;
sCmdStr = pSubSubItem->m_sAction;
if (!sCmdStr.IsEmpty())
{
sCmdStr += _T("\n");
sBarText = pSubSubItem->GetBareText();
IPopUpMenuSubSub.AddMenuItem(index, sBarText, sCmdStr);
}
}
return true;
}
void KTMenuCtrl::AddAutoCADMenu(LPCTSTR pszTitle,int nPos)
{
//备注,只支持到二次菜单!!!
CAcadApplication IAcad(acedGetAcadWinApp()->GetIDispatch(TRUE));
CAcadMenuBar IMenuBar(IAcad.get_MenuBar());
long numberOfMenus;
numberOfMenus = IMenuBar.get_Count();
CAcadMenuGroups IMenuGroups(IAcad.get_MenuGroups());
VARIANT index;
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = 0;
/*if (acrxAppIsLoaded(_T("EarthWorm.arx")))
{
V_I4(&index) = nPos;
}*/
long lCount = IMenuGroups.get_Count();
CAcadMenuGroup IMenuGroup(IMenuGroups.Item(index));
CAcadPopupMenus IPopUpMenus(IMenuGroup.get_Menus());
CString cstrMenuName = pszTitle;//_T("管廊设计(&Q)");
VariantInit(&index);
V_VT(&index) = VT_BSTR;
V_BSTR(&index) = cstrMenuName.AllocSysString();
IDispatch* pDisp=NULL;
//see if the menu is already there
TRY{pDisp = IPopUpMenus.Item(index); pDisp->AddRef();} CATCH(COleDispatchException,e){}END_CATCH;
if (pDisp==NULL)
{
//create it
CAcadPopupMenu IPopUpMenu(IPopUpMenus.Add(cstrMenuName));
CString sCmdStr,sBarText,sSubBarText;
for (int i = 0;i < m_arpItems.GetSize();i++)
{
KTMenuItem* pItem = (KTMenuItem*)m_arpItems[i];
if (pItem->IsPopupItem() )
{
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = i+1;
sBarText = pItem->GetBareText();
LPDISPATCH pDistSub = IPopUpMenu.AddSubMenu(index,sBarText);
CAcadPopupMenu IPopUpMenuSub(pDistSub);
//提取下级菜单
KTMenuPopup* pPopup = pItem->m_pPopup;
for (int j = 0;j < pPopup->m_arpItem.GetSize();j++)
{
KTMenuItem* pSubItem = (KTMenuItem*)pPopup->m_arpItem[j];
if (pSubItem->IsPopupItem())//嵌套,可以提取出子函数,嵌套处理
{
AddAutoCADSubMenu(pSubItem,&IPopUpMenuSub,j);
}
else
{
if (pSubItem->IsSeparator())
{
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = i+1+j+1;
IPopUpMenuSub.AddSeparator(index);
continue;
}
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = i+1+j+1;
sCmdStr = pSubItem->m_sAction;
if (!sCmdStr.IsEmpty())
{
sCmdStr += _T("\n");
sBarText = pSubItem->GetBareText();
IPopUpMenuSub.AddMenuItem(index, sBarText, sCmdStr);
}
}
}
}
else if(pItem->IsSeparator())
{
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = i+1;
IPopUpMenu.AddSeparator(index);
}
else
{
if( !pItem->m_sAction.IsEmpty() &&
!pItem->m_sText.IsEmpty())
{
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = i+1;
sCmdStr = pItem->m_sAction;
if (!sCmdStr.IsEmpty())
{
sCmdStr += _T("\n");
sBarText = pItem->GetBareText();
IPopUpMenu.AddMenuItem(index, sBarText, sCmdStr);
}
}
}
}
pDisp = IPopUpMenu.m_lpDispatch;
pDisp->AddRef();
}
if (pDisp != NULL)
{
CAcadPopupMenu IPopUpMenu(pDisp);
if (!IPopUpMenu.get_OnMenuBar())
{
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = numberOfMenus - 2;
IPopUpMenu.InsertInMenuBar(index);
}
else
{
VariantInit(&index);
V_VT(&index) = VT_BSTR;
V_BSTR(&index) = cstrMenuName.AllocSysString();
IPopUpMenus.RemoveMenuFromMenuBar(index);
VariantClear(&index);
}
pDisp->Release();
}
}
void KTMenuCtrl::SetMenu(KTMenuPopup* pMenu)
{
if (pMenu == m_pMenu)
return;
m_iCurSel = -1;
m_iOffset = 0;
m_iHeight = 0;
m_pMenu = pMenu;
m_arpItems.RemoveAll();
if (m_pMenu != NULL)
{
ASSERT(IsWindow(m_hWnd));
m_iHeight = BuildItem(m_pMenu);
Invalidate();
}
}
KTMenuItem* KTMenuCtrl::GetMenuItem(int iIndex)
{
return ((iIndex >= 0 && iIndex < m_arpItems.GetSize()) ? (KTMenuItem*)m_arpItems[iIndex] : NULL);
}
KTMenuItem* KTMenuCtrl::GetTrackItem(UINT nID)
{
if ( NULL != m_pTrack && NULL != m_pTrack->m_pPopup
&& nID >= KTMENU_ITEM_STARTID && nID <= KTMENU_ITEM_ENDID)
{
MENUITEMINFO info;
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_DATA;
info.dwItemData = NULL;
if (m_pTrack->m_pPopup->m_menuPopup.GetMenuItemInfo(nID, &info, FALSE))
{
return ((KTMenuItem*)info.dwItemData);
}
}
return NULL;
}
BOOL KTMenuCtrl::Create(CWnd* pParentWnd, DWORD dwStyle, const RECT& rect, UINT nID)
{
return CWnd::Create(NULL, NULL, dwStyle, rect, pParentWnd, nID, NULL);
}
BOOL KTMenuCtrl::OnCommand(WPARAM wParam, LPARAM lParam)
{
if (HIWORD(wParam) <= 1 && NULL == lParam && NULL != m_pTrack
&& NULL != m_pTrack->m_pPopup)
{
UINT nID = LOWORD(wParam);
if (nID >= KTMENU_ITEM_STARTID && nID <= KTMENU_ITEM_ENDID)
{
OnTrackClicked(nID);
return TRUE;
}
}
return CWnd::OnCommand(wParam, lParam);
}
BOOL KTMenuCtrl::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
if (nCode == CN_UPDATE_COMMAND_UI && NULL != pExtra)
{
if (OnItemUpdate((CCmdUI*)pExtra))
{
return TRUE;
}
}
return CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
void KTMenuCtrl::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
OnSetMessage(GetTrackItem(nItemID));
CWnd::OnMenuSelect(nItemID, nFlags, hSysMenu);
}
void KTMenuCtrl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
if (m_iOffset + m_iHeight < cy)
{
m_iOffset = cy - m_iHeight;
if (m_iOffset > 0) m_iOffset = 0;
Invalidate();
}
}
void KTMenuCtrl::OnPaint()
{
CPaintDC dc(this);
DrawItem(&dc);
}
void KTMenuCtrl::OnCaptureChanged(CWnd *pWnd)
{
DRAW_ITEM(m_iCurSel, 0)
m_bLDown = FALSE;
m_iCurSel = -1;
OnSetMessage(m_iCurSel);
CWnd::OnCaptureChanged(pWnd);
}
void KTMenuCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
if (NULL != curDoc())
{
m_bLDown = (m_iCurSel >= 0);
DRAW_ITEM(m_iCurSel, ODS_SELECTED)
}
CWnd::OnLButtonDown(nFlags, point);
}
void KTMenuCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bLDown && m_iCurSel >= 0)
{
m_bLDown = FALSE;
int iIndex = m_iCurSel;
KTMenuItem* pItem = (KTMenuItem*)m_arpItems[iIndex];
ASSERT(pItem != NULL);
if (pItem->IsPopupItem())
{
KTMenuPopup* pMenu = ((GetItemState(iIndex) & ODS_EXPAND) ? pItem->m_pParent : pItem->m_pPopup);
m_iHeight = BuildItem(pMenu);
iIndex = FindItem(pItem);
ASSERT(iIndex >= 0);
CRect rc;
GetItemRect(iIndex, rc);
int iPos = m_iOffset - rc.top;
GetClientRect(&rc);
if (m_iHeight > rc.Height())
{
m_iOffset = rc.Height() - m_iHeight;
if (m_iOffset < iPos) m_iOffset = iPos;
}
else
{
m_iOffset = 0;
}
CClientDC dc(this);
DrawItem(&dc);
m_iCurSel = HitTest(&point);
OnSetMessage(m_iCurSel);
}
DRAW_ITEM(m_iCurSel, ODS_FOCUS)
//
SubOnItemClicked(iIndex,point);
}
CWnd::OnLButtonUp(nFlags, point);
}
void KTMenuCtrl::SubOnItemClicked(int iIndex, CPoint& point)
{
if (iIndex < 0 || iIndex >= m_arpItems.GetSize())
return;
KTMenuItem *pItem = (KTMenuItem *)m_arpItems[iIndex];
CRect rc;
GetItemRect(iIndex, rc);
UINT nSub = 1;
rc.left += nSub * 1;
//rc.left += nSub * KTICON_SIZE_X;
CRect rcIcon(rc.left + KTICON_GAP, rc.top, rc.left + KTICON_SIZE_X + KTICON_GAP, rc.bottom);
CRect rcText(rc.left, rc.top, rc.right, rc.bottom);
CClientDC dc(this);
CFont *pOldFnt = NULL;
#if ARX>15
pOldFnt = dc.SelectObject(acedGetAcadFrame()->GetMessageBar()->GetFont());
#else
NONCLIENTMETRICS nm;
nm.cbSize = sizeof(NONCLIENTMETRICS);
VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize, &nm, 0));
CFont fontMenu;
fontMenu.CreateFontIndirect(&nm.lfMenuFont);
pOldFnt = dc.SelectObject(&fontMenu);
#endif // ARX>15
CSize szTxt = dc.GetTextExtent(pItem->m_sText);
rcText.right = rcText.left + szTxt.cx + KTICON_SIZE_X + 11;
dc.SelectObject(pOldFnt);
WORD wd = 0;
if (m_mapCmd2HelpFlag.Lookup((void *)(LPCTSTR)pItem->m_sAction, wd))
{
if (rcText.PtInRect(point))
{
OnItemClicked(iIndex);
}
else
{
rcText.left = rcIcon.right + KTICON_GAP;
CRect rcIcon2 = rcText;
if (wd & 0x001)
{
rcIcon2.left = rcText.left + szTxt.cx + 3 * KTICON_GAP;
rcIcon2.right = rcIcon2.left + POP_ICON;
if (rcIcon2.PtInRect(point))
{
//show txt help
//acutPrintf(_T("\nShow txt help!"));
CFileFind fd;
CString sTxtHelp;
sTxtHelp.Format(_T("%s\\%s.txt"), Tools::GetHelpDir(), pItem->m_sAction);
CString sPdfHelp;
sPdfHelp.Format(_T("%s\\%s.pdf"), Tools::GetHelpDir(), pItem->m_sAction);
if (fd.FindFile(sTxtHelp))
{
int nPos = sTxtHelp.ReverseFind(_T('\\'));
if (nPos != NULL)
{
CString sPath = sTxtHelp.Mid(0, nPos);
ShellExecute(NULL, _T("open"), sTxtHelp, NULL, sPath, SW_SHOWNORMAL);
return;
}
}
if (fd.FindFile(sPdfHelp))
{
int nPos = sPdfHelp.ReverseFind(_T('\\'));
if (nPos != NULL)
{
CString sPath = sPdfHelp.Mid(0, nPos);
ShellExecute(NULL, _T("open"), sPdfHelp, NULL, sPath, SW_SHOWNORMAL);
return;
}
}
}
}
if (wd & 0x002)
{
rcIcon2 = rcText;
rcIcon2.left = rcText.left + szTxt.cx + POP_ICON + 8 * KTICON_GAP;
rcIcon2.right = rcIcon2.left + POP_ICON;
if (rcIcon2.PtInRect(point))
{
CString sWavHelpwav;
sWavHelpwav.Format(_T("%s\\%s.wav"), Tools::GetHelpDir(), pItem->m_sAction);
CString sWavHelpgif;
sWavHelpgif.Format(_T("%s\\%s.gif"), Tools::GetHelpDir(), pItem->m_sAction);
CString sWavHelpmp4;
sWavHelpmp4.Format(_T("%s\\%s.mp4"), Tools::GetHelpDir(), pItem->m_sAction);
CString sWavHelpmov;
sWavHelpmov.Format(_T("%s\\%s.mov"), Tools::GetHelpDir(), pItem->m_sAction);
CFileFind fd;
if (fd.FindFile(sWavHelpwav))
{
ShellExecute(NULL, _T("open"), _T("wmplayer.exe"), sWavHelpwav, NULL, SW_SHOW);
return;
}
if (fd.FindFile(sWavHelpgif))
{
//ShellExecute(NULL, _T("open"), _T("wmplayer.exe"), sWavHelpgif, NULL, SW_SHOW);
CAcModuleResourceOverride myResources;
CPlayGifDlg dlg(sWavHelpgif);
dlg.DoModal();
return;
}
if (fd.FindFile(sWavHelpmp4))
{
ShellExecute(NULL, _T("open"), _T("wmplayer.exe"), sWavHelpmp4, NULL, SW_SHOW);
return;
}
if (fd.FindFile(sWavHelpmov))
{
ShellExecute(NULL, _T("open"), _T("wmplayer.exe"), sWavHelpmov, NULL, SW_SHOW);
return;
}
}
}
}
}
else
{
OnItemClicked(iIndex);
}
}
void KTMenuCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
CWnd* pActive = GetActiveWindow();
if (NULL != curDoc() && (GetParentFrame() == pActive || GetTopLevelParent() == pActive))
{
CRect rcClient;
GetClientRect(&rcClient);
if (rcClient.PtInRect(point))
{
SetFocus();
if (GetCapture() != this)
SetCapture();
}
else
{
if (!m_bLDown && GetCapture() == this)
{
ReleaseCapture();
acedGetAcadDwgView()->SetFocus();
}
}
int iIndex = HitTest(&point);
if (iIndex != m_iCurSel)
{
DRAW_ITEM(m_iCurSel, 0)
m_iCurSel = iIndex;
DRAW_ITEM(m_iCurSel, (m_bLDown ? ODS_SELECTED : ODS_FOCUS))
OnSetMessage(m_iCurSel);
}
}
else if (GetCapture() == this)
{
ReleaseCapture();
acedGetAcadDwgView()->SetFocus();
DRAW_ITEM(m_iCurSel, 0)
m_bLDown = FALSE;
m_iCurSel = -1;
OnSetMessage(m_iCurSel);
}
CWnd::OnMouseMove(nFlags, point);
}
BOOL KTMenuCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
int iBackup = m_iOffset;
m_iOffset += (zDelta > 0 ? 10 : -10);
CRect rc;
GetClientRect(rc);
if (m_iOffset + m_iHeight < rc.Height())
m_iOffset = rc.Height() - m_iHeight;
if (m_iOffset > 0) m_iOffset = 0;
if (iBackup != m_iOffset)
{
CClientDC dc(this);
DrawItem(&dc);
CPoint point(pt);
ScreenToClient(&point);
m_iCurSel = HitTest(&point);
DRAW_ITEM(m_iCurSel, (m_bLDown ? ODS_SELECTED : ODS_FOCUS))
OnSetMessage(m_iCurSel);
}
return TRUE;
}
void KTMenuCtrl::OnSetMessage(int iIndex)
{
OnSetMessage(GetMenuItem(iIndex));
}
void KTMenuCtrl::OnSetMessage(KTMenuItem* pItem)
{
if (NULL == pItem)
acedRestoreStatusBar();
else
{
LPCTSTR pszMsg = _T("");
if (!pItem->IsSeparator())
{
LPCTSTR pszRes = (pItem->IsSwitchItem() ? pItem->m_sAction : pItem->m_sResource);
pszMsg = m_mnRrc.GetResourceInfo(pszRes);
}
CMDIFrameWnd* pFrame = acedGetAcadFrame();
ASSERT(pFrame != NULL);
pFrame->SetMessageText(pszMsg);
}
}
UINT KTMenuCtrl::BuildItem(KTMenuPopup* pMenu)
{
MeasureItem(pMenu);
m_arpItems.RemoveAll();
return OnBuildItem(pMenu, NULL);
}
UINT KTMenuCtrl::OnBuildItem(KTMenuPopup* pMenu, KTMenuPopup* pSub)
{
ASSERT(pMenu != NULL);
UINT nHeight = 0;
KTMenuItem* pItem;
BOOL bFind = FALSE;
int iSize = (int)pMenu->m_arpItem.GetSize();
for (int i = 0; i < iSize; i++)
{
pItem = (KTMenuItem*)pMenu->m_arpItem[i];
if (bFind)
m_arpItems.Add(pItem);
else
m_arpItems.InsertAt(i, pItem);
nHeight += pItem->m_dwData;
bFind |= (pSub != NULL && pItem->m_pPopup == pSub);
}
if (pMenu != m_pMenu && pMenu->m_pParent != NULL)
{
nHeight += OnBuildItem(pMenu->m_pParent, pMenu);
}
return nHeight;
}
UINT KTMenuCtrl::GetItemState(int iIndex, UINT* pSub)
{
ASSERT(iIndex >= 0 && iIndex < m_arpItems.GetSize());
KTMenuItem* pItem = (KTMenuItem*)m_arpItems[iIndex];
KTMenuItem* pNext = (KTMenuItem*)(iIndex+1 < m_arpItems.GetSize() ? m_arpItems[iIndex+1] : NULL);
KTMenuItem* pPrev = (KTMenuItem*)(iIndex > 0 ? m_arpItems[iIndex-1] : NULL);
UINT nFlag = 0;
if (pNext != NULL && pItem->m_pPopup == pNext->m_pParent)
nFlag |= ODS_EXPAND;
if (pPrev == NULL || pItem->m_pParent != pPrev->m_pParent)
nFlag |= ODS_T_EDGE;
if (pNext == NULL || pItem->m_pParent != pNext->m_pParent)
nFlag |= ODS_B_EDGE;
if (pSub != NULL)
{
*pSub = 0;
KTMenuPopup* pMenu = pItem->m_pParent;
while (pMenu != NULL && pMenu != m_pMenu)
{
(*pSub)++;
pMenu = pMenu->m_pParent;
}
}
return nFlag;
}
BOOL KTMenuCtrl::OnItemUpdate(CCmdUI* pCmdUI)
{
ASSERT(NULL != pCmdUI);
KTMenuCtrl* pMenuCtrl = DYNAMIC_DOWNCAST(KTMenuCtrl, pCmdUI->m_pOther);
if (NULL == pMenuCtrl)
return FALSE;
KTMenuItem* pItem = ((NULL == pCmdUI->m_pMenu) ? pMenuCtrl->GetMenuItem(pCmdUI->m_nIndex)
: pMenuCtrl->GetTrackItem(pCmdUI->m_nID));
if (NULL == pItem)
return FALSE;
// 根据条目类型确定相应状态
if (pItem->IsSwitchItem())
{
}
else if (pItem->IsCheckItem())
{
}
else if (pItem->IsStatusItem())
{
}
else
{
pCmdUI->Enable(TRUE);
}
return TRUE;
}
BOOL KTMenuCtrl::GetItemRect(int iIndex, CRect& rcItem)
{
if (iIndex >= m_arpItems.GetSize())
return FALSE;
int iHeight = m_iOffset;
KTMenuItem* pItem = NULL;
for (int i = 0; i <= iIndex; i++)
{
pItem = (KTMenuItem*)m_arpItems[i];
ASSERT(pItem != NULL);
iHeight += pItem->m_dwData;
}
if (pItem != NULL)
{
GetClientRect(&rcItem);
rcItem.bottom = rcItem.top + iHeight;
rcItem.top = rcItem.bottom - pItem->m_dwData;
return TRUE;
}
return FALSE;
}
int KTMenuCtrl::FindItem(KTMenuItem* pItem)
{
for (int i = (int)m_arpItems.GetSize()-1; i >= 0; i--)
{
if (pItem == m_arpItems[i])
return i;
}
return -1;
}
int KTMenuCtrl::HitTest(LPPOINT pPt, UINT* pFlag)
{
CRect rcItem;
GetClientRect(&rcItem);
if (!rcItem.PtInRect(*pPt))
return -1;
rcItem.top += m_iOffset;
rcItem.bottom = rcItem.top;
KTMenuItem* pItem;
int iSize = (int)m_arpItems.GetSize();
for (int i = 0; i < iSize; i++)
{
pItem = (KTMenuItem*)m_arpItems[i];
ASSERT(pItem != NULL);
rcItem.bottom += pItem->m_dwData;
if (rcItem.PtInRect(*pPt))
return i;
rcItem.top = rcItem.bottom;
}
return -1;
}
BOOL KTMenuCtrl::TrackPopupMenu(UINT nFlag, LPPOINT pPt, int iIndex)
{
m_pTrack = GetMenuItem(iIndex);
if (NULL == curDoc() || NULL == m_pTrack)
return FALSE;
return m_pTrack->TrackPopupMenu(nFlag, pPt->x, pPt->y, this);
}
void KTMenuCtrl::MeasureItem(KTMenuPopup* pMenu)
{
ASSERT(pMenu != NULL);
KTMenuItem* pItem;
int iSize = (int)pMenu->m_arpItem.GetSize();
MEASUREITEMSTRUCT mi = {ODT_BUTTON, 0, 0, 20, 20, 0};
for (int i = 0; i < iSize; i++)
{
pItem = (KTMenuItem*)pMenu->m_arpItem[i];
ASSERT(pItem != NULL);
if (pItem->m_dwData > 0)
continue;
mi.itemData = (DWORD_PTR)pItem;
SendMessage(WM_MEASUREITEM, 0, (LPARAM)&mi);
pItem->m_dwData = mi.itemHeight;
}
}
void KTMenuCtrl::DrawItem(CDC* pDC)
{
CRect rcClient;
GetClientRect(&rcClient);
CRect rc(rcClient.left, rcClient.top + m_iOffset, rcClient.right, rcClient.top + m_iOffset);
DRAWITEMSTRUCT di = {ODT_BUTTON, 0, 0, 0, 0, NULL, pDC->m_hDC, 0};
UINT nSub, nFlag;
KTMenuItem* pItem;
int iSize = (int)m_arpItems.GetSize();
for (int i = 0; i < iSize; i++)
{
pItem = (KTMenuItem*)m_arpItems[i];
ASSERT(pItem != NULL);
rc.bottom += pItem->m_dwData;
if (rc.bottom > rcClient.top && rc.top < rcClient.bottom)
{
KTMenuCmdUI state(this, i);
state.DoUpdate(this, FALSE);
nFlag = GetItemState(i, &nSub);
di.rcItem = rc;
di.itemAction = 0;
di.itemState = state.m_nState;
di.itemData = (DWORD_PTR)pItem;
di.hwndItem = (HWND)MAKELPARAM(nSub, nFlag);
SendMessage(WM_DRAWITEM, 0, (LPARAM)&di);
}
rc.top = rc.bottom;
}
rcClient.top = rc.bottom;
pDC->FillSolidRect(rcClient, ::GetSysColor(COLOR_BTNFACE));
}
void KTMenuCtrl::OnItemClicked(int iIndex)
{
ASSERT(iIndex >= 0 && iIndex < m_arpItems.GetSize());
KTMenuCmdUI state(this, iIndex);
state.DoUpdate(this, FALSE);
if (!(state.m_nState & (ODS_DISABLED | ODS_GRAYED)))
{
KTMenuItem* pItem = GetMenuItem(iIndex);
if (pItem != NULL && !pItem->m_sAction.IsEmpty())
OnExecuteCmd(pItem);
}
}
void KTMenuCtrl::OnTrackClicked(UINT nID)
{
ASSERT(nID >= KTMENU_ITEM_STARTID && nID <= KTMENU_ITEM_ENDID);
KTMenuCmdUI state(this, nID, &(m_pTrack->m_pPopup->m_menuPopup));
state.DoUpdate(this, FALSE);
if (!(state.m_nState & (ODS_DISABLED | ODS_GRAYED)))
{
KTMenuItem* pItem = GetTrackItem(nID);
if (pItem != NULL && !pItem->m_sAction.IsEmpty())
OnExecuteCmd(pItem);
}
}
void KTMenuCtrl::OnExecuteCmd(KTMenuItem* pItem)
{
ASSERT(NULL != pItem && !pItem->m_sAction.IsEmpty());
AcApDocument* pDoc = curDoc();
if (NULL == pDoc)
return;
struct resbuf rb = {NULL, RTSHORT, 0};
acedGetVar(_T("CMDACTIVE"), &rb);
CString sCmdStr;
if (rb.resval.rint > 0)
sCmdStr = _T("\33\33");
sCmdStr += pItem->m_sAction;
sCmdStr += _T("\n");
acedPostCommand(sCmdStr);
acedGetAcadDwgView()->SetFocus();
}
void KTMenuCtrl::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
if (lpMeasureItemStruct->CtlType != ODT_BUTTON)
{
CWnd::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
return;
}
KTMenuItem* pItem = (KTMenuItem*)lpMeasureItemStruct->itemData;
ASSERT(pItem != NULL);
if (pItem->IsSeparator())
{
lpMeasureItemStruct->itemHeight = 6;
}
else if (pItem->IsPopupItem())
{
int iTemp = GetSystemMetrics(SM_CYMENU);
lpMeasureItemStruct->itemHeight = max(iTemp, POP_ICON + KTICON_GAP);
}
else
{
int iTemp = GetSystemMetrics(SM_CYMENU);
lpMeasureItemStruct->itemHeight = max(iTemp, KTICON_SIZE_Y + KTICON_GAP);
}
}
void KTMenuCtrl::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (lpDrawItemStruct->CtlType != ODT_BUTTON)
{
CWnd::OnDrawItem(nIDCtl, lpDrawItemStruct);
return;
}
KTMenuItem* pItem = (KTMenuItem*)lpDrawItemStruct->itemData;
ASSERT(pItem != NULL);
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
#if ARX>15
pDC->SelectObject(acedGetAcadFrame()->GetMessageBar()->GetFont());
#else
NONCLIENTMETRICS nm;
nm.cbSize = sizeof (NONCLIENTMETRICS);
VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize, &nm, 0));
CFont fontMenu;
fontMenu.CreateFontIndirect(&nm.lfMenuFont);
pDC->SelectObject(&fontMenu);
#endif // ARX>15
double dScale = CoreTools::GetDPIScale();
CRect rc(lpDrawItemStruct->rcItem);
UINT nSub = LOWORD((DWORD)lpDrawItemStruct->hwndItem);
rc.left += nSub * 1;
//rc.left += nSub * KTICON_SIZE_X;
CRect rcIcon(rc.left + KTICON_GAP * dScale, rc.top, rc.left + KTICON_SIZE_X * dScale + KTICON_GAP * dScale, rc.bottom);
CRect rcText(rcIcon.right + KTICON_GAP * dScale, rc.top, rc.right, rc.bottom);
//rc.left -= nSub * KTICON_SIZE_X;
rc.left -= nSub * 1;
UINT nFlag = HIWORD((DWORD)lpDrawItemStruct->hwndItem);
BOOL bCheck = (lpDrawItemStruct->itemState & ODS_CHECKED);
BOOL bSelect = (!pItem->IsSeparator() && lpDrawItemStruct->itemState & ODS_SELECTED);
BOOL bFocus = (!pItem->IsSeparator() && lpDrawItemStruct->itemState & ODS_FOCUS);
BOOL bDisable = FALSE; //ligend //(!pItem->IsSeparator() && lpDrawItemStruct->itemState & (ODS_DISABLED|ODS_GRAYED));
COLORREF crBkColor;
if (nSub == 0)
crBkColor = ::GetSysColor(COLOR_BTNFACE);
else
crBkColor = ((bFocus || bSelect) ? RGB(255, 255, 170) : (nSub > 1 ? RGB(221, 234, 221) : RGB(239, 239, 236)));
pDC->FillSolidRect(rc, crBkColor);
rc.DeflateRect(0, 1, 1, 1);
COLORREF crLeft, crTop, crRight, crBottom;
if (bSelect)
{
if (bDisable)
{
crLeft = crTop = ::GetSysColor(COLOR_BTNHIGHLIGHT);
crRight = crBottom = ::GetSysColor(COLOR_BTNSHADOW);
}
else
{
crLeft = crTop = ::GetSysColor(COLOR_BTNSHADOW);
crRight = crBottom = ::GetSysColor(COLOR_BTNHIGHLIGHT);
}
}
else if (bFocus)
{
crLeft = crTop = ::GetSysColor(COLOR_BTNHIGHLIGHT);
crRight = crBottom = ::GetSysColor(COLOR_BTNSHADOW);
}
else if ((nFlag & ODS_B_EDGE) && (nFlag & ODS_EXPAND))
{
crBottom = ::GetSysColor(COLOR_BTNSHADOW);
crLeft = crTop = crRight = crBkColor;
}
else
{
crLeft = crTop = crRight = crBottom = crBkColor;
}
//hot 选择状态
{
CPen pen1(PS_SOLID, 1, crLeft);
CPen* pPen = pDC->SelectObject(&pen1);
pDC->MoveTo(rc.left, rc.top);
pDC->LineTo(rc.left, rc.bottom);
CPen pen2(PS_SOLID, 1, crBottom);
pDC->SelectObject(&pen2);
pDC->MoveTo(rc.left, rc.bottom);
pDC->LineTo(rc.right, rc.bottom);
CPen pen3(PS_SOLID, 1, crRight);
pDC->SelectObject(&pen3);
pDC->MoveTo(rc.right, rc.bottom);
pDC->LineTo(rc.right, rc.top);
CPen pen4(PS_SOLID, 1, crTop);
pDC->SelectObject(&pen4);
pDC->MoveTo(rc.right, rc.top);
pDC->LineTo(rc.left, rc.top);
pDC->SelectObject(pPen);
}
if (pItem->IsSeparator())//
{
int iY = (rc.top + rc.bottom) / 2;
CPen pen1(PS_SOLID, 1, ::GetSysColor(COLOR_BTNSHADOW));
CPen* pPen = pDC->SelectObject(&pen1);
pDC->MoveTo(rc.left, iY);
pDC->LineTo(rc.right, iY);
CPen pen2(PS_SOLID, 1, ::GetSysColor(COLOR_BTNHIGHLIGHT));
pDC->SelectObject(&pen2);
pDC->MoveTo(rc.left, iY+1);
pDC->LineTo(rc.right, iY+1);
pDC->SelectObject(pPen);
}
else if (pItem->IsPopupItem())
{
CPoint pt(rcIcon.left, (rcIcon.top + rcIcon.bottom - POP_ICON * dScale) / 2);
CoreTools::drawIcon(m_imglstIcon.GetSafeHandle()
, (nSub > 0 ? 2 : 0) + ((nFlag & ODS_EXPAND) ? 1 : 0)
, pDC->GetSafeHdc()
, pt
, ILD_TRANSPARENT);
pDC->SetBkColor(crBkColor);
pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
pDC->DrawText(pItem->m_sText, rcText, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
}
else
{
if (bCheck)
{
HBITMAP hBmp = LoadBitmap (NULL, MAKEINTRESOURCE(32760));
if (hBmp != NULL)
{
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)
{
HBITMAP hBmp = m_mnRrc.GetResourceIcon(m_hResource, pItem->m_sResource);
if (hBmp != NULL)
{
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);
CPoint pt(rcIcon.left, (rcIcon.top + rcIcon.bottom - KTICON_SIZE_Y * dScale)/2);
CoreTools::drawIcon(hIcon, pDC->GetSafeHdc(), pt, ILD_TRANSPARENT);
DestroyIcon (hIcon);
}
}
pDC->SetBkColor(crBkColor);
pDC->SetTextColor(::GetSysColor(bDisable ? COLOR_GRAYTEXT : COLOR_MENUTEXT));
pDC->DrawText(pItem->m_sText, rcText, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
//最右侧绘制 视频帮助 和 文字帮助 按钮, 如果有
//CMD = pItem->m_sAction
//CString sSys(Tools::GetHelpDir()); F:\\ShangHuaSoft\\PoolPlant3D-2021\\help
DrawHelp(pDC, pItem, rcText);
}
}
void KTMenuCtrl::DrawHelp(CDC* pDC, KTMenuItem * pItem, CRect& rcText)
{
WORD wd = 0;
if (m_mapCmd2HelpFlag.Lookup((void*)(LPCTSTR)pItem->m_sAction,wd))
{
CRect rcIcon = rcText;
CSize szTxt = pDC->GetTextExtent(pItem->m_sText);
if (wd & 0x001 )
{
rcIcon.left = rcText.left + szTxt.cx + 3 * KTICON_GAP;
CPoint pt(rcIcon.left, (rcIcon.top + rcIcon.bottom - POP_ICON) / 2);
m_imgHelpIcon.Draw(pDC, 0, pt, ILD_TRANSPARENT);
}
if (wd & 0x002)
{
rcIcon = rcText;
rcIcon.left = rcText.left + szTxt.cx + POP_ICON + 8 * KTICON_GAP;
CPoint pt(rcIcon.left, (rcIcon.top + rcIcon.bottom - POP_ICON) / 2);
m_imgHelpIcon.Draw(pDC, 1, pt, ILD_TRANSPARENT);
}
}
else
{
CFileFind fd;
CString sTxtHelp;
sTxtHelp.Format(_T("%s\\%s.txt"), Tools::GetHelpDir(), pItem->m_sAction);
CString sPdfHelp;
sPdfHelp.Format(_T("%s\\%s.pdf"), Tools::GetHelpDir(), pItem->m_sAction);
if (fd.FindFile(sTxtHelp) || fd.FindFile(sPdfHelp) )
{
wd |= 0x001;
fd.Close();
CRect rcIcon = rcText;
CSize szTxt = pDC->GetTextExtent(pItem->m_sText);
rcIcon.left = rcText.left + szTxt.cx + 3 * KTICON_GAP;
CPoint pt(rcIcon.left, (rcIcon.top + rcIcon.bottom - POP_ICON) / 2);
m_imgHelpIcon.Draw(pDC, 0, pt, ILD_TRANSPARENT);
}
CString sWavHelpwav;
sWavHelpwav.Format(_T("%s\\%s.wav"), Tools::GetHelpDir(),pItem->m_sAction);
CString sWavHelpgif;
sWavHelpgif.Format(_T("%s\\%s.gif"), Tools::GetHelpDir(), pItem->m_sAction);
CString sWavHelpmp4;
sWavHelpmp4.Format(_T("%s\\%s.mp4"), Tools::GetHelpDir(), pItem->m_sAction);
CString sWavHelpmov;
sWavHelpmov.Format(_T("%s\\%s.mov"), Tools::GetHelpDir(), pItem->m_sAction);
if (fd.FindFile(sWavHelpwav) || fd.FindFile(sWavHelpgif) ||
fd.FindFile(sWavHelpmp4) || fd.FindFile(sWavHelpmov))
{
wd |= 0x002;
fd.Close();
CRect rcIcon = rcText;
CSize szTxt = pDC->GetTextExtent(pItem->m_sText);
rcIcon.left = rcText.left + szTxt.cx + POP_ICON + 8 * KTICON_GAP;
CPoint pt(rcIcon.left, (rcIcon.top + rcIcon.bottom - POP_ICON) / 2);
m_imgHelpIcon.Draw(pDC, 1, pt, ILD_TRANSPARENT);
}
if (wd > 0)
m_mapCmd2HelpFlag.SetAt((void *)(LPCTSTR)pItem->m_sAction,wd);
}
}
void KTMenuCtrl::OnDestroy()
{
CWnd::OnDestroy();
}