I have a macro that automatically creates a Detailed view on a sheet. It works on 2 input's:
- mouse click 1 (set's the target to be detailed)
- mouse click 2 (set's the location where the balloon should be)
The code works fine. But sometimes the user will start another command, or restart the same command, while it is still running. This off course gives all kinds of problems.
Is there a possibility in VBA to prevent the user to start another command while this command is running?
Or is this problem a part of the clicking itself?
Here is my code: (it uses a Class Module called: clsGetPoint, see code below)
Sub AutoDetailedView() On Error GoTo ErrorManagment '(error handling 2013/02/18) 'step 0 Create a transaction. -> for 1 undo command Dim oTransMgr As TransactionManager Set oTransMgr = ThisApplication.TransactionManager Dim oTrans As Transaction Set oTrans = oTransMgr.StartTransaction(ThisApplication.ActiveD
ocument, "AutoDetailedView") 'step 1 Select a drawingView 'Set a reference to the drawing document. Dim oDrawDoc As DrawingDocument Set oDrawDoc = ThisApplication.ActiveDocument 'Set a reference to the active sheet. Dim oSheet As Sheet Set oSheet = oDrawDoc.ActiveSheet ' Select a drawing view Dim oDrawingView As DrawingView Set oDrawingView = oSheet.DrawingViews.Item(1) 'select the below if you want the user to choose a drawing view, else the above will select the first drawingview on the active sheet 'Set oDrawingView = ThisApplication.CommandManager.Pick(kDrawingViewFi lter, "Select a drawing view.") 'step 2 Select the center of the circular fence Dim getPoint As New clsGetPoint Dim oCenterPoint As Point2d Set oCenterPoint = getPoint.GetDrawingPoint("Select the area to be detailed", kLeftMouseButton, kCursorBuiltInCursorSelTrail) 'step 3 Select the place where the detailed view need to be placed Dim oPoint As Point2d Set oPoint = getPoint.GetDrawingPoint("Select the location of the detailed view", kLeftMouseButton, kCursorBuiltInPushpinCursor) ' Get any linear curve from the base view Dim oCurve As DrawingCurve For Each oCurve In oDrawingView.DrawingCurves If oCurve.CurveType = kLineSegmentCurve Then Exit For Next ' Create an intent object Dim oAttachPoint As Point2d Set oAttachPoint = oDrawingView.Center 'step 4 Create the detail view Dim oDetailView As DetailDrawingView Set oDetailView = oSheet.DrawingViews.AddDetailView(oDrawingView, oPoint, kShadedDrawingViewStyle, True, oCenterPoint, 0.5, , 0.25, False, " ") 'Set breakline to smooth oDetailView.IsBreakLineSmooth = True 'Show full detail boundary oDetailView.DisplayFullBoundary = True 'Show connection line oDetailView.DisplayConnectionLine = True 'set detailview to "Parts" ' this assumes that there is an detailview called "Parts", if not, delete this line 'On Error Resume Next 'Call oDetailView.SetDesignViewRepresentation("Parts", False) 'step 5 Active top level of drawing (error handling 2013/02/18) ErrorManagment: '(error handling 2013/02/18) oSheet.Activate 'step 6 End the transaction. oTrans.End End Sub
and now the code for the clsGetPoint (Put it onder Class Modules)
Private WithEvents m_interaction As InteractionEvents Private WithEvents m_mouse As MouseEvents Private m_position As Point2d Private m_button As MouseButtonEnum Private m_continue As Boolean Public Function GetDrawingPoint(Prompt As String, button As MouseButtonEnum, m_Cursor As CursorTypeEnum) As Point2d Set m_position = Nothing m_button = button Set m_interaction = ThisApplication.CommandManager.CreateInteractionEv
ents Set m_mouse = m_interaction.MouseEvents m_interaction.StatusBarText = Prompt m_interaction.SetCursor (m_Cursor) m_interaction.Start m_continue = True Do ThisApplication.UserInterfaceManager.DoEvents Loop While m_continue m_interaction.Stop Set GetDrawingPoint = m_position End Function Private Sub m_mouse_OnMouseClick(ByVal button As MouseButtonEnum, ByVal ShiftKeys As ShiftStateEnum, ByVal ModelPosition As Point, ByVal ViewPosition As Point2d, ByVal View As View) If button = m_button Then Set m_position = ThisApplication.TransientGeometry.CreatePoint2d(Mo delPosition.x, ModelPosition.Y) End If m_continue = False End Sub
Take a look at the UserInteractionDisabled-Property. But be aware of the possibility to make Inventor unusable cause of an error in your code. Always enable UserInteraction after your code, even if an error occurs.
I'm starting to believe that my problem lies in the "clsGetPoint" Class Module.
Their is the command m-continu (it loops until somehting happens). And if you press something then it will trigger to get a point2d. Is there a method to check if it is a valid point 2d? And if it is not that it cancels the command or overrules the click so you can't click outside the view port?
Maybe using the UserInteractionDisabled-Property?
If you set UserInteractionDisabled=True at this point, you will not be able to select a point.
First you can set a SelectFilter. Second you can check if there's really a point2D created in OnMouseClick-Event. I think, outside the graphic window, no Point will be created and m_position is empty?!?! If no Point2D is created, clear SelectSet and don't set m_continue to false. So user think's just nothing happens if he clicks somewhere on invalid input.
I've tried the two options but I keep running into problems:
-> I can't manage to get the select filter on for a mouse event (it doesn't exist). And if I use a select event instead of a mouse event the code doesn't work properly. It doesn't fetch me the needed Point2d.
-> The check if the Point is not empty is not a problem. But it still allows users to start another event or press escape. In but situation the interaction with the sheet gets corrupted.
I believe I need to capture every user input event during the loop. Filter on left mouse clicks and let them go true. All other events should be overruled... But I have no clue how to do this
You're trying to break one of most the basic Inventor behavior rule with that workflow: that is whatever command is running, starting another command will terminate politely the current command and start the new one. Trying to workaround this behavior, you are going ahead of a lot more problems than you should be, why not following that basic behavior instead and try to clean up what your command started when a new command is run or your command is cancelled?
The API is making it easy for your to achieve this:
You can find several samples in the Help Files or our Inventor blogs about using the InteractionEvents. A basic rule is to take avantage of the asynchronous workflow provided by InteractionEvents: don't get stuck in a While(DoEvents) loop, rather use the various events like MouseClick to run the second part of your command or InteractionEvents.Terminate to detect user either cancelled your command or started a new one (this event will be fired automatically in both cases) and nicely clean your command state.
I hope it helps.
Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register