I was able to get this working using mdlElmdscr_operation. The code iterates through the cell element's children. If any of the children's level's contain the substring, then it highlights the entire cell element. The trick is in what value you return from the mdlElmdscr_operation. If you don't return SUCCESS, then the iteration stops and just returns your value. I had it return 3 (some int that was not SUCCESS), and if I returned 3 then I highlighted the cell element.
Below you can see the use of the function pointer foo to elmFunc and that foo must be cast to (MdlFunctionP). At the very bottom I have posted all of my code, just in case some weary traveler would like to try it out (only the .cpp file).
The code is shown below
int ElementRefScanCallback(ElementRef eleR, void *callbackArg, ScanCriteriaP pCriteria){ ScanCallBackData* data = (ScanCallBackData*)callbackArg; DgnModelRefP modelRef = mdlScanCriteria_getModel(pCriteria); DgnModelRefP dgnModelRef = modelRef; EditElemHandle eh(eleR, dgnModelRef); MSElement* eleP = eh.GetElementP(); UInt32 filePos = elementRef_getFilePos(eleR); ElementID eleId = eleId = mdlElement_getID(eleP); UInt32 level; mdlElement_getProperties(&level, NULL, NULL, NULL, NULL, NULL, NULL, NULL, eleP); MSWChar* pLevelNameOut = new MSWChar[100]; mdlLevel_getName(pLevelNameOut, 100, dgnModelRef, level); wstring eleLevelNamew(pLevelNameOut); string eleLevelName = narrowWString(eleLevelNamew); if (mdlElement_isComplexHeader(eleP)) { MSElementDescr* elemDescrP; void* params = dgnModelRef; UInt32 worked = mdlElmdscr_getByElemRef(&elemDescrP, eleR, dgnModelRef, TRUE, &filePos); int(*foo)(MSElement *, void *, int, UInt32, MSElementDescr *); foo = &elmFunc; int op = worked = mdlElmdscr_operation(elemDescrP, (MdlFunctionP)foo, params, ELMD_ALL_ONCE); if (op == 3) { mdlSelect_addElement(filePos, dgnModelRef, NULL, TRUE); } } if (eleLevelName.find(levelName) != std::string::npos) {//If the string is contained in the level's name mdlSelect_addElement(filePos, dgnModelRef, NULL, TRUE); } return SUCCESS; } int elmFunc(MSElement *element,void *params,int operation,UInt32 offset,MSElementDescr *elemDscrP) { DgnModelRefP dgnModelRef = (DgnModelRefP)params; UInt32 filePos = mdlElmdscr_getFilePos(elemDscrP); UInt32 level; mdlElement_getProperties(&level, NULL, NULL, NULL, NULL, NULL, NULL, NULL, element); MSWChar* pLevelNameOut = new MSWChar[100]; mdlLevel_getName(pLevelNameOut, 100, dgnModelRef, level); wstring eleLevelNamew(pLevelNameOut); string eleLevelName = narrowWString(eleLevelNamew); if (eleLevelName.find(levelName) != std::string::npos) {//If the string is contained in the level's name mdlSelect_addElement(filePos, dgnModelRef, NULL, TRUE); return 3; } return SUCCESS; }
#include <mdl.h> #include <toolsubs.h> #include <basetype.h> #include <malloc.h> #include <msrmgr.h> #include <mstypes.h> #include <string.h> #include <msparse.fdf> #include <msstate.fdf> #include <mssystem.fdf> #include <dlmsys.fdf> #include <mscnv.fdf> #include <msfile.fdf> #include <msdialog.fdf> #include <dlogids.h> #include <mswindow.fdf> #include <msdgnmodelref.fdf> #include <msdgnlib.fdf> #include <mselemen.fdf> #include <mselmdsc.fdf> #include <mscell.fdf> #include <msmline.fdf> #include <mstextstyle.fdf> #include <listmodel.fdf> #include <changetrack.fdf> #include <mselems.h> #include <scanner.h> #include <userfnc.h> #include <cmdlist.h> #include <string.h> #include <toolsubs.h> #include <dlogman.fdf> #include <mssystem.fdf> #include <mslinkge.fdf> #include <msscan.fdf> #include <msoutput.fdf> #include <msparse.fdf> #include <msrsrc.fdf> #include <mslocate.fdf> #include <msstate.fdf> #include <msscancrit.fdf> #include <mstypes.h> #include <msscancrit.fdf> #include <elementref.h> #include <msdgnobj.fdf> #include <msdgncache.h> #include <ditemlib.fdf> //#include <FontManager.h> #include <mselementtemplate.fdf> #include <msdimstyle.fdf> #include <msdim.fdf> #include <namedexpr.fdf> #if !defined (DIM) #define DIM(a) ((sizeof(a)/sizeof((a)[0]))) #endif USING_NAMESPACE_BENTLEY_USTN USING_NAMESPACE_BENTLEY_USTN_ELEMENT USING_NAMESPACE_TEXT #include <iostream> #define LINEAR_TEMPLATE_NAME L"CreatedGroup\\Created Linear Template" #define SHAPE_TEMPLATE_NAME L"CreatedGroup\\Created Shape Template" #define HATCH_TEMPLATE_NAME L"CreatedGroup\\Created Hatch Template" #define AREAPATTERN_TEMPLATE_NAME L"CreatedGroup\\Created AreaPattern Template" #define CELL_TEMPLATE_NAME L"CreatedGroup\\Created Cell Template" #define TEXT_TEMPLATE_NAME L"CreatedGroup\\Created Text Template" #define MLINE_TEMPLATE_NAME L"CreatedGroup\\Created MLine Template" #define DIMENSION_TEMPLATE_NAME L"CreatedGroup\\Created Dimension Template" #define HEADER_TEMPLATE_NAME L"CreatedGroup\\Header" #define COMPONENT1_TEMPLATE_NAME L"CreatedGroup\\Component1" #define COMPONENT2_TEMPLATE_NAME L"CreatedGroup\\Component2" #include <iostream> #include <string> #include <fstream> #include <iostream> #include <msselect.fdf> #include <msmisc.fdf> #include <msassoc.fdf> #include <ElemHandle.h> #include <ElementAgenda.h> #include <msview.fdf> #include <msreffil.fdf> #include <mselmdsc.fdf> #include <leveltable.fdf> #include <mswrkdgn.fdf> #include <msvar.fdf> #include <mstmatrx.fdf> //__declspec(dllexport) ElementID mdlElement_getID(); #include <iostream> #include <fstream> #include <sstream> //#include "boost/lexical_cast.hpp" using namespace std; int ElementRefScanCallback(ElementRef eleR, void *callbackArg, ScanCriteriaP); int ScanForLinearElements(DgnModelRefP modelRef); int elmFunc(MSElement *element, void *params, int operation, UInt32 offset, MSElementDescr *elemDscrP); void IterateNestedModels(DgnModelRefP dgnModelRef); string narrowWString(wstring w); typedef struct scancallback_ { string levelName; } ScanCallBackData; string narrowWString(wstring w) { string s(w.begin(), w.end()); return s; } string levelName; extern "C" DLLEXPORT int MdlMain(int argc, char *argv[]){ if (argc == 3){ levelName = argv[2]; } else { mdlDialog_cmdNumberQueue(FALSE, CMD_MDL_UNLOAD, mdlSystem_getCurrTaskID(), TRUE);//Unload program return SUCCESS;//end program } DgnModelRefP dgnModelRef = mdlModelRef_getActive(); IterateNestedModels(dgnModelRef); ScanForLinearElements(dgnModelRef); mdlDialog_cmdNumberQueue(FALSE, CMD_MDL_UNLOAD, mdlSystem_getCurrTaskID(), TRUE); return SUCCESS; } void IterateNestedModels(DgnModelRefP dgnModelRef) { ModelRefIteratorP iterator; DgnModelRefP modelRef; mdlModelRefIterator_create(&iterator, dgnModelRef, MRITERATE_PrimaryChildRefs, 0); while (NULL != (modelRef = mdlModelRefIterator_getNext(iterator))) { ScanForLinearElements(modelRef); IterateNestedModels(modelRef);//This is the iterator } } int ScanForLinearElements(DgnModelRefP modelRef) { UShort typeMask[7]; ScanCallBackData data; data.levelName = levelName;//levelName is global here ScanCriteriaP criteria = mdlScanCriteria_create(); mdlScanCriteria_setModel(criteria, modelRef); // Tell the scanner to call our function for each element found mdlScanCriteria_setReturnType(criteria, MSSCANCRIT_ITERATE_ELMREF, FALSE, TRUE); mdlScanCriteria_setElemRefCallback(criteria, ElementRefScanCallback, &modelRef); // Tell the scanner we're interested only in certain types of element // See mselems.h for the TMSK0_ macros memset(typeMask, 0, sizeof(typeMask)); typeMask[0] = TMSK0_CELL_LIB | TMSK0_CELL_HEADER | TMSK0_LINE | TMSK0_LINE_STRING | TMSK0_GROUP_DATA | TMSK0_SHAPE | TMSK0_TEXT_NODE | TMSK0_DIG_SETDATA | TMSK0_DGNFIL_HEADER | TMSK0_LEV_SYM | TMSK0_CURVE | TMSK0_CMPLX_STRING | TMSK0_CONIC | TMSK0_CMPLX_SHAPE | TMSK0_ELLIPSE | TMSK0_ARC; typeMask[1] = TMSK1_TEXT | TMSK1_SURFACE | TMSK1_SOLID | TMSK1_BSPLINE_POLE | TMSK1_POINT_STRING | TMSK1_CONE | TMSK1_BSPLINE_SURFACE | TMSK1_BSURF_BOUNDARY | TMSK1_BSPLINE_KNOT | TMSK1_BSPLINE_CURVE | TMSK1_BSPLINE_WEIGHT; typeMask[2] = TMSK2_DIMENSION | TMSK2_SHAREDCELL_DEF | TMSK2_SHARED_CELL | TMSK2_MULTILINE | TMSK2_ATTRIBUTE | TMSK2_TYPE44 | TMSK2_DGNSTORE_HDR; typeMask[4] = TMSK4_MICROSTATION_ELM; typeMask[5] = TMSK5_RASTER_HDR | TMSK5_RASTER_COMP | TMSK5_RASTER_LINK | TMSK5_RASTER_REFCMPN | TMSK5_RASTER_HIERARCHY | TMSK5_RASTER_HIERARCHYCMPN | TMSK5_RASTER_FRAME | TMSK5_TABLE_ENTRY | TMSK5_TABLE; typeMask[6] = TMSK6_MATRIX_HEADER | TMSK6_MATRIX_INT_DATA | TMSK6_MATRIX_DOUBLE_DATA | TMSK6_MESH_HEADER | TMSK6_EXTENDED | TMSK6_EXTENDED_NONGRAPHIC_ELM | TMSK6_VIEW_GROUP | TMSK6_VIEW | TMSK6_LEVEL_MASK | TMSK6_REFERENCE_ATTACH; //mdlScanCriteria_setElementTypeTest(criteria, typeMask, sizeof(typeMask)); mdlScanCriteria_setDrawnElements(criteria); int e = mdlScanCriteria_scan(criteria, NULL, NULL, NULL); mdlScanCriteria_free(criteria); return 0; } int ElementRefScanCallback(ElementRef eleR, void *callbackArg, ScanCriteriaP pCriteria){ ScanCallBackData* data = (ScanCallBackData*)callbackArg; DgnModelRefP modelRef = mdlScanCriteria_getModel(pCriteria); DgnModelRefP dgnModelRef = modelRef; EditElemHandle eh(eleR, dgnModelRef); MSElement* eleP = eh.GetElementP(); UInt32 filePos = elementRef_getFilePos(eleR); ElementID eleId = eleId = mdlElement_getID(eleP); UInt32 level; mdlElement_getProperties(&level, NULL, NULL, NULL, NULL, NULL, NULL, NULL, eleP); MSWChar* pLevelNameOut = new MSWChar[100]; mdlLevel_getName(pLevelNameOut, 100, dgnModelRef, level); wstring eleLevelNamew(pLevelNameOut); string eleLevelName = narrowWString(eleLevelNamew); if (mdlElement_isComplexHeader(eleP)) { MSElementDescr* elemDescrP; void* params = dgnModelRef; UInt32 worked = mdlElmdscr_getByElemRef(&elemDescrP, eleR, dgnModelRef, TRUE, &filePos); int(*foo)(MSElement *, void *, int, UInt32, MSElementDescr *); foo = &elmFunc; int op = worked = mdlElmdscr_operation(elemDescrP, (MdlFunctionP)foo, params, ELMD_ALL_ONCE); if (op == 3) { mdlSelect_addElement(filePos, dgnModelRef, NULL, TRUE); } } if (eleLevelName.find(levelName) != std::string::npos) {//If the string is contained in the level's name mdlSelect_addElement(filePos, dgnModelRef, NULL, TRUE); } return SUCCESS; } int elmFunc(MSElement *element,void *params,int operation,UInt32 offset,MSElementDescr *elemDscrP) { DgnModelRefP dgnModelRef = (DgnModelRefP)params; UInt32 filePos = mdlElmdscr_getFilePos(elemDscrP); UInt32 level; mdlElement_getProperties(&level, NULL, NULL, NULL, NULL, NULL, NULL, NULL, element); MSWChar* pLevelNameOut = new MSWChar[100]; mdlLevel_getName(pLevelNameOut, 100, dgnModelRef, level); wstring eleLevelNamew(pLevelNameOut); string eleLevelName = narrowWString(eleLevelNamew); if (eleLevelName.find(levelName) != std::string::npos) {//If the string is contained in the level's name mdlSelect_addElement(filePos, dgnModelRef, NULL, TRUE); return 3; } return SUCCESS; }