[C++ CONNECT] TextBlock::Create - example code

Does anyone have any example C++ code snippets for the TextBlock object? There are some good starting points in MicroStationAPI.chm under the depreciated mdlText_create() function section but I would love to see a working function (or documentation) that just creates a piece of text and places it into a dgn.

Thanks, Loren.

Parents
  • Unknown said:
    Does anyone have any example C++ code snippets for the TextBlock object?

    Search the examples installed with the SDK.  I see several that use a TextBlock for various purposes.

    • incrementTextTool\incrementText.cpp
    • ModifyMultipleElements\ModifyMultipleElements.cpp
    • odbcoledbdemo\odbcoledbdemo.cpp
    • PrintTextSubst\PrintTextSubst.cpp
    • ReportsExample\ReportsExamplePlaceReportTool.cpp
    • TagsExample\TagsExamplePlaceTagFromText.cpp

    Found 56 occurrence(s) in 7 file(s)

     
    Regards, Jon Summers
    LA Solutions

  • Hi Jon,

    None of the examples actually create a text feature from scratch using the Create(...) methods which is what I need to do.  For example,

    1) incrementText.cpp copies an existing textstring with:     TextBlockPtr textBlock = textQuery->GetTextPart (eh, *textPart);

    2)ModifyMultipleElements.cpp  uses GetTextPart -         TextBlockPtr textBlock = textEdit->GetTextPart (*elementToModify, *textPart);

    3)PrintTextSubst.cpp - only uses GetTextPart as well

    4)ReportsExamplePlaceReportTool.cpp = TextBlockPtr textBlock = cell->CreateEmptyTextBlock ();

    5)TagsExamplePlaceTagFromText.cpp - textQuery->GetTextPart (*eeh, *textPart)

    6)odbcoledbdemo.cpp is the closest to what I am looking for  with:             TextBlockPtr tb = TextBlock::Create(*m_TextStyle, *m_ActiveModel);  however no example about size, font,origin, justification etc.

    The closest thing I can find is the depreciated help on  mdlText_create() which says:

    ==================================================================================================================

    // If you want to start with active settings, or from any other DgnTextStyle object...
    TextBlockPtr textBlock = TextBlock::Create (*DgnTextStyle::GetActive (*ISessionMgr::GetActiveDgnFile ()), *ISessionMgr::GetActiveDgnModelP ());
    // -or- If you want to start from an existing template element...
    ElementHandle eh (...);
    TextBlockPtr textBlock = TextHandlerBase::GetFirstTextPartValue (eh);
    if (!textBlock.IsValid ())
    /* ERROR */
    textBlock->Clear ();
    // -or- If you want to start from scratch...
    TextBlockPtr textBlock = TextBlock::Create (*ISessionMgr::GetActiveDgnModelP ());
    // -or- You can manually configure the settings up front...
    TextBlockPropertiesPtr tbProps = TextBlockProperties::Create (...);
    ParagraphPropertiesPtr paraProps = ParagraphProperties::Create (...);
    RunPropertiesPtr runProps = RunProperties::Create (...);
    tbProps.Set... ();
    paraProps.Set... ();
    runProps.Set... ();
    TextBlockPtr textBlock = TextBlock::Create (*tbProps, *paraProps, *runProps, *ISessionMgr::GetActiveDgnModelP ());
    // Then tweak as desired (if you didn't set up properties up-front)...
    // TextParamWide is split between TextBlockProperties, ParagraphProperties, and RunProperties. TextSizeParam (now simply a DPoint2d in UORs) is on RunProperties (via (Get|Set)FontSize).
    TextBlockPropertiesPtr tbProps = textBlock->GetProperties ().Clone ();
    tbProps->Set... ();
    textBlock->SetProperties (*tbProps);
    textBlock->GetParagraphPropertiesForAddR ().Set... ();
    textBlock->GetRunPropertiesForAddR ().Set... ();
    textBlock->SetUserOrigin (...);
    textBlock->SetOrientation (...);
    // Add text...
    textBlock->AppendText (...);
    textBlock->AppendEnterDataField (...);
    // Create the element...
    EditElementHandle eeh;
    if (TextBlock::TO_ELEMENT_RESULT_Success != TextHandlerBase::CreateElement (eeh, NULL /* use the template if you have it */, *textBlock))
    /* ERROR */
    // eeh now contains a text element (or node) that you can AddToModel etc.

    ==================================================================================================================

    This is where I am starting (bold section), however with all the generic "create(...)"s and no other documentation to be found, I am reading through include files to try and decipher what is required where and how.

    I am trying to rewrite my own place text function that I use througout my code:

    "Public int PlaceText ( char text[][256], DPoint3d *pt, double size, int numlines, ULong color, ULong weight, UInt32 levelID, int just, RotMatrix *rMatrix )"

    It creates text from scratch and takes all parameters such as size, font, color etc as input.

    Once again thanks for your help Jon, you continue to be a valued resource to the uStn programming community and frequently come up with solutions far faster than the Bentley support crew (who seem to be ignoring most of these forum posts)

    I will start a SELECT service ticket asking for a place text example and hope that Bentley can supply one - if so I will post it here.

    Loren.

  • Hi Loren,

    This is what I am currently using. 

    	bool GetTextBlock(EditElementHandleR textElm, DPoint3d origin, RotMatrix orientation, std::wstring text, UInt32 textColor, double font_Width, double font_Height, TextElementJustification alignment){
    
    		DPoint2d fontSize;
    		fontSize.x = font_Width;
    		fontSize.y = font_Height;
    
    		TextBlockPropertiesPtr tbProps = TextBlockProperties::Create(*ISessionMgr::GetActiveDgnModelP());
    		ParagraphPropertiesPtr paraProps = ParagraphProperties::Create(*ISessionMgr::GetActiveDgnModelP());
    		RunPropertiesPtr runProps = RunProperties::Create(*DgnTextStyle::GetActive(), *ISessionMgr::GetActiveDgnModelP());
    		tbProps->SetIsViewIndependent(true);
    		paraProps->SetJustification(alignment);
    
    		runProps->SetColor(textColor);
    		runProps->SetFontSize(fontSize);
    		TextBlockPtr textBlock = TextBlock::Create(*tbProps, *paraProps, *runProps, *ISessionMgr::GetActiveDgnModelP());
    
    		textBlock->SetProperties(*tbProps);
    		textBlock->SetUserOrigin(origin);
    		textBlock->SetOrientation(orientation);
    		// Add text...
    		textBlock->AppendText(text.c_str());
    
    
    		if (TEXTBLOCK_TO_ELEMENT_RESULT_Success != TextHandlerBase::CreateElement(textElm, NULL, *textBlock)){
    			return false;
    		}
    
    
    		return true;
    
    	}
    

    Answer Verified By: Loren 

Reply
  • Hi Loren,

    This is what I am currently using. 

    	bool GetTextBlock(EditElementHandleR textElm, DPoint3d origin, RotMatrix orientation, std::wstring text, UInt32 textColor, double font_Width, double font_Height, TextElementJustification alignment){
    
    		DPoint2d fontSize;
    		fontSize.x = font_Width;
    		fontSize.y = font_Height;
    
    		TextBlockPropertiesPtr tbProps = TextBlockProperties::Create(*ISessionMgr::GetActiveDgnModelP());
    		ParagraphPropertiesPtr paraProps = ParagraphProperties::Create(*ISessionMgr::GetActiveDgnModelP());
    		RunPropertiesPtr runProps = RunProperties::Create(*DgnTextStyle::GetActive(), *ISessionMgr::GetActiveDgnModelP());
    		tbProps->SetIsViewIndependent(true);
    		paraProps->SetJustification(alignment);
    
    		runProps->SetColor(textColor);
    		runProps->SetFontSize(fontSize);
    		TextBlockPtr textBlock = TextBlock::Create(*tbProps, *paraProps, *runProps, *ISessionMgr::GetActiveDgnModelP());
    
    		textBlock->SetProperties(*tbProps);
    		textBlock->SetUserOrigin(origin);
    		textBlock->SetOrientation(orientation);
    		// Add text...
    		textBlock->AppendText(text.c_str());
    
    
    		if (TEXTBLOCK_TO_ELEMENT_RESULT_Success != TextHandlerBase::CreateElement(textElm, NULL, *textBlock)){
    			return false;
    		}
    
    
    		return true;
    
    	}
    

    Answer Verified By: Loren 

Children
  • Maury, that was very quick and exactly what I need for a little head start.
    Thanks a bunch, Loren.
  • Hi Maury,

    Have you created a text block element from a template yet? I haven't found any examples of getting the ElementHandleCP, so a template can be passed in with the CreateElement call.

    Thank you,
    Rich
  • No..Sorry, I have not had a need for using a template element.
  • Its cool, figured I would ask. Thanks for responding.
  • Here's what I came up with using Maury's code as a starting point. It adds font, level and will place textnodes instead of text if numlines > 1, and places the text feature into the dgn: 

    sprintf(textarray[0], "File:         %s", szBuffer);
    sprintf(textarray[1], "Project:      %s", g3header.project );
    sprintf(textarray[2], ...
    
    PlaceText(&textarray[0], &textorigin, textsize, 11,  white, 0, EllipLevelID, 
              TextElementJustification::LeftBaseline, rMatrix, L"Courier New");
    
    
    Public int PlaceText ( char text[][255], DPoint3dCP pt, double size, int numlines,
                           ULong color, ULong weight, LevelId levelID,
                           TextElementJustification just,
                           RotMatrixCP rMatrix, WChar *font )
    {
        RotMatrix           rotation;
        EditElementHandle   textElm;
    
    if (rMatrix == NULL) rotation = RotMatrix::FromIdentity();
    else rotation = *rMatrix;
    
    DgnFontP fontP = DgnFontManager::FindSystemFont(font);
    DPoint2d fontSize = {size, size};
    
    TextBlockPropertiesPtr tbProps = TextBlockProperties::Create(*ISessionMgr::GetActiveDgnModelP());
    ParagraphPropertiesPtr paraProps = ParagraphProperties::Create(*ISessionMgr::GetActiveDgnModelP());
    RunPropertiesPtr runProps = RunProperties::Create(*DgnTextStyle::GetActive(), *ISessionMgr::GetActiveDgnModelP());
    tbProps->SetIsViewIndependent(true);
    paraProps->SetJustification(just);
    paraProps->SetLineSpacingValue(size * 1.35); //leading - should be between 120 and 145 percent
    
    runProps->SetColor(color);
    runProps->SetFont(*fontP);
    runProps->SetFontSize(fontSize);
    TextBlockPtr textBlock = TextBlock::Create(*tbProps, *paraProps, *runProps, *ISessionMgr::GetActiveDgnModelP());
    
    textBlock->SetProperties(*tbProps);
    textBlock->SetUserOrigin(*pt);
    textBlock->SetOrientation(rotation);
    
    for (int i=0; i<numlines;i++)
        {
        if (i) textBlock->AppendText(L"\n");
    mdlCnv_convertMultibyteToUnicode(text[i], -1, textW, strlen(text[i]))); textBlock->AppendText(textW); } if (TEXTBLOCK_TO_ELEMENT_RESULT_Success != TextHandlerBase::CreateElement(textElm, NULL, *textBlock)) return(FALSE); ElementPropertiesSetterPtr propsSetter = ElementPropertiesSetter::Create(); propsSetter->SetLevel(levelID); propsSetter->Apply(textElm); textElm.AddToModel(); return(TRUE); }

    Answer Verified By: Loren