[CONNECT C++] Editing a text element from its eeh

Greetings,

I'm currently struggling with some text modifications (C++ MDL, Microstation Connect Edition).

I'm importing text elements from a DWG file into Microstation. I'd like to change some of their attributes before adding them into the DGN active Model. Here a simplified pseudo code of how I create the EditElementHandle (this is not my true code, in reality I have something a little bit more complex, so here a synthetic description):

// modelP is the model from an attached DWG stored as DgnAttachmentP
    for (PersistentElementRefP const& elemRef : modelP->GetElementsCollection())
    {
      DgnPlatform::EditElementHandle* elmhandle = new DgnPlatform::EditElementHandle(elemRef->GetElementId(), modelP);
      if (elmhandle->GetElementType() == Bentley::DgnPlatform::MSElementTypes::TEXT_ELM)
      {
        // modify text here
        changeTxtSizeAndFont(*elmhandle, true, newFont, true, newHeight, true, newWidth, true, newColor);
        // My problem is here !

        // then copy the DWG text element in the DGN file
        DgnPlatform::ElementCopyContext copyContext(ACTIVEMODEL);
        copyContext.SetSourceModelRef(elmhandle->GetModelRef());
        copyContext.SetTransformToDestination(true);
        copyContext.SetWriteElements(true);
        copyContext.SetKeepRefColorIndexOnCopy(true);
        copyContext.DoCopy(*elmhandle);
      }


The problem now, I created this function "changeTxtSizeAndFont" in order to change the text attributes before copying the element.

The debugger go into every part of the function, but nothing change. The imported text has its original color, size, and font. Am I missing something ?

void changeTxtSizeAndFont(DgnPlatform::EditElementHandle & eeh,
                          bool changeFont,   UInt32 newFont, 
                          bool changeHeight, double newHeight,
                          bool changeWidth,  double newWidth,
                          bool changeColor,  UInt32 newColor)
{
  ElementPropertiesSetterPtr remapper = ElementPropertiesSetter::Create();
  TextBlockPtr textBlockP             = DgnPlatform::TextHandlerBase::GetFirstTextPartValue(eeh).GetR();
  RunPropertiesPtr runPropP           = textBlockP->GetRunPropertiesForAdd().Clone();

  if (changeFont)
  {
    DgnFontCP newDgnFont = DgnPlatform::DgnFontManager::GetFontByNumber(newFont, ACTIVEMODEL);
    remapper->SetFont(*newDgnFont);
  }
  
  DPoint2d fontSize;
  fontSize.x = runPropP->GetFontSize().x;
  fontSize.y = runPropP->GetFontSize().y;
  if (changeHeight)
    fontSize.x = newHeight;
  if (changeWidth)
    fontSize.y = newWidth;
  runPropP->SetFontSize(fontSize);
  textBlockP->SetRunPropertiesForAdd(*runPropP);
  
  if (changeColor)
    remapper->SetColor(newColor);
  
  remapper->Apply(eeh);
}


Any idea ?

Thank you by advance for your answers !

  • Here a simplified pseudo code of how I create the EditElementHandle
    DgnPlatform::EditElementHandle* elmhandle = new DgnPlatform::EditElementHandle(elemRef->GetElementId(), modelP);

    An EditElementHandle (and its base class ElementHandle) are C++ smart pointers that wrap an MSElementDecr*.  You don't need to allocate memory on the heap for an element handle (you have a memory leak): just declare a local variable which will handle memory management for you...

    EditElementHandle eeh (elemRef->GetElementId(), modelP);

    Remapper

    You create a remapper and use it to possible change colour and font, then remapper->Apply(eeh);

    Do you see a change to colour or font?

    TextBlock

    You get a TextBlock from the element and modify it, but you don't apply those changes to the DGN element.  At some point you need to create a new element, and use that to replace the existing element.  These comments from the MicroStationAPI help doc may help:

    • To modify the text of an element, use the ITextQuery and ITextEdit interfaces to get/set the text
    • To create a free-standing text element from a TextBlock, use TextHandlerBase::CreateElement

     
    Regards, Jon Summers
    LA Solutions

  • What status is being returned by remapper->Apply? Couple problems with your code that jump out:

    1) Nothing you do with TextBlock will have any affect, it's just an in-memory representation of your text element. Need to update the element from the modified text block.

    2) You can't set a font id (or any other id) from the ACTIVEMODEL on an element from a different file, ids are file specific. The main purpose of ElementCopyContext is to remap ids from the source to destination and bring along things like fonts, linestyles, etc. that currently don't exist in the destination.

    So what happens when you set a font id from the ACTIVEMODEL on your element (assuming remapper->Apply didn't just return false because of an invalid font), is that when DoCopy is called, it will try to find a font with that id in the DWG file, and then try to remap/clone the font into the destination.

    HTH

    -B