Disclaimer: First Foray into using MVBA with the native Microstation Objects. Well versed in VB.NET though.
I am trying to create a simple little MVBA application to return the 2D slope between 2 points. This is what I have so far thanks to a previous post by Jan called MeasureLine.mvba.
Main entry point for the program
Option Explicit ' --------------------------------------------------------------------- Private Const strMODULE_NAME As String = "modMain" ' AnnotateSlope is a MicroStation VBA project. It enables a user to ' identify (locate) a 2 points in a DGN file and get/annotate the slope, ' and post the measurement in a UserForm. ' --------------------------------------------------------------------- ' To start this macro, use the following MicroStation keyin: ' vba run [AnnotateSlope]modMain.Main ' --------------------------------------------------------------------- ' Main entry point ' --------------------------------------------------------------------- Public Sub Main() On Error GoTo err_Main Debug.Print "VBA project location: " & Application.VBE.activevbproject.FileName frmLocator.Show vbModeless Exit Sub err_Main: ReportError strMODULE_NAME, "Main" End Sub ' --------------------------------------------------------------------- ' ReportError ' Generic way to report an error ' --------------------------------------------------------------------- Public Sub ReportError(ByVal modName As String, ByVal procName As String) Const strColon As String = ":" MsgBox "Error " & CStr(err.Number) & strColon & " " & err.Description & vbNewLine & _ "Caused by " & err.Source, vbOKOnly Or vbCritical, "Error in " & modName & strColon & procName End Sub ' ---------------------------------------------------------------------
Temporary code for userform (Everything is commented out except the call CommandState.SetLocate)
Option Explicit ' --------------------------------------------------------------------- Private Const strMODULE_NAME As String = "frmLocator" ' --------------------------------------------------------------------- Public Property Let ElementID(ByRef id As DLong) 'txtID.Text = DLongToString(id) End Property ' --------------------------------------------------------------------- Public Property Let Length(ByVal l As Double) 'txtLength.Text = Format(l, "#0.00") End Property ' --------------------------------------------------------------------- Private Sub commandButton_Click() ' Start a new locate command by invoking our class clsLocator Dim oLocator As New clsLocator Set oLocator.Originator = Me CommandState.SetLocate oLocator End Sub ' --------------------------------------------------------------------- Private Sub UserForm_Initialize() ' Initialise units Dim master As MeasurementUnit master = ActiveModelReference.MasterUnit 'lblLength.Caption = "Length " & master.Label & ":" ' Initialise ID ElementID = DLongFromLong(0) ' Initialise length Length = 0# End Sub
Class Module implementing ILocateCommandEvents
Option Explicit ' --------------------------------------------------------------------- Private Const strMODULE_NAME As String = "clsLocator" ' --------------------------------------------------------------------- Implements ILocateCommandEvents ' --------------------------------------------------------------------- ' Member variable stores a reference to the UserForm that called this ' locate class ' --------------------------------------------------------------------- Private m_oOriginator As frmLocator ' --------------------------------------------------------------------- ' Property lets us assign our form to this variable ' e.g. Set oLocator.Originator = Me ' --------------------------------------------------------------------- Public Property Set Originator(ByRef oForm As frmLocator) Set m_oOriginator = oForm End Property ' --------------------------------------------------------------------- Private Sub ILocateCommandEvents_Accept(ByVal oElement As Element, point As Point3d, ByVal View As View) ' Use originator variable to use properties of frmLocator m_oOriginator.ElementID = oElement.id m_oOriginator.Length = oElement.AsLineElement.Length End Sub ' --------------------------------------------------------------------- Private Sub ILocateCommandEvents_Cleanup() End Sub ' --------------------------------------------------------------------- Private Sub ILocateCommandEvents_Dynamics(point As Point3d, ByVal View As View, ByVal drawMode As MsdDrawingMode) ' Intentionally empty End Sub ' --------------------------------------------------------------------- Private Sub ILocateCommandEvents_LocateFailed() ShowStatus "Not a line element" End Sub ' --------------------------------------------------------------------- ' Reject elements that are not LineElements because we can't measure them ' --------------------------------------------------------------------- Private Sub ILocateCommandEvents_LocateFilter(ByVal oElement As Element, point As Point3d, accepted As Boolean) ' Intentionally empty End Sub ' --------------------------------------------------------------------- Private Sub ILocateCommandEvents_LocateReset() ' Intentionally empty End Sub ' --------------------------------------------------------------------- Private Sub ILocateCommandEvents_Start() Dim ele As Element Dim eleComponent As Element Dim hitPoint As Point3d ShowCommand "Select 1st Data Point" ShowPrompt "Snap on your 1st point" hitPoint = CommandState.GetHitPoint Debug.Print " Point on Element " & Point3dToString(hitPoint) End Sub ' --------------------------------------------------------------------- Function Point3dToString(pnt As Point3d) As String Point3dToString = "(" & pnt.X & ", " & pnt.Y & ", " & pnt.Z & ")" End Function
I am having difficulty finding a CommandState Object Method for prompting the user to send a snapped Point3d rather than an element of some sort. Do I need to be using IPrimitiveCommandEvents instead? It looks like the IPrimitiveCommandEvents_DataPoint Method does what I want, but I am having trouble calling it from a dialog box button.
Thanks!Matt
P.S. How do you do code blocks <code></code> on these forums?
Unknown said:It looks like the IPrimitiveCommandEvents_DataPoint Method does what I want, but I am having trouble calling it from a dialog box button
A locator class does what you expect — it locates things. If the points you want are always part of an element (e.g. a line end point) then ILocateCommandEvents is what you need.
If you want to gather a point placed anywhere, then you don't want to be locating something, and a class that Implements IPrimitiveCommandEvents should do you. You can start that command class from a UserForm command button much the same as your locator class...
Sub MyButton_click () Dim oPointPicker As New clsPointPicker ' this is your class that Implements IPrimitiveCommandEvents CommandState.StartPrimitive oPointPicker End Sub
Unknown said:CommandState.SetLocate oLocator
That should be...
CommandState.StartLocate oLocator
Regards, Jon Summers LA Solutions