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

1287 lines
33 KiB
C++

#include "StdAfx.h"
#include <typeinfo>
#include "AecUIContextMenu.h"
#include "AecDbEntityBase.h"
#include "AecDbCurveBase.h"
#include "AecDbEwEquipment.h"
#include "aecdbewpipe.h"
#include "AecDbEwFitting.h"
#include "CoreTools.h"
#include "aecdb3droad.h"
#include "AecDb3dRoadFitting.h"
#include "AecDbECFitting.h"
#include "AecDbEwPipeBase.h"
#include "AecDbHvacDuct.h"
#include "AecDbX3dPartEntity.h"
#include "shJson.h"
#include "TypeConvert.h"
#include "FilePath.h"
namespace
{
bool isSHEntity(const AcDbObjectId &id)
{
if (UIMenuItem::isKindOf<AecDbEntityBase>(id)
|| UIMenuItem::isKindOf<AecDbCurveBase>(id))
return true;
return false;
}
bool isSHEntity(const AcDbObjectIdArray &ids)
{
for (int i(0); i < ids.length(); ++i)
{
if (!isSHEntity(ids[i]))
return false;
}
return true;
}
bool getSingleSelect(ads_name adsEnt, bool bClearPickFirst = true)
{
ads_name ssSet;
if (acedSSGet(NULL, NULL, NULL, NULL, ssSet) == RTNORM)
{
acedSSName(ssSet, 0, adsEnt);
acedSSFree(ssSet);
// 清空当前选择
if (bClearPickFirst)
acedSSSetFirst(NULL, NULL);
return true;
}
return false;
}
//一个 Polyline 自身是否所有点共线
bool isPolylineSelfCollinear(const AcDbObjectId &id)
{
AcDbObjectPointer<AcDbPolyline> ent(id, AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) return true; // 打开失败算共线
AcDbPolyline *pPoly(ent.object());
return CoreTools::isPolylineSelfCollinear(pPoly);
}
void idsToSelection(const AcDbObjectIdArray &ids, ads_name &ss)
{
// 创建一个空的选择集
acedSSAdd(NULL, NULL, ss);
ads_name entName;
for (int i = 0; i < ids.length(); i++)
{
// 将 ID 转为 ads_name
if (acdbGetAdsName(entName, ids[i]) == Acad::eOk)
{
// 加入选择集
acedSSAdd(entName, ss, ss);
}
}
}
void appendMenu(HMENU hMenu
, const UINT_PTR id
, LPCTSTR psz
, int idx = -1
, UINT flags = MF_STRING | MF_ENABLED )
{
static CString sIdx = _T("0123456789ABCDEFGHIJKUMNOPQRSTUVWXYZabcdefghijkumnopqrstuvwxyz");
if (idx == -1)
{
::AppendMenu(hMenu, flags, id, psz);
return;
}
CString str(_T("&"));
if (idx >= sIdx.GetLength()) idx = 0;
str += sIdx[idx];
str += _T(". ");
::AppendMenu(hMenu, flags, id, str + psz);
}
AcGePoint3d getPickPoint()
{
AcGePoint3d ptOut(AcGePoint3d::kOrigin);
CPoint ptCursor;
::GetCursorPos(&ptCursor);
HWND hDocWnd = adsw_acadDocWnd();
if (hDocWnd == NULL) return ptOut;
::ScreenToClient(hDocWnd, &ptCursor);
struct resbuf rb;
acedGetVar(_T("CVPORT"), &rb);
int cvport = rb.resval.rint;
ads_point ptResult;
if (acedCoordFromPixelToWorld(cvport, ptCursor, ptResult))
{
ptOut.set(ptResult[X], ptResult[Y], ptResult[Z]);
}
return ptOut;
}
// 将 AcDbObjectIdArray 转换为 resbuf 链表
// 格式: RTENAME, <name1>, RTENAME, <name2>, ..., RTNONE
resbuf *makeResbuf(const AcDbObjectIdArray &ids)
{
// 1. 如果数组为空,直接返回 NULL (或者一个仅包含 RTNONE 的节点,视需求而定)
// 通常返回 NULL 表示没有数据,acedCmd 会处理 NULL
if (ids.isEmpty())
{
return NULL;
}
resbuf *pHead = NULL; // 链表头指针
resbuf *pTail = NULL; // 链表尾指针,用于快速追加
for (int i = 0; i < ids.length(); ++i)
{
// 2. 获取实体 ID
const AcDbObjectId &id = ids[i];
// 3. 将 ObjectId 转换为 ads_name
ads_name entName;
if (acdbGetAdsName(entName, id) != Acad::eOk)
{
// 如果转换失败(例如实体已被删除),跳过该实体
continue;
}
// 4. 创建新的 resbuf 节点
// acutNewRb 分配内存,记得最后要释放
resbuf *pNode = acutNewRb(RTENAME);
if (pNode == NULL)
{
// 内存分配失败,清理已分配的链表并返回 NULL
if (pHead) acutRelRb(pHead);
return NULL;
}
// 5. 复制 ads_name 到 resbuf 中
// 注意:ads_name 是一个数组 (long[2]),必须复制内容,不能直接赋值指针
pNode->resval.rlname[0] = entName[0];
pNode->resval.rlname[1] = entName[1];
// 6. 链接到链表
if (pHead == NULL)
{
pHead = pNode; // 第一个节点
pTail = pNode;
}
else
{
pTail->rbnext = pNode; // 追加到尾部
pTail = pNode; // 更新尾指针
}
}
// 7. 在链表末尾追加 RTNONE 节点 (作为结束标志)
// 许多 ADS 函数(如 acedCmd)需要 RTNONE 结尾,但有些(如 acedSSGet)可能不需要。
// 根据你的描述 "最后是 RTNONE",我们加上它。
if (pHead != NULL)
{
resbuf *pEndNode = acutNewRb(RTNONE);
if (pEndNode)
{
pTail->rbnext = pEndNode;
}
else
{
// 极端情况下内存不足,清理并返回
acutRelRb(pHead);
return NULL;
}
}
return pHead;
}
void analyCfgFile(std::vector<UIMenuItem::Category> &cats
, std::map<CString, int> &mapWeight
, std::map<CString, bool> &mapUsed )
{
using namespace SHJson;
// 1. 初始化:清空传入的容器,防止多次调用时数据叠加
cats.clear();
mapWeight.clear();
mapUsed.clear();
// 2. 获取配置文件路径
CString sPath = FilePath::GetSysDir() + AecObjectUIContext::outputFileName;
// 3. 读取并解析 JSON 文件
WDocument doc;
if (!file2Json(sPath, doc))
{
// 如果文件不存在或解析失败,直接返回空容器
return;
}
CString sClass;
int iWeight = 0;
bool bUsed(false);
// 4. 遍历 JSON 根节点(每个成员代表一个分类)
for (MIt it = doc.MemberBegin(); it != doc.MemberEnd(); ++it)
{
// 获取分类的 Key 并转换为 UIMenuItem::Category 枚举,存入 vector
CString sCatKey = it->name.GetString();
int iCat = _ttoi(sCatKey);
cats.push_back(static_cast<UIMenuItem::Category>(iCat));
// 5. 确保分类的值是一个数组,然后遍历数组中的菜单项
if (!it->value.IsArray()) continue;
const WValue &arr = it->value;
MCIt cit;
for (SHJson::VCIt vit = arr.Begin(); vit != arr.End(); ++vit)
{
if (!vit->IsObject()) continue;
cit = vit->FindMember(_T("class"));
if (cit != vit->MemberEnd() && cit->value.IsString())
sClass = cit->value.GetString();
cit = vit->FindMember(_T("weight"));
if (cit != vit->MemberEnd() && cit->value.IsInt())
iWeight = cit->value.GetInt();
cit = vit->FindMember(_T("used"));
if (cit != vit->MemberEnd() && cit->value.IsBool())
bUsed = cit->value.GetBool();
// 存入 map 中 (只要 class 名称不为空)
if (!sClass.IsEmpty())
{
mapWeight[sClass] = iWeight;
mapUsed[sClass] = bUsed;
}
}
}
}
}
#pragma region command
#define SEND_EXEC_CMD(subcmd)\
acDocManager->sendStringToExecute(acDocManager->curDocument(), m_sCommand + subcmd, false, false, false)
resbuf *Filter_Condition_N_ENT::executeCommand() const
{
// N 个实体按照顺序发送
// 清空选择集
acedSSSetFirst(0, NULL);
// 实际上,不会出现N和m_arIds数量不一致的情况,在判断菜单是否有效时就会判断
resbuf *pEntBuf = makeResbuf(m_arIds);
if (!pEntBuf) return NULL;
resbuf *pRes = acutBuildList(RTSTR, m_sCommand, RTNONE);
pRes->rbnext = pEntBuf;
return pRes;
}
resbuf *Fitler_Condition_Interface_Ins::executeCommand() const
{
ads_point pt;
pt[X] = m_ptPick.x;
pt[Y] = m_ptPick.y;
pt[Z] = m_ptPick.z;
return acutBuildList(RTSTR, m_sCommand, RT3DPOINT, pt, RTNONE);
}
bool Fitler_Condition_Interface_Ins::eanbleCondition(const AcDbObjectIdArray &ar, const AcGePoint3d &pt)
{
if (ar.length() != 1) return false;
if (!m_pFunc) return false;
// 1.是否满足列表
if (!m_pFunc(ar, pt, m_sFilter, m_N)) return false;
// 2.是否是能得到接口的类
if (!isAecMInterfaces(ar.first())) return false;
// 3.得到所有接口
AcDbEntityPointer ent(ar.first(), AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) return false;
AecMInterfaces *pInterface = dynamic_cast<AecMInterfaces *>(ent.object());
if (!pInterface) return false;
int count = pInterface->GetInterfaceCount();
if (count == 0) return false;
AcGePoint3d pt1(AcGePoint3d::kOrigin), pt2(pt);
pt2.z = 0;
AecInterface inf;
for (int i(0); i < count; ++i)
{
pInterface->GetInterface(i, inf);
pt1.x = inf.ptPos.x;
pt1.y = inf.ptPos.y;
if (pt1.distanceTo(pt2) > 50)
continue;
else
{
m_ptPick = inf.ptPos;
return true;
}
}
return false;
}
resbuf *Filter_Condition_Sender::executeCommand() const
{
SEND_EXEC_CMD(_T(" "));
return NULL;
}
#pragma endregion
#pragma region UIMenuItem
AcDbObjectIdArray UIMenuItem::m_arIds;
bool UIMenuItem::isOneSHEntity(CONDI_PARAMS_IMP)
{
return isOneAndKindOf<AecDbEntityBase>(ar, pt) || isOneAndKindOf<AecDbCurveBase>(ar, pt);
}
bool UIMenuItem::isClosedPLine(CONDI_PARAMS_IMP)
{
if (isOneAndKindOf<AcDbPolyline>(ar, pt))
{
AcDbObjectPointer<AcDbPolyline> ent(ar.first(), AcDb::kForRead);
if (ent.openStatus() == Acad::eOk && ent->isClosed())
return true;
}
return false;
}
bool UIMenuItem::canQModify(CONDI_PARAMS_IMP)
{
// 只要有一个上华实体就可以
for (int i(0); i < ar.length(); ++i)
{
if (isKindOf<AecDbCurveBase>(ar[i]) || isKindOf<AecDbEntityBase>(ar[i]))
return true;
}
return false;
}
bool UIMenuItem::isOneValve(CONDI_PARAMS_IMP)
{
if (!isOneAndKindOf<AecDbEwEquipment>(ar, pt)) return false;
AcDbEntityPointer ent(ar.first(), AcDb::kForRead);
if (ent.openStatus() != Acad::eOk)
return false;
AecDbEwEquipment *pEqu(AecDbEwEquipment::cast(ent));
if (!pEqu) return false;
int subRuntime(0), valveType(0);
pEqu->GetAt(KEY_SUBRUNTIME, subRuntime);
if (subRuntime != eValve)
return false;
if (!pEqu->GetAt(PIPE_VALVE, valveType))
return false;
return true;
}
bool UIMenuItem::isAllSHEntity(CONDI_PARAMS_IMP)
{
for (int i(0); i < ar.length(); ++i)
{
if (!isSHEntity(ar[i]))
return false;
}
return true;
}
CString UIMenuItem::getClassName(UIMenuItem * pItem)
{
const std::type_info &info = typeid(*pItem);
return CString(info.name()).Mid(6);
}
bool UIMenuItem::compareItems(const UIMenuItem *a, const UIMenuItem *b)
{
if (!a || !b) return false;
// 1. 先比分类
if (a->m_iCategory != b->m_iCategory)
return a->m_iCategory < b->m_iCategory;
// 2. 分类相同,再比权重
return a->m_iWeight < b->m_iWeight;
}
bool UIMenuItem::compareItemsByCategory(const UIMenuItem *a, const UIMenuItem *b)
{
if (!a || !b) return false;
return a->m_iCategory < b->m_iCategory;
}
void UIMenuItem::BuildPickFist()
{
if (m_arIds.length() > 0)
{
ads_name ss;
idsToSelection(m_arIds, ss);
acedSSSetFirst(ss, ss);
acedSSFree(ss);
}
}
CString UIMenuItem::getCategoryName(const Category & cat)
{
switch (cat)
{
case eSys:
return CString(_T("系统"));
case eCr:
return CString(_T("生成实体"));
case eCrPipe:
return _T("管线实体");
case eCrStut:
return _T("土建实体");
case eCrHVAC:
return _T("暖通实体");
case eCrElec:
return _T("电气实体");
case eDsPipe:
return _T("管线设计");
case eDsStut:
return _T("土建设计");
case eDsEqui:
return _T("设备设计");
case eDsHVAC:
return _T("暖通设计");
case eDsElec:
return _T("电气设计");
case eInsFitting:
return _T("插入管件");
case eCrEqui:
return _T("设备实体");
case eInsParamValve:
return _T("参数阀门");
case eInsCustomValve:
return _T("自定义阀门");
case eDimStut:
return _T("土建标注");
case eDimSys:
return _T("系统标注");
case eOpView:
return _T("视图操作");
case eExport:
return _T("数据中心");
default:
break;
}
return CString();
}
bool UIMenuItem::isVertPipe(CONDI_PARAMS_IMP)
{
if (ar.length() != 1) return false;
AcDbObjectPointer<AecDbEwPipe> ent(ar.first(), AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) return false;
AcGeVector3d vtDir = ent->GetTailDir();
if (!vtDir.isParallelTo(AcGeVector3d::kZAxis)
&& !vtDir.isParallelTo(-AcGeVector3d::kZAxis))
return false;
return true;
}
bool UIMenuItem::isFlange(CONDI_PARAMS_IMP)
{
if (ar.length() != 1) return false;
AcDbObjectPointer<AecDbEwFitting> ent(ar.first(), AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) return false;
int nType(0);
ent->GetAt(KEY_RUNTIME, nType);
return nType == eFlange;
}
bool UIMenuItem::isEquButNoValve(CONDI_PARAMS_IMP)
{
if (!isOneAndKindOf<AecDbEwEquipment>(ar, pt)) return false;
return !isOneValve(ar, pt);
}
bool UIMenuItem::isSlab(CONDI_PARAMS_IMP)
{
if (isOneAndKindOf<AcDbCircle>(ar, pt)) return true;
return isXSlab(ar, pt);
}
bool UIMenuItem::isXSlab(CONDI_PARAMS_IMP)
{
if (isOneAndKindOf<AcDbPolyline>(ar, pt))
{
return !isPolylineSelfCollinear(ar.first());
}
return false;
}
bool UIMenuItem::isAecMInterfaces(const AcDbObjectId &id)
{
if (isSameOf<AecDb3dRoad>(id)
|| isSameOf<AecDb3dRoadFitting>(id)
|| isSameOf<AecDbEcFitting>(id)
|| isSameOf<AecDbEwEquipment>(id)
|| isSameOf<AecDbEwFitting>(id)
|| isKindOf<AecDbEwPipeBase>(id) // AecDbEwPipeBase派生的都是
|| isSameOf<AecDbHvacDuct>(id)
|| isSameOf<AecDbX3dPartEntity>(id) )
return true;
return false;
}
bool UIMenuItem::idMatchFilter(const AcDbObjectId &id, LPCTSTR sFilter)
{
if (!sFilter) return false;
AcRxClass *pRx = id.objectClass();
if (!pRx) return false;
const TCHAR *dxfName = pRx->dxfName();
if (!dxfName) return false;
return acutWcMatch(dxfName, sFilter) == RTERROR ? false : true;
}
// 实体的dxf是否满足 Filter
bool UIMenuItem::isFilterMacth(CONDI_PARAMS_IMP, LPCTSTR sFilter, const int &N)
{
// 如果N==-1,说明命令需要用户选择多个实体,
// 当命令需要多个实体的时候,都会自带过滤器,
// 会自动过滤出需要的实体,所以,只要符合条件的实体大于1
// 就可以把选择集抛给命令取舍了
if (N <= 0)
{
int num(0);
for (int i(0); i < ar.length(); ++i)
{
if (idMatchFilter(ar[i], sFilter))
num++;
// N 的意义在于 这个命令虽然需要大于1个的实体,
// 但是至少需要abs(N)个实体才能工作
if (num >= -N)
return true;
}
return false;
}
// 当N是具体数值是,说明ar的数量不仅要等于N
// 它们的类型也都要满足 filter
if (ar.length() != N) return false;
for (int i(0); i < ar.length(); ++i)
{
if (!idMatchFilter(ar[i], sFilter))
return false;
}
return true;
}
bool UIMenuItem::eanbleCondition(const AcDbObjectIdArray & ar, const AcGePoint3d & pt)
{
if (!ar.isEmpty())
{
m_arIds = ar;
m_ptPick = pt;
return true;
}
return false;
}
void UIMenuItem::addToMenu(const HMENU & hMenu, const int &idx) const
{
if (!hMenu) return;
appendMenu(hMenu, m_idCommand, m_sUIName, idx);
}
resbuf* UIMenuItem::executeCommand() const
{
if (m_bUseSingleEntity)
{
ads_name adsEnt;
if (getSingleSelect(adsEnt))
return acutBuildList(RTSTR, m_sCommand, RTENAME, adsEnt, RTNONE);
}
else
{
// 不管选择了几个实体,都直接发送,PICKFIRST已经在外部构建
SEND_EXEC_CMD(_T(" "));
return NULL;
}
// 多个实体,用sendStringToExecute通过选择集来传递实体
if (m_arIds.length() > 1)
SEND_EXEC_CMD(_T(" "));
else
{ // 单个实体用 acedCmd
ads_name adsEnt;
if (getSingleSelect(adsEnt))
return acutBuildList(RTSTR, m_sCommand, RTENAME, adsEnt, RTNONE);
}
return NULL;
}
#pragma endregion
// 暂存选中的 ID 数组
static AcDbObjectIdArray g_cachedIdsForCmd;
// 暂存要执行的操作 ID
static int g_cachedCmdIndex = 0;
AecObjectUIContext* AecObjectUIContext::g_pBaseUIContext = NULL;
AecDefaultUIContext* AecDefaultUIContext::g_pDefaultContext = NULL;
const CString AecObjectUIContext::outputFileName = _T("\\uicontext.cfg");
#pragma region AecObjectUIContext
AecObjectUIContext::AecObjectUIContext(): m_hMenu(NULL)
{
remakeMenuItems();
initMenuItems();
}
AecObjectUIContext::~AecObjectUIContext()
{
if (m_hMenu)
{
::DestroyMenu(m_hMenu);
m_hMenu = NULL;
}
deleteContainerOfStd<std::vector<UIMenuItem *>>(m_menuItems);
}
void AecObjectUIContext::analyCfgFile()
{
std::map<CString, int> weights;
std::map<CString, bool> useds;
::analyCfgFile(m_sortCategories, weights, useds);
if (weights.empty() || useds.empty()) return;
CString className;
std::map<CString, int>::const_iterator itW;
std::map<CString, bool>::const_iterator itU;
for (size_t i(0); i < m_menuItems.size(); ++i)
{
UIMenuItem *pItem(m_menuItems[i]);
if (!pItem) continue;
className = UIMenuItem::getClassName(pItem);
itW = weights.find(className);
if (itW != weights.end())
pItem->m_iWeight = itW->second;
itU = useds.find(className);
if (itU != useds.end())
pItem->m_bUsed = itU->second;
}
}
void AecObjectUIContext::buildMenu(const AcDbObjectIdArray &ids, const AcGePoint3d &ptPick)
{
if (m_hMenu)
{
::DestroyMenu(m_hMenu);
m_hMenu = NULL;
}
m_hMenu = ::CreatePopupMenu();
if (!m_hMenu) return;
std::pair<UIItemVector::const_iterator, UIItemVector::const_iterator> range;
UIMenuItem item;
int idx(0);
HMENU hSubMenu(NULL);
for (size_t i(0); i < m_sortCategories.size(); ++i)
{
item.m_iCategory = m_sortCategories[i];
range = std::equal_range(
m_menuItems.begin(),
m_menuItems.end(),
&item, // 传入指针用于比较
UIMenuItem::compareItemsByCategory // 比较函数
);
if (range.first == range.second)
continue; // 没有该类别的菜单项,跳过
// 系统级命令,直接插入
if (item.m_iCategory == UIMenuItem::eSys)
{
hSubMenu = m_hMenu;
}
else
{
hSubMenu = ::CreatePopupMenu();
appendMenu(m_hMenu
, (UINT_PTR)hSubMenu
, UIMenuItem::getCategoryName(item.m_iCategory)
, ++idx
, MF_POPUP);
idx = 0;
}
UIItemVector::const_iterator it(range.first);
for (; it != range.second; ++it)
{
UIMenuItem *pItem = *it;
if (!pItem) continue;
if (!pItem->m_bUsed) continue;
if(!pItem->eanbleCondition(ids, ptPick)) continue;
pItem->addToMenu(hSubMenu, ++idx);
}
if (::GetMenuItemCount(hSubMenu) == 0 && hSubMenu != m_hMenu)
{
::RemoveMenu(m_hMenu, (UINT_PTR)hSubMenu, MF_BYCOMMAND);
::DestroyMenu(hSubMenu);
}
idx = ::GetMenuItemCount(m_hMenu);
}
}
void *AecObjectUIContext::getMenuContext(const AcRxClass *pClass, const AcDbObjectIdArray &ids)
{
if (ids.isEmpty()) return NULL;
AcGePoint3d ptPick(getPickPoint());
UIMenuItem::m_arIds = ids;
buildMenu(ids, ptPick);
return &m_hMenu;
}
void AecObjectUIContext::onCommand(Adesk::UInt32 cmdIndex)
{
g_cachedCmdIndex = cmdIndex;
acDocManager->sendStringToExecute(acDocManager->curDocument(), _T("_ui_context_command_helper_ "));
}
UIMenuItem* AecObjectUIContext::findItemById(const UINT_PTR & id)
{
UIMenuItem ut(id);
UIItemSet::const_iterator it = m_UIItemSet.find(&ut);
if (it == m_UIItemSet.end())
return NULL;
return *it;
}
void AecObjectUIContext::items2Json(LPCTSTR pszPath) const
{
using namespace SHJson;
typedef std::map<UIMenuItem::Category, UIItemVector> ITEMMAP;
if (!pszPath) return;
if (_taccess(pszPath, 0x0) == 0x0)
::DeleteFile(pszPath);
ITEMMAP mapItems;
std::pair<ITEMMAP::iterator, bool> pr;
for (size_t i(0); i < m_menuItems.size(); ++i)
{
UIMenuItem *pItem(m_menuItems[i]);
pr = mapItems.insert(std::make_pair(pItem->m_iCategory, UIItemVector()));
pr.first->second.push_back(pItem);
}
WDocument doc;
doc.SetArray();
ITEMMAP::const_iterator it(mapItems.begin());
WValue v;
v.SetObject();
WValue ar;
for (; it != mapItems.end(); ++it)
{
ar.SetArray();
const UIItemVector &vec(it->second);
for (size_t i(0); i < vec.size(); ++i)
{
UIMenuItem *pItem(vec[i]);
addMember(v, _T("class"), UIMenuItem::getClassName(pItem));
addMember(v, _T("name"), pItem->m_sUIName);
addMember(v, _T("weight"), pItem->m_iWeight);
// 此函数只为初始化使用,used字段永远为真
addMember(v, _T("used"), true);
pushBack(ar, v);
}
addMember(doc, TypeConvert::i2s(it->first), ar);
}
json2File(pszPath, doc ,true);
}
void AecObjectUIContext::remakeMenuItems()
{
deleteContainerOfStd<std::vector<UIMenuItem *>>(m_menuItems);
m_menuItems.clear();
m_menuItems.push_back(new CO_COPY);
m_menuItems.push_back(new CO_MOVE);
m_menuItems.push_back(new PL_DTYC);
m_menuItems.push_back(new PL_YCQT);
m_menuItems.push_back(new PL_TMXS);
m_menuItems.push_back(new CO_KSXZ);
m_menuItems.push_back(new CO_ALIGN);
m_menuItems.push_back(new CO_KSXG);
m_menuItems.push_back(new PL_DTYG);
m_menuItems.push_back(new PL_QMPS);
m_menuItems.push_back(new PL_GYST);
m_menuItems.push_back(new PL_JGST);
m_menuItems.push_back(new PL_RYPD);
m_menuItems.push_back(new PL_RZPD);
m_menuItems.push_back(new PL_HZDB);
m_menuItems.push_back(new PL_FZPB);
m_menuItems.push_back(new PL_HZGB);
m_menuItems.push_back(new PL_HZXB);
m_menuItems.push_back(new PL_FZFM);
m_menuItems.push_back(new PL_DXBQ);
m_menuItems.push_back(new PL_QXHN);
m_menuItems.push_back(new PL_GZZZ);
m_menuItems.push_back(new PL_ZZDZ);
m_menuItems.push_back(new PL_TYQG);
m_menuItems.push_back(new PL_DLJC);
m_menuItems.push_back(new PL_QTDD);
m_menuItems.push_back(new PL_PLGL);
m_menuItems.push_back(new PL_JXDQ);
m_menuItems.push_back(new PL_BXDQ);
m_menuItems.push_back(new PL_YHLT);
m_menuItems.push_back(new PL_QTCC);
m_menuItems.push_back(new PL_QTCM);
m_menuItems.push_back(new PL_ZHMC);
m_menuItems.push_back(new PL_CBKD);
m_menuItems.push_back(new PL_CDKD);
m_menuItems.push_back(new PL_BZZJ);
m_menuItems.push_back(new PL_YXKD);
m_menuItems.push_back(new PL_ZLKD);
m_menuItems.push_back(new PL_DGKD);
m_menuItems.push_back(new PL_JFZJ);
m_menuItems.push_back(new PL_JFYJ);
m_menuItems.push_back(new PL_JYZJ);
m_menuItems.push_back(new PL_JYXJ);
m_menuItems.push_back(new PL_JJSK);
m_menuItems.push_back(new PL_CDST);
m_menuItems.push_back(new PL_YXCG);
m_menuItems.push_back(new PL_CJSY);
m_menuItems.push_back(new PL_PMFY);
m_menuItems.push_back(new PL_LJGD);
m_menuItems.push_back(new PL_FYGX);
m_menuItems.push_back(new PL_WTLG1);
m_menuItems.push_back(new PL_DJWT);
m_menuItems.push_back(new PL_45WT);
m_menuItems.push_back(new PL_BJWT);
m_menuItems.push_back(new PL_wmerge);
m_menuItems.push_back(new PL_GXLJ);
m_menuItems.push_back(new PL_GXBJ);
m_menuItems.push_back(new PL_TJST1);
m_menuItems.push_back(new PL_DJST);
m_menuItems.push_back(new PL_PXST);
m_menuItems.push_back(new PL_DZST);
m_menuItems.push_back(new PL_EFST);
m_menuItems.push_back(new PL_TJST2);
m_menuItems.push_back(new PL_GXGM);
m_menuItems.push_back(new PL_TJDT);
m_menuItems.push_back(new PL_CRFL);
m_menuItems.push_back(new PL_CDFL);
m_menuItems.push_back(new PL_TJKG);
m_menuItems.push_back(new PL_CRMB);
m_menuItems.push_back(new PL_BZMB);
m_menuItems.push_back(new PL_FZCB);
m_menuItems.push_back(new PL_ZGBQ);
m_menuItems.push_back(new PL_TJZT);
m_menuItems.push_back(new PL_TJHJ);
m_menuItems.push_back(new PL_JSJT);
m_menuItems.push_back(new PL_WLJT);
m_menuItems.push_back(new PL_NLJT);
m_menuItems.push_back(new PL_GJBG);
m_menuItems.push_back(new PL_SBLG);
m_menuItems.push_back(new PL_UXBR);
m_menuItems.push_back(new PL_XGXG);
m_menuItems.push_back(new PL_LGGJ);
m_menuItems.push_back(new PL_CXBG);
m_menuItems.push_back(new PL_CRBQ);
m_menuItems.push_back(new PL_SBDJ);
m_menuItems.push_back(new PL_SBXZ1);
m_menuItems.push_back(new PL_SBXZ2);
m_menuItems.push_back(new PL_SBJC1);
m_menuItems.push_back(new PL_SBJC2);
m_menuItems.push_back(new PL_XGBG1);
m_menuItems.push_back(new PL_XGBG2);
m_menuItems.push_back(new PL_SBGZ);
m_menuItems.push_back(new CO_SFXT1);
m_menuItems.push_back(new CO_SFXT2);
m_menuItems.push_back(new P3_CRZF);
m_menuItems.push_back(new P3_CRDXZF);
m_menuItems.push_back(new P3_CRJZF);
m_menuItems.push_back(new P3_CRQF);
m_menuItems.push_back(new P3_CRZHF);
m_menuItems.push_back(new P3_CRDF);
m_menuItems.push_back(new P3_CRPQF);
m_menuItems.push_back(new P3_CRZSF);
m_menuItems.push_back(new P3_CRFQF);
m_menuItems.push_back(new P3_CRTJF);
m_menuItems.push_back(new P3_CRSLKZF);
m_menuItems.push_back(new P3_CRJYF);
m_menuItems.push_back(new P3_CRPNF);
m_menuItems.push_back(new P3_CRDCF);
m_menuItems.push_back(new P3_GDBC);
m_menuItems.push_back(new P3_CRSSJT);
m_menuItems.push_back(new P3_CRCLJT);
m_menuItems.push_back(new PL_CLBK);
m_menuItems.push_back(new P3_CRXJJT);
m_menuItems.push_back(new PL_CRZF);
m_menuItems.push_back(new PL_CJZF);
m_menuItems.push_back(new PL_AQFM);
m_menuItems.push_back(new PL_CZHF);
m_menuItems.push_back(new PL_CRDF);
m_menuItems.push_back(new PL_CRJF);
m_menuItems.push_back(new PL_CAQF);
m_menuItems.push_back(new PL_STFM);
m_menuItems.push_back(new PL_XTFM);
m_menuItems.push_back(new PL_TJFM);
m_menuItems.push_back(new PL_SSFM);
m_menuItems.push_back(new PL_XSFM);
m_menuItems.push_back(new PL_GMFM);
m_menuItems.push_back(new PL_JYFM);
m_menuItems.push_back(new PL_CBYF);
m_menuItems.push_back(new PL_CZXF);
m_menuItems.push_back(new PL_CCBF);
m_menuItems.push_back(new PL_CPQF);
m_menuItems.push_back(new PL_CJYF);
m_menuItems.push_back(new PL_CPNF);
m_menuItems.push_back(new PL_CDCF);
m_menuItems.push_back(new PL_SSJT);
m_menuItems.push_back(new PL_CLJT);
m_menuItems.push_back(new PL_XJJT);
m_menuItems.push_back(new PL_CRJZ);
m_menuItems.push_back(new PL_QTDJ);
m_menuItems.push_back(new PL_QTDY);
m_menuItems.push_back(new PL_JBWC);
m_menuItems.push_back(new PL_FFTM);
m_menuItems.push_back(new PL_WQTP);
m_menuItems.push_back(new PL_DXCH);
m_menuItems.push_back(new PL_ZJCH);
m_menuItems.push_back(new PL_JLHC);
m_menuItems.push_back(new PL_FZYT);
m_menuItems.push_back(new PL_FZTJ);
m_menuItems.push_back(new PL_PFBZ);
m_menuItems.push_back(new PL_DKBH);
m_menuItems.push_back(new PL_DHFW);
m_menuItems.push_back(new PL_BHYX);
m_menuItems.push_back(new PL_DKBZ);
m_menuItems.push_back(new PL_TGBZ);
m_menuItems.push_back(new PL_YHBZ);
m_menuItems.push_back(new PL_MCMM);
m_menuItems.push_back(new PL_ZXBZ);
m_menuItems.push_back(new PL_XSBZ);
m_menuItems.push_back(new PL_XXBZ);
m_menuItems.push_back(new PL_YCBZ);
m_menuItems.push_back(new PL_YCSB);
m_menuItems.push_back(new PL_ZZBZ);
m_menuItems.push_back(new PL_ZZCB);
m_menuItems.push_back(new PL_GJBZ);
m_menuItems.push_back(new PL_FMBZ1);
m_menuItems.push_back(new PL_FMBZ2);
m_menuItems.push_back(new PL_SBBZ);
m_menuItems.push_back(new HA_FBBZ);
m_menuItems.push_back(new EL_QJBZ1);
m_menuItems.push_back(new EL_QJBZ2);
m_menuItems.push_back(new EL_DLBZ);
m_menuItems.push_back(new CO_EXPORT);
}
void AecObjectUIContext::initMenuItems()
{
analyCfgFile();
// 得到以先种类后再权重排序的集合
std::sort(m_menuItems.begin(), m_menuItems.end(), UIMenuItem::compareItems);
// 得到以id排序的集合
m_UIItemSet.clear();
m_UIItemSet.insert(m_menuItems.begin(), m_menuItems.end());
}
void AecObjectUIContext::AddContext(void * pAppID)
{
if (g_pBaseUIContext == NULL)
{
AcRxClass *pEntityClass = AcDbEntity::desc();
if (pEntityClass && pAppID)
{
g_pBaseUIContext = new AecObjectUIContext();
acedAddObjectContextMenu(pEntityClass, g_pBaseUIContext, pAppID);
}
}
}
void AecObjectUIContext::DelContext()
{
if (g_pBaseUIContext != NULL)
{
AcRxClass *pEntityClass = AcDbEntity::desc();
if (pEntityClass)
acedRemoveObjectContextMenu(pEntityClass, g_pBaseUIContext);
DELETE_PTR(g_pBaseUIContext);
}
}
void AecObjectUIContext::output2Json()
{
CString sPath = FilePath::GetSysDir() + AecObjectUIContext::outputFileName;
AecObjectUIContext::g_pBaseUIContext->items2Json(sPath);
}
#pragma endregion
#pragma region AecDefaultUIContext
AecDefaultUIContext::AecDefaultUIContext(): m_hMenu(NULL) { }
AecDefaultUIContext::~AecDefaultUIContext()
{
if (m_hMenu)
{
::DestroyMenu(m_hMenu);
m_hMenu = NULL;
}
}
void *AecDefaultUIContext::getMenuContext(const AcRxClass *pClass, const AcDbObjectIdArray &ids)
{
if (m_hMenu)
{
::DestroyMenu(m_hMenu);
m_hMenu = NULL;
}
m_hMenu = ::CreatePopupMenu();
if (!m_hMenu) return NULL;
UINT flags(MF_STRING | MF_ENABLED);
int idx(1);
appendMenu(m_hMenu, ID_CONTEXT_MENU_HIDE_SHOWALL, _T("显示全部"), idx++);
appendMenu(m_hMenu, ID_CONTEXT_MENU_PL_DKBH, _T("编号排序"), idx++);
appendMenu(m_hMenu, ID_CONTEXT_MENU_EXPORT_SWTT, _T("三维提图"), idx++);
appendMenu(m_hMenu, NULL, NULL, -1, MF_SEPARATOR);
HMENU hViewPort = ::CreatePopupMenu();
if (hViewPort)
{
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_TOP, _T("俯 视"), 1);
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_BOTTOM, _T("仰 视"), 2);
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_LEFT, _T("左 视"), 3);
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_RIGHT, _T("右 视"), 4);
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_FRONT, _T("前 视"), 5);
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_BACK, _T("后 视"), 6);
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_SWISO, _T("西南等轴测"), 7);
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_SEISO, _T("东南等轴测"), 8);
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_NEISO, _T("东北等轴测"), 9);
appendMenu(hViewPort, ID_CONTEXT_MENU_VIEW_NWISO, _T("西北等轴测"), 10);
appendMenu(m_hMenu, (UINT_PTR)hViewPort, _T("视图"), idx++, MF_POPUP);
}
HMENU hOrbit = ::CreatePopupMenu();
if (hOrbit)
{
appendMenu(hOrbit, ID_CONTEXT_MENU_ORBIT_3D, _T("受约束的动态观察"), 1);
appendMenu(hOrbit, ID_CONTEXT_MENU_ORBIT_3DF, _T("自由动态观察"), 2);
appendMenu(hOrbit, ID_CONTEXT_MENU_ORBIT_3DC, _T("连续动态观察"), 3);
appendMenu(m_hMenu, (UINT_PTR)hOrbit, _T("动态观察"), idx++, MF_POPUP);
}
HMENU hViewStyle = ::CreatePopupMenu();
if (hViewStyle)
{
appendMenu(hViewStyle, ID_CONTEXT_MENU_VSCURRENT_2, _T("二维线框"), 1);
appendMenu(hViewStyle, ID_CONTEXT_MENU_VSCURRENT_W, _T("三维线框视觉样式"), 2);
appendMenu(hViewStyle, ID_CONTEXT_MENU_VSCURRENT_H, _T("三维隐藏视觉样式"), 3);
appendMenu(hViewStyle, ID_CONTEXT_MENU_VSCURRENT_R, _T("真实视觉样式"), 4);
appendMenu(hViewStyle, ID_CONTEXT_MENU_VSCURRENT_C, _T("概念视觉样式"), 5);
appendMenu(m_hMenu, (UINT_PTR)hViewStyle, _T("视觉样式"), idx++, MF_POPUP);
}
return &m_hMenu;
}
void AecDefaultUIContext::onCommand(Adesk::UInt32 cmdIndex)
{
g_cachedCmdIndex = cmdIndex;
acDocManager->sendStringToExecute(acDocManager->curDocument(), _T("_ui_context_command_helper_ "));
}
void AecDefaultUIContext::AddContext(void *pAppID)
{
if (g_pDefaultContext == NULL)
{
if (pAppID)
{
g_pDefaultContext = new AecDefaultUIContext();
acedAddDefaultContextMenu(g_pDefaultContext, pAppID, _T("✦ 上华软件 ✦"));
}
}
}
void AecDefaultUIContext::DelContext()
{
if (g_pDefaultContext != NULL)
{
acedRemoveDefaultContextMenu(g_pDefaultContext);
DELETE_PTR(g_pDefaultContext);
}
}
#pragma endregion
#pragma region AecUIContext
void AecUIContext::AddContext(void *pAppID)
{
AecObjectUIContext::AddContext(pAppID);
AecDefaultUIContext::AddContext(pAppID);
}
void AecUIContext::DelContext()
{
AecObjectUIContext::DelContext();
AecDefaultUIContext::DelContext();
}
#pragma endregion
void _ui_context_command_helper_()
{
if (AecObjectUIContext::g_pBaseUIContext)
{
// 如果是AecObjectUIContext传过来的命令,则在这里处理
UIMenuItem *pItem = AecObjectUIContext::g_pBaseUIContext->findItemById(g_cachedCmdIndex);
if (pItem)
{
// 构建选择集
UIMenuItem::BuildPickFist();
resbuf *pRes = pItem->executeCommand();
if (pRes)
{
SHacedCmd(pRes);
acutRelRb(pRes);
}
return;
}
}
// 下面的逻辑来处理 AecDefaultUIContext
#pragma region default context menu commands
resbuf *pRes(NULL);
switch (g_cachedCmdIndex)
{
case ID_CONTEXT_MENU_PL_DKBH:
pRes = acutBuildList(RTSTR, _T("PL_DKBH"), RTNONE);
break;
case ID_CONTEXT_MENU_HIDE_SHOWALL:
pRes = acutBuildList(RTSTR, _T("PL_XSQB"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_TOP:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_top"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_BOTTOM:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_bottom"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_LEFT:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_left"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_RIGHT:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_right"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_FRONT:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_front"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_BACK:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_back"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_SWISO:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_swiso"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_SEISO:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_seiso"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_NEISO:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_neiso"), RTNONE);
break;
case ID_CONTEXT_MENU_VIEW_NWISO:
pRes = acutBuildList(RTSTR, _T("_view"), RTSTR, _T("_nwiso"), RTNONE);
break;
case ID_CONTEXT_MENU_ORBIT_3D:
pRes = acutBuildList(RTSTR, _T("_3dorbit"), RTNONE);
break;
case ID_CONTEXT_MENU_ORBIT_3DF:
pRes = acutBuildList(RTSTR, _T("_3DFOrbit"), RTNONE);
break;
case ID_CONTEXT_MENU_ORBIT_3DC:
pRes = acutBuildList(RTSTR, _T("_3DCOrbit"), RTNONE);
break;
case ID_CONTEXT_MENU_VSCURRENT_2:
pRes = acutBuildList(RTSTR, _T("vscurrent"), RTSTR, _T("_2"), RTNONE);
break;
case ID_CONTEXT_MENU_VSCURRENT_W:
pRes = acutBuildList(RTSTR, _T("vscurrent"), RTSTR, _T("_W"), RTNONE);
break;
case ID_CONTEXT_MENU_VSCURRENT_H:
pRes = acutBuildList(RTSTR, _T("vscurrent"), RTSTR, _T("_H"), RTNONE);
break;
case ID_CONTEXT_MENU_VSCURRENT_R:
pRes = acutBuildList(RTSTR, _T("vscurrent"), RTSTR, _T("_R"), RTNONE);
break;
case ID_CONTEXT_MENU_VSCURRENT_C:
pRes = acutBuildList(RTSTR, _T("vscurrent"), RTSTR, _T("_C"), RTNONE);
break;
case ID_CONTEXT_MENU_EXPORT_SWTT:
pRes = acutBuildList(RTSTR, _T("ew_swtt"), RTNONE);
break;
default:
break;
}
if (pRes)
{
SHacedCmd(pRes);
acutRelRb(pRes);
}
#pragma endregion
}