树状图钩子函数如下,选中最小的叶子节点后,再次点击该叶子节点想取消选中,但没有实现,除非勾选别的叶子节点,请问我要怎么做才能实现这个功能,谢谢!
/** * @简介 对话框树项的钩子函数,在项创建、修改、选中、销毁时进行操作 * @参数 dimP 对话框项消息的指针 * @返回值 无 */ void Dialog_treeHook(DialogItemMessage *dimP) { GuiTreeModel *pModel; DialogItem *diP = dimP->dialogItemP; RawItemHdr *riP = diP->rawItemP; dimP->msgUnderstood = TRUE; switch (dimP->messageType) { case DITEM_MESSAGE_CREATE: { GuiTreeNode *pRoot; MSValueDescr valueDescr; //创建个1列的TreeModel pModel = mdlTreeModel_create(1); //从TreeModel中获取根节点 pRoot = mdlTreeModel_getRootNode(pModel); mdlTreeNode_setDisplayText(pRoot, g_temgraphdatas.siteTree.pwDisplayText); //将结构信息保存到根节点上 valueDescr.SetVoidPtr(&g_temgraphdatas.siteTree); mdlTreeNode_setValue(pRoot, valueDescr, FALSE); //设置在Gui树项中显示的图标的相关信息。 mdlTreeNode_setExpandedIcon(pRoot, ICONID_ToggleOff18Pt, RTYPE_Icon, NULL); mdlTreeNode_setExpandedSelectedIcon(pRoot, ICONID_ToggleOn18Pt, RTYPE_Icon, NULL); mdlTreeNode_setExpandedDeselectedIcon(pRoot, ICONID_ToggleOff18Pt, RTYPE_Icon, NULL); //加载根节点的子节点;其他父节点将在statechangmessage期间加载它们的子节点并展开 treexmpl_nodeLoadChildren(pModel, pRoot, false); //从展开的根开始 mdlTreeNode_expand(pRoot); //设置树项中的GuiTreeModel指针。 mdlDialog_treeSetTreeModelP(riP, pModel); break; } //在加载时递归展开了所有节点,无需响应此操作 /*case DITEM_MESSAGE_STATECHANGING: { GuiTreeNode *pNode; int row; if (dimP->u.stateChanging.changeType == StateChangingType::NodeExpanding)//展开节点时响应 { pModel = mdlDialog_treeGetTreeModelP(riP); row = dimP->u.stateChanging.row; //获取这个父节点&如果还没有填充,填充它 if (NULL != (pNode = mdlTreeModel_getDisplayRowAtIndex(pModel, row)) && !mdlTreeNode_isParentPopulated(pNode)) { bool isSelceted = mdlDialog_treeIsCellSelected(riP, row, 0); treexmpl_nodeLoadChildren(pModel, pNode, isSelceted); } } dimP->u.stateChanging.response = StateChangingResponse::Allow; break; }*/ case DITEM_MESSAGE_BUTTON: { if (dimP->u.button.clicked) { int row = -1, col = -1; bool found; GuiTreeNode *pNode; pModel = mdlDialog_treeGetTreeModelP(riP); bool isSelceted = false; mdlDialog_treeLastCellClicked(&row, &col, riP); if (row != INVALID_ITEM && col != INVALID_ITEM) { row = -1; col = -1; //从树项中检索选择光标的位置。 found = !(mdlDialog_treeGetLocationCursor(&row, &col, riP)); if (found) { if (NULL != (pNode = mdlTreeModel_getDisplayRowAtIndex(pModel, row))) { isSelceted = mdlDialog_treeIsCellSelected(riP, row, col); MyTreeData *pMyData; MSValueDescr valueDescr; mdlTreeNode_getValue(pNode, valueDescr); pMyData = (MyTreeData *)valueDescr.GetVoidPtr(); if (mdlTreeNode_isParent(pNode)) { int projNum = mdlTreeNode_getChildCount(pNode);//项目个数 for (int i = 0; i < projNum; ++i) { GuiTreeNode* projNode = mdlTreeNode_getChildAtIndex(pNode, i); if (mdlTreeNode_isParent(projNode))//为真时表示选择的为ZONE节点 { int projNum2 = mdlTreeNode_getChildCount(projNode); for (int j = 0; j < projNum2; ++j) { GuiTreeNode* projNode2 = mdlTreeNode_getChildAtIndex(projNode, j); MyTreeData *pMyData2; MSValueDescr valueDescr2; mdlTreeNode_getValue(projNode2, valueDescr2); pMyData2 = (MyTreeData *)valueDescr2.GetVoidPtr(); pMyData2->isSelected = isSelceted; if (mdlTreeNode_isExpanded(projNode))//如果节点是展开状态,设置子节点的选中状态 { int row2 = mdlTreeModel_getDisplayRowIndex(pModel, projNode2); mdlDialog_treeSelectCells(riP, row2, row2, 0, 0, isSelceted, true); } } } MyTreeData *pMyData2; MSValueDescr valueDescr2; mdlTreeNode_getValue(projNode, valueDescr2); pMyData2 = (MyTreeData *)valueDescr2.GetVoidPtr(); pMyData2->isSelected = isSelceted; if (mdlTreeNode_isExpanded(pNode))//如果节点是展开状态,设置子节点的选中状态 { int row2 = mdlTreeModel_getDisplayRowIndex(pModel, projNode); mdlDialog_treeSelectCells(riP, row2, row2, 0, 0, isSelceted, true); } } } else if (mdlTreeNode_isLeaf(pNode))//点选叶子节点,直接设置是否选中参数 { pMyData->isSelected = isSelceted; } } } } /*如下函数用来高亮选中的板件及墙体*/ GuiTreeNode* pRoot = mdlTreeModel_getRootNode(pModel); MyTreeData *pMyData; MSValueDescr valueDescr; //获取根节点的数据 mdlTreeNode_getValue(pRoot, valueDescr); pMyData = (MyTreeData *)valueDescr.GetVoidPtr(); g_temgraphdatas.affectedElements.ClearHilite(); g_temgraphdatas.affectedElements.Clear(); if (mdlTreeNode_isParent(pRoot)) { int projNum = mdlTreeNode_getChildCount(pRoot);//zone节点个数 for (int i = 0; i < projNum; ++i) { GuiTreeNode* projNode = mdlTreeNode_getChildAtIndex(pRoot, i); if (mdlTreeNode_isParent(projNode)) { int projNum2 = mdlTreeNode_getChildCount(projNode);//stru节点个数 for (int j = 0; j < projNum2; ++j) { GuiTreeNode* projNode2 = mdlTreeNode_getChildAtIndex(projNode, j); if (mdlTreeNode_isParent(projNode2)) { int projNum3 = mdlTreeNode_getChildCount(projNode2);//板件个数 for (int k = 0; k < projNum3; ++k) { GuiTreeNode* projNode3 = mdlTreeNode_getChildAtIndex(projNode2, k); MyTreeData *pMyData2; MSValueDescr valueDescr2; mdlTreeNode_getValue(projNode3, valueDescr2); pMyData2 = (MyTreeData *)valueDescr2.GetVoidPtr(); if (pMyData2->isSelected) { WString wname(pMyData2->pwDisplayText); char tmpchar[1024]; wname.ConvertToLocaleChars(tmpchar); for (string tmpstring: g_temgraphdatas.ChildNames[tmpchar]) { ElementId id = g_temgraphdatas.mapidAndmodel[tmpstring].ID; DgnModelRefP tmodel = g_temgraphdatas.mapidAndmodel[tmpstring].tModel; if (tmodel == NULL) { continue; } ElementHandle eh(id, tmodel); g_temgraphdatas.affectedElements.Insert(eh.GetElementRef(), tmodel, false);//将选中的板件添加到要高亮的集合中 } } } } } } } } g_temgraphdatas.affectedElements.Hilite();//高亮选中的板件 } } break; case DITEM_MESSAGE_DESTROY: { if (NULL != (pModel = mdlDialog_treeGetTreeModelP(riP))) { //清空选中的板件 g_temgraphdatas.affectedElements.ClearHilite(); g_temgraphdatas.affectedElements.Clear(); if (g_temgraphdatas.siteTree.size > 0) { //释放树节点数据占用的内存 MyTreeData **pChildren; pChildren = g_temgraphdatas.siteTree.children; MyTreeData* pChild = NULL; for (int i = 0; i < g_temgraphdatas.siteTree.size; i++) { pChild = pChildren[i]; if (pChild == NULL) { continue; } if (pChild->bAllowsChildren) { MyTreeData **pChildren2; MyTreeData *pChild2; pChildren2 = pChild->children; for (int j = 0; j < pChild->size; j++) { pChild2 = pChild->children[j]; if (pChild2 != NULL) { delete pChild2; pChild2 = NULL; } } delete[] pChildren2; pChildren2 = NULL; } delete pChild; pChild = NULL; } delete[] pChildren; pChildren = NULL; } g_temgraphdatas.dataSet.destroyElem(g_temgraphdatas.dataSet.root); if (g_temgraphdatas.dataSet.root != NULL) { delete g_temgraphdatas.dataSet.root; g_temgraphdatas.dataSet.root = NULL; } g_importpdmsdatas.FreeAllData(); mdlTreeModel_destroy(pModel, TRUE); } break; } default: dimP->msgUnderstood = FALSE; break; } }
您获取选中节点是如何获取的,应该是有一个对应的函数可以设置其为未选中状态。
mdlDialog_treeLastCellClicked(&row, &col, riP);这个函数可以获取到当前点击的节点吧,然后用isSelceted = mdlDialog_treeIsCellSelected(riP, row, col);这个函数获取该节点的选中状态,最后用这个pMyData->isSelected = isSelceted;设置节点的新状态,但是这里无论是=isSelected还是=!isSelected都没有生效
整个树状控件中必须得有一个节点是当前被选中的。不能做到没有任何一个节点被选中。
MS学习资源:
MicroStation Wednesday视频分享
深入探讨MicroStation DGN基本概念系列
一步步学习MicroStation CE Addin开发
一步步学习MicroStation CE MDL开发
Answer Verified By: 焯辉 洪
好吧 谢谢老师