#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(); }