11 Replies Latest reply on Aug 18, 2016 3:36 PM by Ivana Kolin

    Get selected Blockinstance in Drawing

    Sascha Smolny

      Hello,

       

      how can i get the selected Blockinstance in a Drawing (Selected in the Grapics Area) ?

      If i select a point from the Block i can get this point with:

          Dim swApp As SldWorks.SldWorks
          Dim swModel As SldWorks.ModelDoc2
          Dim swSelMgr As SldWorks.SelectionMgr
              
          Set swApp = CreateObject("SldWorks.Application")
          Set swModel = swApp.ActiveDoc
          Set swSelMgr = swModel.SelectionManager
          
          
          Dim swSketchPt As SketchPoint
          Set swSketchPt = swSelMgr.GetSelectedObject6(1, -1)
      

       

      If i select a Line from the Block i can get this with:

          Dim swApp As SldWorks.SldWorks
          Dim swModel As SldWorks.ModelDoc2
          Dim swSelMgr As SldWorks.SelectionMgr
              
          Set swApp = CreateObject("SldWorks.Application")
          Set swModel = swApp.ActiveDoc
          Set swSelMgr = swModel.SelectionManager
      
      
          Dim swSkSeg As SldWorks.SketchSegment
          Set swSkSeg = swSelMgr.GetSelectedObject6(1, -1)
      
      
      

       

      But how can i get the selected Block?

       

      Regards,

      Sascha

       

      [edit]

      I can get it only, when i use selection Filter and select the Block. But i want use it without the selection Filter.

         Dim swSkBlockInstance As SldWorks.SketchBlockInstance
         Set swSkBlockInstance = swSelMgr.GetSelectedObject6(1, -1)
      

       

      [/edit]

        • Re: Get selected Blockinstance in Drawing
          Keith Rice

          Sascha,

           

          I think you have two options:

           

          1. Programmatically set the selection filter when you get the selected object using ISldWorks::SetApplySelectionFilter and its associated methods. (I have not used these API calls before so I cannot give you any sample code, unfortunately.)

           

          2. Traverse all of the sketch block definitions (and their instances) in the feature tree until you find an instance containing a sketch segment or sketch point identical to the one selected. You can use ISldWorks::IsSame to perform this comparison. I believe all it does is compare the persistent IDs of the two objects.

           

          Keith

          SolidWorks API Automation Services

            • Re: Get selected Blockinstance in Drawing
              Sascha Smolny

              Hello,

              many thanks for the ideas. I have spend now many hours (i had a very short night)...but i havend found a solution.

               

              What i am planing to do:

              I  write a Task-Pane AddIn for a better handling of Blocks. We will use the Blocks for Piping and instrumentation diagram.

              To add functions like "explode selected Block", "Get active Block Layer", "Show how many Instances of Block exist" and so on, i need to get the Block Instance on every selection changed.

               

              What i have tried/found out now:

              1.) If i select a Sketch Point/Line from a Block in the Journal File i get a entry:

              boolstatus = Part.Extension.SelectByID2("Point4/Block1-1", "SKETCHPOINT", 0.42861457398812175, 0.37061952028896927, 0, False, 0, Nothing, 0)

              Here is the Block Instance Name. But i cant get this Name via API. I can only read the Journal File.

              2.) I have found this Example: API: Finding the Sketch Block Instance to Which a Sketch Segment Belongs

              Here are the Sketch Points compared. But here i must compare each Selection individually (Point, Line, Spline ...) this is very complicated and slow. I think that I can not do this every mouse click.

              3.) persistent IDs

              I have yesterday tested. But i cant find the same id. I think, that the selected point and a sketch Point are not the same. It is the same if i use ISldWorks::IsSame or compare the byte Array. Here are my sample. I have now wrote this in vb.net. It much easier for me with Visual Studio and the Debugger.

               

              Private Sub SelectionChanged()
                      Dim swModel As sldworks.ModelDoc2
                      Dim swSelMgr As sldworks.SelectionMgr
                      Try
                          swModel = swApp.ActiveDoc
                          swSelMgr = swModel.SelectionManager
                          swModel = swApp.ActiveDoc
                          swSelMgr = swModel.SelectionManager
                          Dim Sel As Object
                          Sel = swSelMgr.GetSelectedObject6(1, -1)
                          Dim ext As sldworks.ModelDocExtension
                          ext = swModel.Extension
                          Dim b() As Byte = ext.GetPersistReference3(Sel) 'Only to test if the unknown Object is the same ID
                          Dim swSketchPt As sldworks.SketchPoint
                          swSketchPt = Sel
                          Dim LastPersistReference() As Byte
                          LastPersistReference = ext.GetPersistReference3(swSketchPt) 'This are the same!
                          Dim SwSketchMgr As sldworks.SketchManager
                          SwSketchMgr = swModel.SketchManager
                          Dim blockDefinitions() As Object = SwSketchMgr.GetSketchBlockDefinitions
                          For Each blockDef As sldworks.SketchBlockDefinition In blockDefinitions
                              For Each blockInstance As sldworks.SketchBlockInstance In blockDef.GetInstances
                                  Debug.WriteLine(blockInstance.Name)
                                  Dim BSketch As sldworks.Sketch = blockInstance.GetSketch
                                  Dim swSktBlkDef As sldworks.SketchBlockDefinition
                                  Dim swSketch As sldworks.Sketch
                                  swSktBlkDef = blockInstance.Definition
                                  swSketch = swSktBlkDef.GetSketch
                                  Dim points() As Object = swSketch.GetSketchPoints2()
                                  For Each p As sldworks.SketchPoint In points
                                      Dim test() As Byte = ext.GetPersistReference3(p)
                                      If test.SequenceEqual(LastPersistReference) Then
                                          MsgBox("Found")
                                      End If
                                  Next
                              Next
                          Next
                      Catch ex As Exception
                      End Try
                  End Sub
              

               

              This test is only if a point in a sketch is selected. But the IDs are not the same.

               

              4.) You wrote that i can programmatically set the selection filter. But when i use this, i remove every time the user changes the selection the selection from the user? Or can i select "only in the api" without change the user selection?

               

              5.) Is it possible to get information from the property Manager. Which is open if a Block is selected?

               

              I think it is very difficult. The fastest Way is to read the Journal File. But if i use more than one SolidWorks Session no Journal File are written. So it is not the right way.

              Any other ideas? What i am doing wrong?

               

              Regards

              Sascha

            • Re: Get selected Blockinstance in Drawing
              John Alexander

              I've just skimmed through this discussion so I apologize if I'm pointing something out that has already been tried.

               

              The selection manager will report all selections. You can iterate over the selections and test if any of them are sketchblockinstances. In this way, you can get a reference to one or several sketchblockinstances that the user has selected.

               

              The behavior that I have observed with regard to sketch blocks is that the selection method has an impact on whether or not the selection manager reports the sketchblockinstance as selected. For instance, if you perform a single left click on any sketch entity that is a part of the sketchblockinstance, the selection manager will report that entity and also the sketchblockinstance that it is a part of. However, if the user drag-selects (box-selects) the sketch block, the selectionmanager will not report the sketchblockinstance as selected even though the entities inside of it are.

               

              I haven't worked out a solution to that problem - my approach was similar to what you are trying in your examples in this thread. I tried iterating over all sketchblockinstances in the drawing and testing if the entities inside of their sketch were the same as those that are reported by the SelectionManager. I think the problem was my assumption about what the blockInstance.GetSketch returns. If you read the documentation, you'll notice that this sketch is not unique to the sketchblockinstance. If two sketchblockinstances are on the same sketch, it will be impossible to determine which points belong to one and not the other.

               

              2012 SOLIDWORKS API Help - GetSketch Method (ISketchBlockInstance)

               

              1.                     For Each p As sldworks.SketchPoint In points 
              2.                         Dim test() As Byte = ext.GetPersistReference3(p) 
              3.                         If test.SequenceEqual(LastPersistReference) Then 
              4.                             MsgBox("Found") 
              5.                         End If 
              6.                     Next

               

              edit: Out of curiosity, does this code snippet return? I couldn't tell from your comments.

                • Re: Get selected Blockinstance in Drawing
                  Keith Rice

                  For instance, if you perform a single left click on any sketch entity that is a part of the sketchblockinstance, the selection manager will report that entity and also the sketchblockinstance that it is a part of.

                   

                  I can't repeat this. When I select on a sketch entity contained in a block (see attached picture) and run the following code, I get "1" and "10", meaning that only one entity is selected and that entity is a sketch segment (according to swSelectType_e).

                   

                  Dim swApp As SldWorks.SldWorks
                  Dim swModel As SldWorks.ModelDoc2
                  Dim swSelMgr As SldWorks.SelectionMgr
                  
                  Sub main()
                      Set swApp = Application.SldWorks
                      Set swModel = swApp.ActiveDoc
                      Set swSelMgr = swModel.SelectionManager
                      Debug.Print swSelMgr.GetSelectedObjectCount2(-1)
                      Debug.Print swSelMgr.GetSelectedObjectType3(1, -1)
                  End Sub
                  

                   

                  Can you elaborate on how you are getting ISketchBlockInstance from ISelectionManager? Thanks.

                   

                  Keith

                  SolidWorks API Training

                    • Re: Get selected Blockinstance in Drawing
                      John Alexander

                      This is a snippet from a larger project. I took a look at it to make sure my memory was correct. I should have pointed out that this is SW2012 - maybe that explains the discrepancy. I notice that your screen shot of single left on the sketchblockinstance appears different from mine.

                       

                          'Grab the first sketch block balloon

                          For i = 0 To swSelectionMgr.GetSelectedObjectCount2(-1)

                              selectionType = swSelectionMgr.GetSelectedObjectType3(i, -1)

                              If selectionType = swSelectType_e.swSelSUBSKETCHINST Then

                                  Set BlockInstance = swSelectionMgr.GetSelectedObject6(i, -1)

                                  If (BlockInstance.Definition Is swSketchBlockDef_Machined) Or (BlockInstance.Definition Is swSketchBlockDef_Purchased) Or (BlockInstance.Definition                Is swSketchBlockDef_FastenerStack3) Or (BlockInstance.Definition Is swSketchBlockDef_FastenerStack2) Then

                                      stackName = BlockInstance.GetAttributeValue("Root")

                                      Debug.Print (stackName)

                                      Exit For

                                  End If

                              End If

                          Next i

                       

                      Unselected

                      Single Left Click: Debug.Print (stackName) shows the property "Root" which was assigned to the selected balloon.

                      Box Select: Debug.Print (stackName) never gets called.

                       

                      edit: Apologies for the formatting - I'm having problems with the syntax highlighting

                        • Re: Get selected Blockinstance in Drawing
                          Sascha Smolny

                          Hello,

                          many thanks for your works!

                           

                          The code snippet from me above return nothing. The IDs are different. I cant find the sketch segments this way.

                          I have tried your code. But with SolidWorks 2015 (and since today 2016) i get also only 1 selected Object count if i select a point or line from the sketch.

                          If i select a containing text i get the Block instance.

                          I will tomorrow made a few tests.

                           

                          There must be a way to do this. But this way is very difficult to find .

                           

                          Regards,

                          Sascha

                    • Re: Get selected Blockinstance in Drawing
                      Ivana Kolin
                      Sub main()
                          Dim swApp As SldWorks.SldWorks
                          Dim swModel As SldWorks.ModelDoc2
                          Dim swSelMgr As SldWorks.SelectionMgr
                          Dim swSkSeg As SldWorks.SketchSegment
                          Dim swSketchPt As SldWorks.SketchPoint
                          Dim swSketch As SldWorks.Sketch
                          Dim swFeat As SldWorks.Feature
                          Dim vBlocks As Variant
                          Dim vBlock As Variant
                          Dim swSkBlockInstance As SldWorks.SketchBlockInstance
                                
                          Set swApp = CreateObject("SldWorks.Application")
                          Set swModel = swApp.ActiveDoc
                          Set swSelMgr = swModel.SelectionManager
                          If swSelMgr.GetSelectedObjectType3(1, -1) = swSelSKETCHPOINTS Then
                              Set swSketchPt = swSelMgr.GetSelectedObject6(1, -1)
                              Set swSketch = swSketchPt.GetSketch
                          Else
                              Set swSkSeg = swSelMgr.GetSelectedObject6(1, -1)
                              Set swSketch = swSkSeg.GetSketch
                          End If
                            
                          vBlocks = swSketch.GetSketchBlockInstances
                          If IsEmpty(vBlocks) Then Exit Sub
                      
                      
                          For Each vBlock In vBlocks
                              Set swSkBlockInstance = vBlock
                          Next
                      
                      
                      End Sub
                      
                        • Re: Get selected Blockinstance in Drawing
                          Sascha Smolny

                          @Ivana Kolin

                          Thanks for the example. But i can only get all Block Instances in the Drawing. Not the specific one.

                           

                          I think the only Way is this: API: Finding the Sketch Block Instance to Which a Sketch Segment Belongs

                          but this is not the way that i prefer.

                          Are there undocumented API calls?

                           

                          Regards,

                          Sascha

                            • Re: Get selected Blockinstance in Drawing
                              Ivana Kolin

                              I thought it could not be just that simple

                              This one is only for lines, but it should work with points anyway (I hope).

                              Sub main()
                                  Dim swApp As SldWorks.SldWorks
                                  Dim swModel As SldWorks.ModelDoc2
                                  Dim swSelMgr As SldWorks.SelectionMgr
                                  Dim swSkSeg As SldWorks.SketchSegment
                                  Dim swSketchPt As SldWorks.SketchPoint
                                  Dim swSketch As SldWorks.Sketch
                                  Dim swFeat As SldWorks.Feature
                                  Dim vBlocks As Variant
                                  Dim vBlock As Variant
                                  Dim swSkBlockInstance As SldWorks.SketchBlockInstance
                                 
                                  Dim swSkSegx As SldWorks.SketchSegment
                                  Dim swSketchx As SldWorks.Sketch
                              
                              
                                  Set swApp = CreateObject("SldWorks.Application")
                                  Set swModel = swApp.ActiveDoc
                                  Set swSelMgr = swModel.SelectionManager
                                  Dim feat As SldWorks.Feature
                              
                              
                                  If swSelMgr.GetSelectedObjectType3(1, -1) = swSelSKETCHPOINTS Then
                                      Set swSketchPt = swSelMgr.GetSelectedObject6(1, -1)
                                      Set swSketch = swSketchPt.GetSketch
                                      Exit Sub
                                  Else
                                      Set swSkSeg = swSelMgr.GetSelectedObject6(1, -1)
                                      Set swSketch = swSkSeg.GetSketch
                                  End If
                                   
                              
                                  vBlocks = swSketch.GetSketchBlockInstances
                                  If IsEmpty(vBlocks) Then Exit Sub
                              
                              
                                  For Each vBlock In vBlocks
                                      Set swSkBlockInstance = vBlock
                                      swSkBlockInstance.Select False, Nothing
                                      swModel.SketchManager.EditSketchBlock
                                      swSkSeg.Select4 False, Nothing
                                      Set swSkSegx = swSelMgr.GetSelectedObject6(1, -1)
                                      Set swSketchx = swSkSegx.GetSketch
                                      If swSketch.Name <> swSketchx.Name Then
                                          MsgBox swSkBlockInstance.Name
                                      End If
                                      swModel.SketchManager.EndEditSketchBlock False
                                  Next
                              
                              
                              End Sub
                              
                                • Re: Get selected Blockinstance in Drawing
                                  Sascha Smolny

                                  Hello,

                                   

                                  @Ivana Kolin

                                  interesting approach. I didnt tried it now. I don´t want change the selection that the user has made. I want to react when the user select an Block. This can be very often.

                                   

                                  @All

                                  It is so simple (Not really...but i found a (good?) way!)

                                  I have tried so many ways. For example i have read out the property Manager page. So i get fast the BlockDefinition Name.. (But not the BlockInstance):

                                   

                                  swApp.GetRunningCommandInfo(commandID, pmpTitle, isUIActive)
                                  If pmpTitle <> "" Then Debug.Print("Title of PropertyManager page: " & pmpTitle)
                                  
                                  

                                   

                                   

                                   

                                  But than i found this Page in the Documentation: 2016 SOLIDWORKS API Help - GetSelectionSpecification Method (ISelectionMgr)

                                  And now i have a fast way:

                                  Private Function GetSketchBlockInstanceFromSelection() As SldWorks.SketchBlockInstance
                                          Dim swModel As SldWorks.ModelDoc2
                                          Dim swModelDocExt As SldWorks.ModelDocExtension
                                          Dim SketchBlockInstance As SldWorks.SketchBlockInstance
                                  
                                          Dim time As DateTime = Now
                                  
                                          Try
                                              swModel = swApp.ActiveDoc
                                              swModelDocExt = swModel.Extension
                                  
                                              Dim swSelectionMgr As SldWorks.SelectionMgr
                                              swSelectionMgr = swModel.SelectionManager
                                  
                                              Dim SelectByString As String = ""
                                              Dim ObjectType As String = ""
                                              Dim type As Integer
                                              Dim x As Double
                                              Dim y As Double
                                              Dim z As Double
                                  
                                              If swSelectionMgr.GetSelectedObjectCount2(-1) > 1 Then
                                                  'Return only a SketchblockInstance when only one is selected...
                                                  'modify if you want return more than one (or only the first) selected Sketchblockinstance
                                                  Return Nothing
                                                  Exit Function
                                              End If
                                  
                                              swSelectionMgr.GetSelectionSpecification(1, SelectByString, ObjectType, type, x, y, z)
                                              Debug.WriteLine(SelectByString & " " & ObjectType & " " & type)
                                  
                                              If type = SwConst.swSelectType_e.swSelSUBSKETCHINST Then 'ObjectType = "SUBSKETCHINST" Then
                                                  SketchBlockInstance = swSelectionMgr.GetSelectedObject6(1, -1)
                                                  Debug.WriteLine("Found:" & SketchBlockInstance.Name)
                                                  Return SketchBlockInstance
                                                  Exit Function
                                              ElseIf type = SwConst.swSelectType_e.swSelSKETCHSEGS Or type = SwConst.swSelectType_e.swSelSKETCHPOINTS Then
                                                  'Show if a sketchblockinstance has the same name
                                                  Dim SwSketchMgr As SldWorks.SketchManager
                                                  SwSketchMgr = swModel.SketchManager
                                  
                                                  Dim blockDefinitions() As Object = SwSketchMgr.GetSketchBlockDefinitions
                                                  For Each blockDef As SldWorks.SketchBlockDefinition In blockDefinitions
                                                      For Each blockInstance As SldWorks.SketchBlockInstance In blockDef.GetInstances
                                                          If SelectByString.EndsWith(blockInstance.Name) Then
                                                              Debug.WriteLine("Found:" & blockInstance.Name)
                                                              Return blockInstance
                                                              Exit Function
                                                          End If
                                                      Next
                                                  Next
                                              Else
                                                  'Not a Block
                                                  Return Nothing
                                                  Exit Function
                                              End If
                                  
                                          Catch ex As Exception
                                              MsgBox(ex.Message)
                                          Finally
                                              Debug.WriteLine(Now.Subtract(time).Milliseconds)
                                          End Try
                                  
                                          Return Nothing
                                      End Function
                                  
                                  

                                   

                                   

                                  Remarks:

                                   

                                  - This function returns nothing, when no sketchblockinstance is selected

                                  - This function returns only one sketchblockinstance. Multiselect are ignored

                                  - This function is fast. Only a few ms.

                                  - I have only found, that i get a "SUBSKETCHINST", "SKETCHSEG" or "SKETCHPOINT". I don´t know if there are more possibilities.

                                   

                                  What do you think about it? Can i mark my own answer as right answer? Do you see problems with this?

                                   

                                  Regards,

                                  Sascha

                                   

                                  [edit]

                                  Many many thanks to all that had worked on my problem!

                                  [/edit]