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.
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?
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.
- For Each p As sldworks.SketchPoint In points
- Dim test() As Byte = ext.GetPersistReference3(p)
- If test.SequenceEqual(LastPersistReference) Then
- End If
edit: Out of curiosity, does this code snippet return? I couldn't tell from your comments.
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.
select.PNG 3.4 KB
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")
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
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 .
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
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?
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
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.
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
- 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?
Many many thanks to all that had worked on my problem!
thank you for sharing this. I didn't know GetSelectionSpecification, because I use SW2013 most of the time. I was also looking for something in this direction, but GetNameForSelection works only with features and not on sketch entities.
You can mark your own answer.