Detecting a Cached Saved View Attachment in MicroStation CONNECT

Hi All,

I have some legacy VBA code from v8i that I'm trying to port over to the CONNECT versions - it's using a CExpression with a pointer into the referenceFile struct for a specific reference:

Private Declare PtrSafe Function mdlRefFile_getInfo Lib "stdmdlbltin.dll" (ByVal modelRef As LongLong) As LongLong //Declare MDL Function

//Do other stuff

RefInfoP = mdlRefFile_getInfo(modelRef:=oRef.MdlModelRefP) //Get a Pointer to the Reference File

strRefName = "((struct referenceFile *)" & RefInfoP & ")" //Construct the beginning of the CExpression

iCacheValue = GetCExpressionValue(CExpression:=strRefName & "->display.flags.hiddenLineCaching") //Grab the value from the nested members of the struct

This is from the refernce.h header file included with the v8i SDK:

struct  referenceFile
    File_id_desc            file_id;                    /* file identification */
    Ref_display             display;                    /* display information */
    Ref_attach_desc         attach;                     /* attachment description */
    Clip_desc               clip;                       /* clipping descriptor(points separate) */
    UInt32                  *colorMap_deprecated[2];    /* DEPRECATED: element to screen color mappings */
    RefLevelMasks           levelMask;                  /* Level mask */
    MSElementDescrP         readOnlyRefAttachEdP;       /* Attachment descriptor for reference attached during readonly session */
    MiscellaneousRefData    *extraDataP;                /* variable sized part of reference structure. More can be added to it. */
    void                    *additionalDataP[2];        /* Future use */

The struct Ref_display named "display" contains the variable I want, "hiddenLineCaching".

The v8i code generates an error "expected struct/union name" when running in CONNECT, so I went hunting through the documentation.

I think I know (from what I can gather) that the MicrostationAPI has superseded MDL, so looking at the documentation and headers in the CONNECT SDK I found the struct Bentley::DgnPlatform::DgnAttachment.

In the header DgnAttachment.h is a similar struct to what was nested within the original referenceFile struct:

struct  RefDisplayFlags
    UInt32      symbologySet:1;                 //!< The symbology has been set.
    UInt32      hiliteBoundary:1;               //!< Hilite the clip boundary when the DgnAttachment is selected in the reference dialog box (not persistent).
    UInt32      displayHilitedManip:1;          //!< Hilite all elements in the DgnAttachment when the DgnAttachment is the subject of a DgnAttachmnet manipulation command.
    UInt32      displayHilitedSelected:1;       //!< Hilite all elements in the DgnAttachment when the DgnAttachment is selected in the reference dialog box (not persitent).
    UInt32      dontUpdateChildren:1;           //!< Don't display child references (not persistent).
    UInt32      redundant:1;                    //!< This display of this DgnAttachment is the the same as another in the tree of DgnAttachments, so it is not displayed (not persistent).
    UInt32      missingModel:1;                 //!< The file for this DgnAttachment is found, but the model is not (not persistent).
    UInt32      rightNotGranted:1;              //!< The file is found, but we don't have View permissions (not persistent).
    UInt32      namedGroupFound:1;              //!< There is a named group limiting display to only members of that named group (not persistent).
    UInt32      revisionNotAvailable:1;         //!< There is a History revision specified, but that revision was not found in the file (not persistent).
    UInt32      resolvedHistoryTag:1;           //!< A revision is specfied as a tag and found.
    UInt32      revisionFromParent:1;           //!< The revision came from a parent history tag.
    UInt32      findModelByID:1;                //!< Use file_id.modelId to find the target model.
    UInt32      missingGeoCoordApp:1;           //!< This is a Geo referenced attachment, but the GeoCoord capabilities are not available.
    UInt32      missingGeoCoordSys:1;           //!< This is a Geo referenced attachment, but there is no GCS in either the parent model or the DgnAttachment model.
    UInt32      isCircular:1;                   //!< This is a circular reference? (Usually, such a DgnAttachment is not loaded at all).
    UInt32      calculatedTransformUsed:1;      //!< The DgnAttachment is set to be GeoCoord reprojected, but DgnPlatform was were able to substitue an identical linear transform.
    UInt32      namedGroupProcessingComplete:1; //!< We have done the named group processing for this reference already.
    UInt32      hiddenLineCaching:2;            //!< How hidden lines are saved in the file (stored in linkage).
    UInt32      proxyCacheSynchOption:2;
    UInt32      dontAddRefClip:1;
    UInt32      unused:9;

I can see this contains the variable I want to access: hiddenLineCaching.

I have amended the CExpression thus:

 strRefName = "((struct Bentley::DgnPlatform::DgnAttachment *)" & RefInfoP & ")"
 iCacheValue = GetCExpressionValue(CExpression:=strRefName & "->RefDisplayFlags.hiddenLineCaching")

When this runs I receive an error "expected struct/union name".

Reading through the documentation it seems that not all structs are published / accessible, and I'm a long way from a C++ expert, so I'm stumped.

I can't figure out what struct I need to access and get the members of.

Any insight would be greatly appreciated.

Related problem is changing the slot number as well:

strRfName = "((struct referenceFile *)" & RefInfoP & ")"

lngSlotNumber = GetCExpressionValue(CExpression:=strRfName & "->file_id.referenceNum")

I haven't looked into this yet, but the struct is the same, so also doesn't work.

Parents Reply
  • Hi ,

     has provided some very experienced and well-guided advice for the current path of customization you have chosen/have to take.

    For MicroStation VBA if the VBA/COM APIs do not provide the functionality needed, then (as Jon mentions) using the MicroStation VBA or Bentley Macro Recorder(s) are often the next best step to gain insights and reliable path forward.  If none available the next step (especially for new/beginning API developers) would be to determine if any product Key-ins exist that may produce the desired results.  Sometimes key-ins may take some time to identify, may not exist at all, and if/when found and implemented are likely to seem obscure/strange to most future VBA API developers yet are a viable option to work until a better fit solution can be created (or required). Similarly, extending MicroStation VBA code with (Declare) MDL function calls is also likely to look obscure to a future VBA developers and can be fraught with implementation issues, testing and/or not being able to implement due to API implementation specifics, or (Microsoft or Bentley) incompatibilities when attempting to cross native, managed, or COM; memory and runtime boundaries.

    So, imho and given the above...

    First suggestion:

    From what I can tell an Attachment's previous display.flags.hiddenLineCaching was migrated internally to using a public enum of ProxyCachingOption that I do not see a direct public API accessor for.  The closest and possibly easiest way to access this specific item would be use a VBA Property Handler on the VBA attachment object and see if you can locate a "Visible Edge Display" property and value.

    Additional suggestion:

    Since you appear to be doing and have a fair/significant amount and need to access the MDL API, why not consider taking some time to learn and create a more robust and reliable custom MDL "helper application".  This path would certainly provide more: direct, performant, reliable and easily debuggable MDL code/functionality; that can be called from any/many custom VBA applications via your own simple wrapper exported function calls that can survive crossing VBA/COM, native and manage code boundaries via your own custom app key-ins, connections, etc.?  Doing also best ensure consistent access and a desired clean separation between APIs and Interfaces/Implementations.