[CE U15 VBA] DWG:could not find SHX font

How to check which lines are missing shp symbols when opening a DWG file? The message "could not find SHX font [dgnlstyle]" is not very informative.

The missing symbols are replaced with dots or question marks but it is only visual indicator or is there some way to actually scan and find those broken lines?

Parents
  • 1. Scan all text elements

    2. Get text element's textStyle

    3. Judge if the textStyle.Font is msdFontTypeSHX AND textStyle.Font.Name file is exist in the folder(s) which config var MS_FONTPATH, MS_DWGFONTPATH and MS_ACADDIR point to.

    4. If font file doesn't exist, then this text element is missing font.



  • And how does this apply to DWG linestyles which uses missing fonts?

    This posts was posted because Bentley analyst recommended to try VBA approach. I am quite sure that it is out of scope for VBA to check low level linestyle properties but little hope still exists.

  • Sorry. I misunderstood your question. I wrongly thought you are trying to find missing SHX for all text elements.

    Can you upload a such DWG file to let me investigate.



  • As an example, you could start with ANY DWG file, and show us how to find out what SHX font is used for a linestyle. Once we learn how to determine what font is expected, I believe it will be easier to determine if the font is missing. Could we start there? You can use any DWG file you have to see what SHX file is used for any specific linestyle.

    MaryB

    Power GeoPak 08.11.09.918
    Power InRoads 08.11.09.918
    OpenRoads Designer 2021 R2

        

  • I checked MVBA  programming object model and found it doesn't have enough objects/methods to get these info. But C++ API can do this. You can start from here:

    void DWGLineStyleTest()
    {
    	DgnFileP dgnFile = ISessionMgr::GetActiveDgnFile();
    	LineStyleManager::Reinitialize();
    	Int32 LsNumber = LineStyleManager::GetNumberFromName(L"Center", *dgnFile);
    	LsEntryCP LsEntry = LineStyleManager::ResolveLineStyle(LsNumber, dgnFile);
    	WPrintfString wStr(L"LsName=%s, LsNumber=%d", LsEntry->GetStyleName(), LsNumber);
    	mdlDialog_dmsgsPrint(wStr);
    	LsLocationType LsLocType = LsEntry->GetDefinitionLocation();
    	switch (LsLocType)
    	{
    		case LsLocationType::DgnFile:		mdlDialog_dmsgsPrint(L"LsLocationType = DgnFile");		break;
    		case LsLocationType::Importer:		mdlDialog_dmsgsPrint(L"LsLocationType = Importer");		break;
    		case LsLocationType::LinFile:		mdlDialog_dmsgsPrint(L"LsLocationType = LinFile");		break;
    		case LsLocationType::ResourceFile:  mdlDialog_dmsgsPrint(L"LsLocationType = ResourceFile"); break;
    		case LsLocationType::System:		mdlDialog_dmsgsPrint(L"LsLocationType = System");		break;
    		case LsLocationType::Unknown:		mdlDialog_dmsgsPrint(L"LsLocationType = Unknown");		break;
    	}
    	if (LsLocType != LsLocationType::DgnFile)
    		return;
    	LineStyleHandlePtr LsHandle = LineStyleHandle::GetStyleHandle(L"Center", *dgnFile);
    	LsComponentPtr LsComp = LsHandle->GetComponent();
    	LsElementType LsElemType = LsComp->GetType();
    	switch (LsElemType)
    	{
    	case LsElementType::PointSymbol:
    	{
    		mdlDialog_dmsgsPrint(L"LsElementType = PointSymbol");
    		LsPointSymbolComponentPtr LsPtSymbComp = dynamic_cast<LsPointSymbolComponentP>(LsComp.get());
    		MSElementDescrCP   symbolEdP = LsPtSymbComp->GetElements();
    		if (NULL == symbolEdP || symbolEdP->el.ehdr.type != TEXT_ELM)
    			return;
    		//Extract Font info here
    		break;
    	}
    	case LsElementType::Compound:	 
    		mdlDialog_dmsgsPrint(L"LsElementType = Compound");
    		break;
    	case LsElementType::LineCode:
    	{
    		mdlDialog_dmsgsPrint(L"LsElementType = LineCode");
    		LsLineCodeComponentPtr LsLineCodeComp = dynamic_cast<LsLineCodeComponentP>(LsComp.get());
    		break;
    	}
    	case LsElementType::LinePoint:
    	{
    		mdlDialog_dmsgsPrint(L"LsElementType = LinePoint");	
    		LsLinePointComponentPtr LsLinePointComp = dynamic_cast<LsLinePointComponentP>(LsComp.get());
    		LsPointSymbolInfoPtr LsSymbInfo = LsLinePointComp->GetSymbolInfo(0);
    		MSElementDescrCP   symbolEdP = LsSymbInfo->GetSymbol()->GetElements();
    		if (NULL == symbolEdP || symbolEdP->el.ehdr.type != TEXT_ELM)
    			return;
    		//Extract Font info here
    		break;
    	}
    	case LsElementType::Internal:
    		mdlDialog_dmsgsPrint(L"LsElementType = System");
    		break;
    	case LsElementType::RasterImage: 
    		mdlDialog_dmsgsPrint(L"LsElementType = RasterImage");  
    		break;
    	case LsElementType::Unknown:	 
    		mdlDialog_dmsgsPrint(L"LsElementType = Unknown");		
    		break;
    	}
    }

    If the line style's component type is Symbol or LinePoint, we can get a text ElementDescrP which then can further get font info. Line 33 and 53 are the places you can continually do more things.



  • Do we need the SDK to compile code like this? The SDK is not publicly available to just anyone.

    Thank you for the sample code.

    MaryB

    Power GeoPak 08.11.09.918
    Power InRoads 08.11.09.918
    OpenRoads Designer 2021 R2

        

  • Do we need the SDK to compile code like this?

    Yes, to compile native C++ code for MicroStation, SDK is always required (in contrast to NET addins, where the compilation can be done without SDK).

    Regards,

      Jan

  • I figured as much.


    Do you have any suggestions for those of us who are not approved for the SDK? Many companies do not want to sign onto any program such as Bentley Developers Network for simple "dabbling" or the occasional one-off macro.

    MaryB

    Power GeoPak 08.11.09.918
    Power InRoads 08.11.09.918
    OpenRoads Designer 2021 R2

        

Reply Children