Microstation CE: Get actual side of Text element

We're working on a huge porting from 100+ MA applications from V8i to Connect Edition.
One of the problems we're encountering regards the old mdlText_extract API.
In order to determine the size of an existing text element, we so far use the following code:

MSElement* pElement = ...;

char     text[256];
TextSize tileSize;
TextSize textSize;
mdlText_extract(NULL, NULL, NULL, NULL, text, NULL, NULL, NULL, &tileSize, &textSize, pElement);
printf("Text '%s' has tileSize (%.1lf, %.1lf) and textSize (%.1lf, %.1lf)\n",
       text, tileSize.width, tileSize.height, textSize.width, textSize.height);

It has the following output:

Text 'TTF3' has tileSize (525.0, 1200.0) and textSize (1901.5, 1200.0)
Text 'ODF10' has tileSize (420.0, 1200.0) and textSize (1785.7, 1200.0)

I tried the code as suggested by the link:

https://communities.bentley.com/products/programming/microstation_programming/f/microstation-programming---forum/112563/connect-c-textblock-code-to-replace-mdltext_extract

ElementHandle eh(pElement, ACTIVEMODEL);
TextBlockPtr  textBlock = TextHandlerBase::GetFirstTextPartValue(eh);
DPoint2d      fontSize = textBlock->GetRunPropertiesForAdd().GetFontSize();
DRange3d      range = textBlock->GetNominalRange();
printf("FontSize of %ls: (%.1lf, %.1lf)\n", textBlock->ToString().GetWCharCP(), fontSize.x, fontSize.y);
printf("low/high: (%.1lf, %.1lf) / (%.1lf, %.1lf)\n", range.low.x, range.low.y, range.high.x, range.high.y);
printf("doc.width: %.1lf\n", textBlock->GetProperties().GetDocumentWidth());

But this gives me the output:

FontSize of TTF3: (0.0, 12.0)
low/high: (0.0, -12.0) / (0.0, 0.0)
doc.width: 0.0
FontSize of ODF10: (0.0, 12.0)
low/high: (0.0, -12.0) / (0.0, 0.0)
doc.width: 0.0

In other words, I get the height of the text (expressed as the fontsize) but not the width.

Any idea how to get the actual width and height of an existing text element?
I didn't find anything useful within the TextBlock class.

Thanks,

Robert Kock

  • Any idea how to get the actual width and height of an existing text element?

    Continue to use mdlText_extract until Bentley respond...

    #include <deprecated10_0.fdf>

    Note that its signature has changed from V8.

     
    Regards, Jon Summers
    LA Solutions

  • Hi Jon,

    I tried that before but also that function returns 0 for textSize->size.width and the first call returns +Inf as height. Am I doing something wrong?

    Furthermore, I don't know whether this parameter returns the tileSize or the textSize. Anyway, I need both of them.

    Thanks,

    Robert

  • I tried that before...

    While browsing the help doc I came across mdlText_extractW.  That function really is obsolete, because all strings are wide (Unicode) in CONNECT.  However, there's this interesting information appended...

    ElementHandle eh (...); 
    TextBlockPtr textBlock = TextHandlerBase::GetFirstTextPartValue (eh); 
    if (!textBlock.IsValid ()) 
      /* ERROR */

    Often, getting the parameters was only required to modify the text and re-create it. If this is your goal, instead of acquiring the properties, mutate the TextBlock in-place and re-generate the element.

    There is no direct equivalent to getting the element origin (lower-left) from a TextBlock; only user origin is supported. The user origin is the data point / snap point used to create the text, and affects how it flows and positions itself as its content changes. Element origins were always lower-left, and failure to keep this concept synchronized with the user origin resulted in poorly positioned text.

    WString string = textBlock->ToString ();
    DPoint3d userOrigin = textBlock->GetUserOrigin ();
    RotMatrix rotMatrix = textBlock->GetOrientation ();
    If the TextBlock came from a text element, querying the paragraph and run formatting at the beginning is sufficient (since it will not have heterogeneous formatting).
    CaretPtr caret = textBlock->CreateStartCaret ();

    TextParamWide is split between TextBlockProperties, ParagraphProperties, and RunProperties. TextSizeParam (now simply a DPoint2d in UORs) is on RunProperties (via (Get|Set)FontSize).

    textBlock->GetProperties ().Get/Is... ();
    caret->GetCurrentParagraphCP ()->GetProperties ().Get/Is... ();
    caret->GetCurrentRunCP ()->GetProperties ().Get/Is... ();

    There is no direct equivalent to TextEDParam in TextBlock. You must iterate the runs and dynamic_cast to an EdfCharStream to get EDF information.

    To mutate the TextBlock, see methods such as TextBlock::Clear (), TextBlock::AppentText (), TextBlock::InsertText (), TextBlock::Remove (), TextBlock::SetParagraphPropertiesForAdd (), and TextBlock::SetRunPropertiesForAdd ().

    To create the updated element, see TextHandlerBase::CreateElement, then you can use standard EditElementHandle methods (such as EditElementHandle::ReplaceInModel ()).

     
    Regards, Jon Summers
    LA Solutions

  • Hi Jon,

    Thanks again but I noticed that comment before. Didn't help me any further.

    I'm encountering tons of problems while porting old code that interfers with the DGN. Simple dialogs and their management don't give me any trouble (except for a lot of work).

    I guess I need to consider to completely rewrite the code that changes the DGN.

    Thanks,

    Robert

  • Determine the size of an existing text element

    While snuggled up amid autumn blankets, I was browsing the API help — it's a great way to combat insomnia — when I came across the TextString class: Used to draw a single-line collection of like-formatted characters.

    It has some methods that may be useful to you...

    • GetExtents Gets the bounds of this entire instance in local coordinates
    • GetWidth Gets the width of the extents
    • GetHeight Gets the height of the extents

    And several more.  It's not clear how one constructs a TextString.  It looks like you have to use a static Create() method, but I can find no examples.

     
    Regards, Jon Summers
    LA Solutions

  • It's not clear how one constructs a TextString

    TextString is only used for view decoration (for example, you want to draw a text at a fixed point, which doesn't move when you change the view), not for normal text element.

    I today faced a Japanese user's query for how to extract text element's information and wrote below test code in MSCE-U16. It seems work well.

    void extractTextInfo(ElementId myId)
    {
    	ElementHandle eh(myId, ACTIVEMODEL);
    	TextBlockPtr txtBlk = TextElemHandler::GetFirstTextPartValue(eh);
    	WString myStr = txtBlk->ToString();
    	mdlDialog_dmsgsPrint(myStr.GetWCharCP());
    	
    	TextBlockPropertiesCR blkProp = txtBlk->GetProperties();
    	bool isVertical = blkProp.IsVertical();
    	myStr.Sprintf(L"isVertical = %d", isVertical);
    	mdlDialog_dmsgsPrint(myStr.GetWCharCP());
    
    	ParagraphPropertiesR paraProp = txtBlk->GetParagraphPropertiesForAddR();
    	TextElementJustification just = paraProp.GetJustification();
    	double lineSpacing = paraProp.GetLineSpacingValue();
    	myStr.Sprintf(L"just = %d, lineSpacing = %.2f", just, lineSpacing);
    	mdlDialog_dmsgsPrint(myStr.GetWCharCP());
    
    	RunPropertiesR runProp = txtBlk->GetRunPropertiesForAddR();
    	DPoint2d fontSize = runProp.GetFontSize();
    	myStr.Sprintf(L"Width = %.2f, Height = %.2f", fontSize.x, fontSize.y); //in UOR unit
    	mdlDialog_dmsgsPrint(myStr.GetWCharCP());
    }



  • Is there a way to use TextBlockPtr to get the actual height and width of the whole string "Abc"?

  • Is there a way

    Please respect the best practices! Do not steal this over a year old discussion with own new question (especially when your question is specifically about TextBlockPtr).

    Ask in a new post and share all mandatory information like product and its exact version.

    Regards,

      Jan

  • Sorry. I just saw Fu replied the post a month ago. I will ask in a new post.