Place Text through VBA

Hi all,

Trying to work out how to place a predefined text string onto the drawing, without bring up any menus or options.

Have tried

    CadInputQueue.SendKeyin "place text"
CadInputQueue.SendKeyin sText

But the keyin window appears and i cant work out how to close it.

Also have tried
    CadInputQueue.SendKeyin "place dialogtext icon"
CadInputQueue.SendMessageToApplication "WORDPROC", sText

Which brings up the word processor but doesn't input the text.

Ideally i'd like to simple click a button on a form and the text appears on the drawing at the cursor ready for the user to select the location.

Cheers,

Rob

Parents
  • Unknown said:
    CadInputQueue.SendKeyin "place text"
    CadInputQueue.SendKeyin sText

    In general, if you queue a user key-in using VBA then the result is the same as if you performed that task manually.  In other words, MicroStation can't distinguish between you typing place dialogtext icon and VBA queueing place dialogtext icon.

    If a key-in causes MicroStation to pop a dialog, then it will pop that dialog.

    If you want to avoid the consequents of a user key-in, then use VBA to create objects directly, in the way that others have suggested.  Search VBA help for examples.  Searching for CreateTextElement1 reveals an example under topic Elements and Levels.

     
    Regards, Jon Summers
    LA Solutions

    Answer Verified By: Rob Golding 

  • Thanks for the replies. Has basically got what i wanted.

    The only thing is that i would like the user to place the text where they would like, is there a way i can put the new text element to the cursor and have the user select the point? rather than define the point?

  • Unknown said:
    The only thing is that i would like the user to place the text where they would like, is there a way Ii can put the new text element to the cursor and have the user select the point?

    Write a class that Implements IPrimitiveCommandEvents.  Read about Interface Oriented Programming in VBA help.  Start that class from your form and pass it the string to be created.

    Sub PlaceTextInteractive (s As String)
      Dim oTextPlacer As New clsGolding
      oTextPlacer.Text = s
      CommandState.StartPrimitive oTextPlacer
    End Sub

    Create a class module named clsGolding.  Put the following in that class...

    Implements IPrimitiveCommandEvents

    Private m_strText As String

    [Edit] ' wrong: Public Property Set Text (s As String)
    Public Property Let Text (s As String)


      m_strText = s

    End Property

    '  Add all the subroutines required by IPrimitiveCommandEvents

    Sub IPrimitiveCommandEvents_Datapoint (point As Point3d, oView As View)
      Dim oText As TextElement
      Set oText = CreateTextElement1 (Nothing, m_strText, point, Matrix3dIdentity)
      ActiveModelReference.AddElement oText
    End Sub

     
    Regards, Jon Summers
    LA Solutions

  • Thanks Jon,

    I haven't been able to get that to work unfortunatley.

    I have done as above...

    -Created a Class Module called "clsGolding" which has the following in it... But when run the below error appears.

    My form has a button that simply is this
     PlaceTextInteractive ("testing")
    
    
    
    
    
    
    Which controls this
    
    
    Sub PlaceTextInteractive(s As String)
    Dim oTextPlacer As New clsGolding
    oTextPlacer.Text = s
    CommandState.StartPrimitive oTextPlacer
    End Sub
    
    
    
    
    What have I done wrong?
  • See the highlighted portion of your code? Thats the error. Unfortunately the Screenshot is too small, could not read it.

    But I can see it is not the part you copied into your mail.

  • I understand the highlighted part is the error but not too sure why its appearing.

    I have attached the picture rather than embed it.

    Thanks for the replies guys.

  • Your Property needs a Getter! Google your error text, you will find an answer.

  • Syntax of Class Properties

    When you write a class property with VB/VBA...

    • use the Set keyword when assigning an object
    • use the Let keyword when assigning plain old data (POD), such as a number or string
    • use the Get keyword to extract data from the class

    In your screenshot, the incomprehensible error message is trying to tell you to use Let rather tha Set in your Text property.  Try this instead:

    Public Property Let Text (s As String)
      m_strText = s
    End Property

    Apologies

    
    

    Unknown said:
    What have I done wrong?

    Nothing! That was my fault for writing the wrong keyword in my example below.  I'm always forgetting to use Let for PODs.

     
    Regards, Jon Summers
    LA Solutions

Reply
  • Syntax of Class Properties

    When you write a class property with VB/VBA...

    • use the Set keyword when assigning an object
    • use the Let keyword when assigning plain old data (POD), such as a number or string
    • use the Get keyword to extract data from the class

    In your screenshot, the incomprehensible error message is trying to tell you to use Let rather tha Set in your Text property.  Try this instead:

    Public Property Let Text (s As String)
      m_strText = s
    End Property

    Apologies

    
    

    Unknown said:
    What have I done wrong?

    Nothing! That was my fault for writing the wrong keyword in my example below.  I'm always forgetting to use Let for PODs.

     
    Regards, Jon Summers
    LA Solutions

Children
  • Thanks Jon, much appreciated. I'm still a relative newbie to all this. Its a hell of a learning curve!

    Its skipped over that part but now it comes up with another message.

    Compile error:

    Procedure declaration does not match description of event or procedure having the same name

    Its highlighted the ...

    Sub IPrimitiveCommandEvents_Datapoint(point As Point3d, oView As View)

  • Unknown said:
    Sub IPrimitiveCommandEvents_Datapoint(point As Point3d, oView As View)

    The exact signature is

    Sub IPrimitiveCommandEvents_Datapoint(point As Point3d, ByVal oView As View)

    Is the compiler happier with that?

     
    Regards, Jon Summers
    LA Solutions

  • Happier :)

    ---------------------------

    Microsoft Visual Basic

    ---------------------------

    Compile error:

    Object module needs to implement 'Keyin' for interface 'IPrimitiveCommandEvents'

    has highlighted

    Implements IPrimitiveCommandEvents

  • Unknown said:
    Object module needs to implement 'Keyin' for interface 'IPrimitiveCommandEvents'

    In VB/VBA, a class that Implements an Interface must have all the subroutines of that Interface, even when they do nothing.  In other words, you must write all the subroutines required by IPrimitiveCommandEvents.  Fortunately, the IDE provides some assistance:

    1. Top-left is a combobox having a list of classes and interfaces in your current project
      1. Choose IPrimitiveCommandEvents
    2. Top-right is a list of procedures for the current class or interface
      1. As you select each procedure, VBA writes a skeleton for that procedure
      2. Repeat and rinse for each procedure

     
    Regards, Jon Summers
    LA Solutions

  • You must have Procedures for all Procedures defined in your Interface.

    (Just click them all once in our VBA IDE.)

  • You guys are absolute legends!

    All working. Many thanks for helping out!

  • Just a bit further to this... the client has asked if its possible to show a preview of the text on the screen (i personally think its not needed but hey they pay the bills so least i can do is ask)

    In the above, I know that VBA doesn't actually create the text element until the datapoint is clicked, so i'm not sure if this is possible.

    They basically want to be able to see where the text is going to be placed, so much like the text already predefined at the cursor just waiting for a insertion point.

    Any ideas?

    Thanks again!

  • Hi Rob,

    you can display dynamic elements when Primitive Command is active. The right place to do it is Dynamics methods in IPrimitiveCommandEvents, because this method is called everytime the cursor is moved.

    You can check for example Line Element Creation Command example in MicroStation VBA help to see how to do it.

    If there is no dynamic, Transient Elements can be used to display elements that don't exist in design file.

    With regards,

     Jan

  • Thanks Jan. I have had a look at the example and it was helpful but still couldn't give the result the client wants.

    Below is the code that i have pieced together from the example and also from what the guys helped me with above. The exact code below, essentially work the same as before

    If i add another "ActiveModelReference.AddElement otext" into the Dynamics section, then its achieves sort of what i'm after, where the text is placed at the cursor, however everytime the mouse is moved it will place the text... ending up with hundreds of text elements on the design.

    Is there anything from below that could be changed to get the result the client wants?

    I have seen a few programs (i think it was part of an MDL) that could do exactly as im after so i assume this is possible?


    Implements IPrimitiveCommandEvents

    Private m_strText As String
    Private m_atPoints(0 To 1) As Point3d
    Private m_nPoints As Integer

    Public Property Let Text(s As String)
    m_strText = s
    End Property

    Sub IPrimitiveCommandEvents_Datapoint(Point As Point3d, ByVal oView As View)

    If m_nPoints = 0 Then
    CommandState.StartDynamics
    m_atPoints(0) = Point
    m_nPoints = 1
    ShowPrompt "Place end point"
    ElseIf m_nPoints = 1 Then
    m_atPoints(1) = Point
    Dim otext As TextElement
    Set otext = CreateTextElement1(Nothing, m_strText, Point, Matrix3dIdentity)
    ActiveModelReference.AddElement otext
    otext.Redraw msdDrawingModeNormal
    m_atPoints(0) = m_atPoints(1)
    End If

    End Sub


    Private Sub IPrimitiveCommandEvents_Dynamics(Point As Point3d, ByVal View As View, ByVal DrawMode As MsdDrawingMode)

    If m_nPoints = 1 Then
    m_atPoints(1) = Point
    Dim otext As TextElement
    Set otext = CreateTextElement1(Nothing, m_strText, Point, Matrix3dIdentity)
    otext.Redraw msdDrawingModeNormal
    End If
    End Sub

    Private Sub IPrimitiveCommandEvents_Keyin(ByVal Keyin As String)
    End Sub

    Private Sub IPrimitiveCommandEvents_Reset()
    CommandState.StartPrimitive Me
    m_nPoints = 0
    End Sub

    Private Sub IPrimitiveCommandEvents_Start()
    ShowPrompt "Select insertion point for text"
    End Sub
  • Unknown said:
    If i add another "ActiveModelReference.AddElement otext" into the Dynamics section

    You never can do that. _Dynamics method is called when a cursor is moved, which means it can happen tens times every second. _DataPoint is the best place to add element into a model.

    Unknown said:
    Is there anything from below that could be changed to get the result the client wants?

    This thread has become pretty long and it's hard to find out what your client wants. Can you describe step by step how the tool should work ? Something like (just an example):

    1. Tool is started, the user is asked to enter text into a dialog.
    2. Until datapoint is pressed, text is dynamically displayed at cursor.
    3. If reset button is pressed, text is erased.
    4. If datapoint is pressed, text is added into model and the tool is restarted.

    What I miss in the information available is a definition how mouse buttons should work.

    With regards,

      Jan