最近使用NX二次开发,需要用到集列表,也就是SetList这个控件,然而网上相关的资料和范例实在是太少,有幸找到《NX二次开发-BlockUI集列表的使用技巧》和《UG(NX)二次开发 BlockUI 集列表使用方法》,这两篇文章,对我的帮助很大,但是因为使用的编程语言不同(我使用的是c++),仍然遇到了很多困难,不过最终在我不断的摸索和尝试下,终于有个完整的使用流程,特此分享给需要的同学,避免跟我一样一下子不知道从何下手。
想快速获取结果的可以直接看代码,想看一下问题的解决过程的,且听我娓娓道来。
对于集列表,它不同于一般的控件,一般的控件直接添加即可,而集列表则需要添加种子块,那么种子块如何添加呢,下面我将详细说明这个步骤。
项目原因,我就使用nx8.0的32位版本来做说明,其他版本类似。
首先,打开任意项目,然后打开块UI样式编辑器,如下图所示:
新建或者打开任意界面,并且添加集列表:
此时提示“错误:缺少种子块”。
我们需要新建或者使用已有的任意对话框dlx文件,并且在下方红色方框位置填入文件名(dlx在同一目录的情况下),如果种子块在不同目录,则使用种子块dlx文件的全路径。
此时,错误提示消失,并且自动加入到主界面。
在集列表中可以设置是否自动展开以及列数等。
以上是界面相关,下面进入代码部分,这部分主要是我在前面两篇文章的的帮助下摸索和尝试出来的,特此分享关键代码,项目原因部分不重要的代码实现无法公开,可以自己考虑实现,或者查阅资料,调用UG自带的函数。
针对集列表,主要有两个回调函数,添加和删除按钮时的回调函数,我无法直接找到相关的c++范例,不过后来我发现,可以查看函数的声明和参数来确定回调函数的样式。
比如:对于集列表m_pListCurves,输入set可以智能提示有如下回调函数:
而我们需要的就是AddHandler和DelHandler,那么如何添加这两个回调函数呢,我们可以按F12,进去声明看一下:
然后在AddCallback的地方再按下F12,此时就可以看到如下的声明:
这代表着,这个回调函数是以int为返回值,以 NXOpen::BlockStyler::SetList *为参数类型的函数,同理,在下方可以看到Del的回调函数样式:
typedef NXOpen::Callback2<int, NXOpen::BlockStyler::SetList *, NXOpen::BlockStyler::UIBlock *> DeleteCallback;
形如:
// 集列表回调函数
int addCurve_cb(NXOpen::BlockStyler::SetList *);
int deleteCurve_cb(NXOpen::BlockStyler::SetList *, NXOpen::BlockStyler::UIBlock *);
于是,得到下面的代码:
// 这是添加按钮的
m_pListCurves->SetAddHandler(make_callback(this, &CAMFeatureAddCurveUI::addCurve_cb));
// 这是删除按钮的
m_pListCurves->SetDeleteHandler(make_callback(this, &CAMFeatureAddCurveUI::deleteCurve_cb));
供参考。
为了在点击添加按钮的时候,可以自动有一些动作,比如初始化界面等(这里说一下,nx初始化界面一般是放在dialogShown_cb()中的,但是因为这个是作为list控件的种子块,dialogShown_cb()并不会执行,所以这种情况下的初始化应该放在添加按钮的回调函数中)。
代码供参考:
int CAMFeatureAddCurveUI::addCurve_cb(NXOpen::BlockStyler::SetList *pList)
{
// 点击添加按钮的时候,会添加一个你设置的seedDlx的那个ui
UIBlock *pBlockUI = m_pListCurves->AddNewSet(true);
// 这个是设置显示的文本,第一列是序号,后面是的列自己设置即可
int nNewIndex = m_pListCurves->GetItems().size();
NXString stIndex = AUTUMOONString::to_string(nNewIndex).c_str();
stIndex = "曲线组" + stIndex;
std::vector<NXString> vContenInList;
vContenInList.push_back(stIndex);
m_pListCurves->SetItemText(pBlockUI, vContenInList);
// 针对控件的初始化
// 强转成NXOpen.BlockStyler.CompositeBlock,类似一个UI的集合,里面可以添加很多ui
NXOpen::BlockStyler::CompositeBlock *compositeBlock = (NXOpen::BlockStyler::CompositeBlock *)pBlockUI;
// 分别查找对应的控件
NXOpen::BlockStyler::UIBlock *edge_select0 = compositeBlock->FindBlock("edge_select0");
NXOpen::BlockStyler::UIBlock *enumCamMethod = compositeBlock->FindBlock("enumCamMethod");
NXOpen::BlockStyler::UIBlock *enumMaterialSide = compositeBlock->FindBlock("enumMaterialSide");
NXOpen::BlockStyler::UIBlock *doubleProcessDis = compositeBlock->FindBlock("doubleProcessDis");
NXOpen::BlockStyler::UIBlock *doubleSelToolDia = compositeBlock->FindBlock("doubleSelToolDia");
NXOpen::BlockStyler::UIBlock *toggleRough = compositeBlock->FindBlock("toggleRough");
NXOpen::BlockStyler::UIBlock *toggleFinish = compositeBlock->FindBlock("toggleFinish");
doubleSelToolDia->AUTUMOONBLock_SetDouble(63.0);
enumCamMethod->AUTUMOONBLock_SetEnum(0);
enumMaterialSide->AUTUMOONBLock_SetEnum(0);
edge_select0->Focus();
// 计算加工距离
Vector3d vec3d = m_pVectorZ->GetProperties()->GetVector("Vector");
AUTUMOONMathVector3d ivecUserZ(vec3d.X, vec3d.Y, vec3d.Z);
// 计算加工距离
double dProcessDistance =
CAMFeaRecognition::GetProcessDistanceEx(m_cfFeature.m_pvFaces, m_cfFeature.m_eCAMMachiningType, ivecUserZ);
doubleProcessDis->AUTUMOONBLock_SetDouble(dProcessDistance);
return 0;
}
其中的关键是获取块指针,用FindBlock来实现。
删除功能的回调函数,基本可以通用,如果你不需要进行特别处理的话。
int CAMFeatureAddCurveUI::deleteCurve_cb(NXOpen::BlockStyler::SetList *pList, NXOpen::BlockStyler::UIBlock *pBlockUI)
{
// GetSelected()返回选择item的UIblock的数组
for (int i = 0; i < m_pListCurves->GetSelected().size(); i++)
{
// 删掉即可
m_pListCurves->Delete(m_pListCurves->GetSelected()[i]);
}
return 0;
}
实际上,你会发现,如果你的子块不需要特殊的处理的话,你甚至都不需要子块对应的hpp文件和cpp文件,因为无论是设置还是读取,都是在集列表所在的主界面中实现的。
下面讲一下,如何获取集列表中的值,实际上在上面的回调函数代码中已经有了,不过这里还是专门写一下,代码供参考:
//author:autumoon
//邮箱:9506@163.com
//日期:2023-08-17
//---------Enter your code here-----------
// 用户选择的方向
Vector3d vec3d = m_pVectorZ->GetProperties()->GetVector("Vector");
AUTUMOONMathVector3d ivecUserZ(vec3d.X, vec3d.Y, vec3d.Z);
if (m_cfFeature.m_pvFaces.size() == 0)
{
uc1601("请选择面!", 1);
return -1;
}
Face *pFirstFace = m_cfFeature.m_pvFaces[0];
AUTUMOONMathVector3d vecLaw = CAMFeaRecognition::GetFaceLawEx(pFirstFace);
if (vecLaw.IsSameDirection(ivecUserZ))
{
m_cfFeature.m_eCAMMachiningType = eMachiningTypeFront;
}
else if (vecLaw.IsParallel(ivecUserZ))
{
m_cfFeature.m_eCAMMachiningType = eMachiningTypeReverse;
}
else
{
m_cfFeature.m_eCAMMachiningType = eMachiningTypeFiveAxis;
}
// 添加平面铣颜色
m_cfFeature.m_nFeatureColor = pFirstFace->Color();
// 根据平面铣的当前z方向,得到编程时的坐标系
CAMFeaRecognition::GenerateWCSCoorByFeature(&m_cfFeature, ivecUserZ);
// 类型
int nSelIndex = m_pEnumMillType->AUTUMOONBLock_GetEnumValue;
m_cfFeature.m_eCAMMachiningMode = static_cast<ProcessingType>(eProcessingTypeFlatMillingOpen + nSelIndex);
// 从list列表获取曲线信息
std::vector<UIBlock *> vAllBlocks = m_pListCurves->GetItems();
for (int i = 0; i < vAllBlocks.size(); i++)
{
// 强转成NXOpen.BlockStyler.CompositeBlock,类似一个UI的集合,里面可以添加很多ui
NXOpen::BlockStyler::CompositeBlock *compositeBlock =
(NXOpen::BlockStyler::CompositeBlock *)vAllBlocks[i];
// 分别查找对应的控件
NXOpen::BlockStyler::UIBlock *edge_select0 = compositeBlock->FindBlock("edge_select0");
NXOpen::BlockStyler::UIBlock *enumCamMethod = compositeBlock->FindBlock("enumCamMethod");
NXOpen::BlockStyler::UIBlock *enumMaterialSide = compositeBlock->FindBlock("enumMaterialSide");
NXOpen::BlockStyler::UIBlock *doubleProcessDis = compositeBlock->FindBlock("doubleProcessDis");
NXOpen::BlockStyler::UIBlock *doubleSelToolDia = compositeBlock->FindBlock("doubleSelToolDia");
NXOpen::BlockStyler::UIBlock *toggleRough = compositeBlock->FindBlock("toggleRough");
NXOpen::BlockStyler::UIBlock *toggleFinish = compositeBlock->FindBlock("toggleFinish");
vector<TaggedObject *> selectedCurves = edge_select0->AUTUMOONBLock_GetSelectedObjects;
if (m_cfFeature.m_vpCurveExs.size())
{
m_cfFeature.m_vpCurveExs.clear();
}
for (auto it = selectedCurves.begin(); it != selectedCurves.end(); ++it)
{
Curve *pCurveSel = static_cast<Curve *>(*it);
CurveEx *pCurveEx = new CurveEx(pCurveSel);
// 加工曲线位置
pCurveEx->m_nCurveCamMethod = enumCamMethod->AUTUMOONBLock_GetEnumValue;
// 材料侧
pCurveEx->m_nMaterialSide = enumMaterialSide->AUTUMOONBLock_GetEnumValue + 1;
// 加工距离
pCurveEx->m_dProcessDistance = doubleProcessDis->AUTUMOONBLock_GetDoubleValue;
// 刀具直径
pCurveEx->m_dSelToolDia = doubleSelToolDia->AUTUMOONBLock_GetDoubleValue;
// 粗加工
if (toggleRough->AUTUMOONBLock_GetLogicalValue)
{
pCurveEx->m_nMachiningMethod |= MACHINING_METHOD_ROUGH;
}
else
{
pCurveEx->m_nMachiningMethod &= ~MACHINING_METHOD_ROUGH;
}
// 半精加工和精加工
if (toggleFinish->AUTUMOONBLock_GetLogicalValue)
{
pCurveEx->m_nMachiningMethod |= MACHINING_METHOD_HALF_FINISH | MACHINING_METHOD_FINISH;
}
else
{
pCurveEx->m_nMachiningMethod &= ~(MACHINING_METHOD_HALF_FINISH | MACHINING_METHOD_FINISH);
}
// 加工面高度(从当前主界面获取)
pCurveEx->m_dDeepOffset = m_DoubleFaceHeight->AUTUMOONBLock_GetDoubleValue;
m_cfFeature.m_vpCurveExs.push_back(pCurveEx);
}
}
int nFindIndex = -1;
for (int i = 0; i < m_vFeatures.size(); ++i)
{
CAMFeature &cf = m_vFeatures[i];
if (cf.m_pvFaces.size())
{
Face *pFaceCur = cf.m_pvFaces[0];
if (pFaceCur == pFirstFace)
{
nFindIndex = i;
// 释放原来的
if (cf.m_vpCurveExs.size())
{
CurveEx::ReleaseCurveEx(cf.m_vpCurveExs);
}
cf = m_cfFeature;
break;
}
}
}
// 添加
if (nFindIndex == -1)
{
m_vFeatures.push_back(m_cfFeature);
}
// 复位控件
resetAllCtrlBlock();
// 面选择重新选择为焦点
m_pSelFace->Focus();
获取的关键是这一段:
此代码也是我尝试出来的结果,当发现可以正常工作的时候,我还是很开心的,毕竟这个代码带着一点点猜想的成分。
至此,集列表的创建以及回调函数,以及获取集列表上任意控件的值就已经全部结束了。
欢迎交流与讨论,欢迎留言或者私信我寻求帮助,谢谢。