特色

C# SolidWorks 二次开发 API—各种遍历对象

在实际项目中,我们有时候无法通过一些名字或者信息来查找所要的对象,最快的方式就是通过遍历。然后再去通过细节来找到想要的数据。

  • 遍历图块
       ///这是根据名字来遍历图块的定义
      public static SketchBlockDefinition GetBlockInstenseByBlockName(string blockName)
{

SwApp = ConnectToSolidWorks();

var swModel = (ModelDoc2)SwApp.ActiveDoc;

var skMgr = swModel.SketchManager;

var vBlocks = (object[])skMgr.GetSketchBlockDefinitions();

if (vBlocks == null)
{
return null;
}
else
{
foreach (var item in vBlocks)
{
var blockDef = (SketchBlockDefinition)item;
var fBlock = blockDef.GetFeature();

if (fBlock.Name == blockName)
{
return blockDef;
}
}
}

return null;
}
  • 遍历零件特征
  var swSelMgr = (SelectionMgr)swModel.SelectionManager;
            var swFeat = (Feature)swModel.FirstFeature();
     
            while ((swFeat != null))
            {              
                var swSubFeat = (Feature)swFeat.GetFirstSubFeature();
​
                while ((swSubFeat != null))
                {
                    Debug.Print(swSubFeat.Name.ToString());                    
                    swSubFeat = (Feature)swSubFeat.GetNextSubFeature();
                }
​
                swFeat = (Feature)swFeat.GetNextFeature();
            }
  • 遍历面上的边

   swModel = (ModelDoc2)swApp.ActiveDoc;
           swModelExt = swModel.Extension;
           swSelMgr = (SelectionMgr)swModel.SelectionManager;
           swFeature = (Feature)swSelMgr.GetSelectedObject6(1, -1);
           swModel.ClearSelection2(true);

           nFaceCount = swFeature.GetAffectedFaceCount();
           Debug.Print("Number of faces affected by selected feature = " + nFaceCount);
           vAffectedFaces = (object[])swFeature.GetAffectedFaces();

           for (i = 0; i <= (nFaceCount - 1); i++)
          {
               nEdgeCount = ((Face)vAffectedFaces[i]).GetEdgeCount();
               Debug.Print("   Number of edges on Face " + i + " = " + nEdgeCount);
               vEdges = (object[])((Face)vAffectedFaces[i]).GetEdges();

               for (j = 0; j <= (nEdgeCount - 1); j++)
              {
                  ((Edge)vEdges[j]).Display(2, 0, 0, 1, true);
              }
          }

  • 遍历草图直线

//获取当前草图对象
               var swSketch = (Sketch)swModel.GetActiveSketch2();

               //获取该草图中的所有线
               var vSketchSeg = (object[])swSketch.GetSketchSegments();

               //定义选择
               SelectData swSelData = swSelMgr.CreateSelectData();

               SketchSegment swSketchSeg;
               //遍历线
               for (int i = 0; i < vSketchSeg.Length; i++)
              {
                   swSketchSeg = (SketchSegment)vSketchSeg[i];

                   swSketchSeg.Select4(false, swSelData);
                   
              }

     
  • 遍历草图中的点

var swSketch = (Sketch)swModel.GetActiveSketch2();
            object[] vSketchPt = (object[])swSketch.GetSketchPoints2();
               SketchPoint swSketchPt;
               //遍历点
               for (int i = 0; i < vSketchPt.Length; i++)
              {
                   swSketchPt = (SketchPoint)vSketchPt[i];        
                   
              }
  • 遍历装配中的零件

请参考之前的博文
  • 遍历视图


 var allViewsInThisSheet = (object[])sheet.GetViews();
 
 
  • 遍历视图中的尺寸

   Object[] displayDimensions = (Object[])swView.GetDisplayDimensions();
  • 遍历视图中的注释

var swNote = (Note)swView.GetFirstNote();
 while (swNote != null)
  {
     
       var swAnn = (Annotation)swNote.GetAnnotation();      
       swNote = (Note)swNote.GetNext();
  }
  • 遍历图纸

var sheetNames = (string[])drawingDoc.GetSheetNames();
for (int i = 0; i < sheetNames.Length; i++)
  {
     var bActiveSheet = drawingDoc.ActivateSheet(sheetNames[i]);
  }
  • 遍历视图中形位公差

var swGtol = (Gtol)swView.GetFirstGTOL();

while (swGtol != null)
{
   
    var swAnn = (Annotation)swGtol.GetAnnotation();
       swGtol = (Gtol)swGtol.GetNextGTOL();
}
  • 遍历视图中的表面粗糙度

var swSfSymbol = (SFSymbol)swView.GetFirstSFSymbol();

 while (swSfSymbol != null)
{
   
     var swAnn = (Annotation)swSfSymbol.GetAnnotation();
   
     swSfSymbol = (SFSymbol)swSfSymbol.GetNext();
}
  • 遍历方程式
               //获取当前模型
                ModelDoc2 swModel = (ModelDoc2)swApp.ActiveDoc;
                //定义方程式管理器
                EquationMgr swEqnMgr = default(EquationMgr);
​
                int i = 0;
                int nCount = 0;
​
                if (swModel != null)
                {
                    swEqnMgr = (EquationMgr)swModel.GetEquationMgr();
                     nCount = swEqnMgr.GetCount();
                    for (i = 0; i < nCount; i++)
                    {
                        Debug.Print("  Equation(" + i + ")  = " + swEqnMgr.get_Equation(i));
                        Debug.Print("    Value = " + swEqnMgr.get_Value(i));
                        Debug.Print("    Index = " + swEqnMgr.Status);
                       Debug.Print("    Global variable? " + swEqnMgr.get_GlobalVariable(i));
                    }
​
                    //修改高度为60
​
                }

C# SolidWorks 二次开发 API—调用Solidworks命令

比如说用户选中一个尺寸时,solidworks的左侧属性框就会自动出来(有个选项可以控制),但此时如果我们想关闭属性框。应该怎么操作? 通过正常的测试可以发现按esc就可以。
当然如果直接发送系统的键盘命令的话,还需要先切换焦点到solidworks中。虽然 也可以实现,相对麻烦。
这时候我们可以通过另一种方式来执行命令,这个方式和我们手动点击菜单中的命令按钮是一样的效果。
这个我就不细说了,下面看一下简单的例子:

首先需要引用SolidWorks.Interop.swcommands
在这里插入图片描述
代码比较简单

			 SldWorks swApp = PStandAlone.GetSolidWorks();

            //执行命令监控
            swApp.CommandOpenPreNotify += SwApp_CommandOpenPreNotify;

            //请参考SolidWorks.Interop.swcommands

            //swCommands_e 命令操作

            //swMouse_e  鼠标操作

            //打开选项对话框
            //swApp.RunCommand((int)swCommands_e.swCommands_Options, "");

            //开始3d草图
            swApp.RunCommand((int)swCommands_e.swCommands_3DSketch, "");

            //单击右键
            //swApp.RunCommand((int)swMouse_e.swMouse_Click, "");

在零件或者装配体的状态下执行后,就会看到solidworks已经在3d草图状态下了。
在这里插入图片描述

下面这个事件就可以对执行的命令进行记录。还可以限制用户进行一些特殊的命令,如下面的代码就禁用了过滤面命令。
这个可以扩展很多功能,比如做一些标准化管理,限制用户乱改配置。

 		/// <summary>
        /// 在执行命令前通知。
        /// </summary>
        /// <param name="Command"></param>
        /// <param name="UserCommand"></param>
        /// <returns></returns>
        private int SwApp_CommandOpenPreNotify(int Command, int UserCommand)
        {
            Debug.Print($@"command is :{Enum.GetName(typeof(swCommands_e), Command)}");

            Debug.Print($@"user command Id is :{UserCommand}");

            if (Command == (int)swCommands_e.swCommands_FilterFaces)
            {
                MessageBox.Show("Fillet Faces Command is disable!");
                return 1;
            }

            return 0;
        }

在用户点击过滤面的时候就会出现:
在这里插入图片描述

C# SolidWorks 二次开发 API—遍历零件所有可编辑尺寸

最近有高校学生问到一个问题,如何得到零件中所有可以编辑的尺寸信息。包括所有的特征以及草图尺寸。之前的博客中只是写了如何遍历特征以及图纸中的尺寸。通过查api发现,其实这个和图纸中标注的尺寸一样,直接使用:先看结果:零件:

        /// <summary>
       /// 遍历特征
       /// </summary>
       /// <param name="thisFeat"></param>
       /// <param name="isTopLevel"></param>
       public static void TraverseFeatures(Feature thisFeat, bool isTopLevel, bool isShowDimension = false)
      {
           Feature curFeat = default(Feature);
           curFeat = thisFeat;

           while ((curFeat != null))
          {
               //输出特征名称
               Debug.Print(curFeat.Name);
               if (isShowDimension == true) ShowDimensionForFeature(curFeat);

               Feature subfeat = default(Feature);
               subfeat = (Feature)curFeat.GetFirstSubFeature();

               while ((subfeat != null))
              {
                   //if (isShowDimension == true) ShowDimensionForFeature(subfeat);
                   TraverseFeatures(subfeat, false);
                   Feature nextSubFeat = default(Feature);
                   nextSubFeat = (Feature)subfeat.GetNextSubFeature();
                   subfeat = nextSubFeat;
                   nextSubFeat = null;
              }

               subfeat = null;

               Feature nextFeat = default(Feature);

               if (isTopLevel)
              {
                   nextFeat = (Feature)curFeat.GetNextFeature();
              }
               else
              {
                   nextFeat = null;
              }

               curFeat = nextFeat;
               nextFeat = null;
          }
      }

       /// <summary>
       /// 遍历零件中的所有特征
       /// </summary>
       /// <param name="feature"></param>
       public static void ShowDimensionForFeature(Feature feature)
      {
           var thisDisplayDim = (DisplayDimension)feature.GetFirstDisplayDimension();

           while (thisDisplayDim != null)
          {
               var dimen = (Dimension)thisDisplayDim.GetDimension();

               Debug.Print($"---特征 {feature.Name} 尺寸-->" + dimen.GetNameForSelection() + "-->" + dimen.Value);

               thisDisplayDim = (DisplayDimension)feature.GetNextDisplayDimension(thisDisplayDim);
          }
      }

代码已经上传,请自取。

C# SolidWorks 二次开发 API —工程图尺寸信息的读取

工程图尺寸信息的读取

前提条件: 在打开的工程图选中一个尺寸
本文目标: 通过转换选择的尺寸为一个尺寸对象,获取该尺寸的值与公差。


 private void btnGetDimensionInfo_Click(object sender, EventArgs e)
        {
            ISldWorks swApp = Utility.ConnectToSolidWorks();
            swApp.CommandInProgress = true;

            ModelDoc2 swModel = (ModelDoc2)swApp.ActiveDoc;

            SelectionMgr selectionMgr = (SelectionMgr)swModel.SelectionManager;

            //转换成尺寸显示对象
            var swDisplayDimension = (DisplayDimension)selectionMgr.GetSelectedObject6(1, 0);

            DisplayData displayData = (DisplayData)swDisplayDimension.GetDisplayData();

            //获取尺寸上的文字
            var anno = (Annotation)swDisplayDimension.GetAnnotation();

            //获取所在视图 ---如果是图纸,这里会报错。需要用OwnerType来判断
            var thisView = (View)anno.Owner;//

            var textwidth = displayData.GetTextInBoxWidthAtIndex(0);

            var textHeight = displayData.GetTextHeightAtIndex(0);

            // dat.GetLineCount 几条线
            var lineCount = displayData.GetLineCount();
            var lineAngle = displayData.GetTextAngleAtIndex(0);
            var linePoints = (double[])displayData.GetLineAtIndex(0);
            var linePoints2 = (double[])displayData.GetLineAtIndex(1);
            var textPoint = (double[])displayData.GetTextPositionAtIndex(0);

            var thisDimAng = lineAngle * 180 / Math.PI;

            //尺寸对象
            var swDimension = (Dimension)swDisplayDimension.GetDimension();

            //获取尺寸的公差
            var cruToleranceType = swDimension.GetToleranceType();
            var cruTolerance = swDimension.Tolerance;

            if (cruToleranceType == (int)swTolType_e.swTolBILAT)
            {
                cruTolerance.GetMaxValue2(out double ToleranceValueMax); //上公差

                cruTolerance.GetMinValue2(out double ToleranceValueMin);//下公差
            }

            var TextAll = swDisplayDimension.GetText((int)swDimensionTextParts_e.swDimensionTextAll);
            var TextPrefix = swDisplayDimension.GetText((int)swDimensionTextParts_e.swDimensionTextPrefix);
            var TextSuffix = swDisplayDimension.GetText((int)swDimensionTextParts_e.swDimensionTextSuffix);
            var CalloutAbove = swDisplayDimension.GetText((int)swDimensionTextParts_e.swDimensionTextCalloutAbove);
            var CalloutBelow = swDisplayDimension.GetText((int)swDimensionTextParts_e.swDimensionTextCalloutBelow);

            var relValue = Math.Round(swDimension.GetSystemValue2("") * 1000, 3).ToString();

            MessageBox.Show(relValue);
        }

上面是代码,有一些备注。

这是初学markdown写的, 源代码继续在码云或者github上拿。

C# SolidWorks 二次开发 API —dll插件如何让 winform 类似ShowDialog,但还能操作solidworks

这篇文章记录一下,这次看api帮助解决到的一个问题:

          由于之前我都是先做好的exe独立开发,后来改成插件形式后遇到的问题。以前经常利用窗体的ShowDialog特性,让程序暂停,让用户进行对象的自定义选择操作,但是到了dll中出现了问题,因为dll和solidworks主进程是一个,所以当用了页面的ShowDialog之后,solidworks就再也无法操作了。这个问题之前花了一天多时间都没搞定,想了好多办法,最后利用的doevents解决的,但是效果不是特别好。

         原来solidworks的帮助文件中已经有了解决方案: 只需要使用 Application.Run(winform)就可以了,我刚才进行了测试,很好用,至于还有没有别的问题,后面再测试一下。

        

         参考链接:

http://help.solidworks.com/2018/English/api/sldworksapiprogguide/overview/Keystrokes_and_Accelerator_Keys_and_ActiveX_Modeless_Dialogs_and_PropertyManager_Pages.htm

C# SolidWorks 二次开发 API —只开工程图的情况下直接转出3D和2D

##昨天晚上有网友咨询了一个问题,问如何只打开工程图的情况下导出step与pdf.

之前我写的博客中存3D格式是在打开的情况下做的,之前我的一篇文章中有写过怎么在工程图中获取零件对象,所以我们只需要在那上面改一改就可以了。直接调用ModelDoc2.Extension.SaveAs方法就可以存成想要的格式,而不产生单独打开窗口的动作了。

代码如下:

           //连接到Solidworks
            ISldWorks swApp = Utility.ConnectToSolidWorks();

            ModelDoc2 swModel = (ModelDoc2)swApp.ActiveDoc;

            // DrawingDoc dc = (DrawingDoc)swModel;

            SelectionMgr selectionMgr = (SelectionMgr)swModel.SelectionManager;

            //获取选择的视图对象
            View view = (View)selectionMgr.GetSelectedObject5(1);

            //获取视图中的引用模型
            var viewModel = view.ReferencedDocument;

            //其它读取属性请参考博文 读取零件属性 ->BtnGetPartData_Click

            MessageBox.Show(viewModel.GetPathName());

            //下面是导出,如果不需要请注释掉以下代码。
            int error = 0;
            int warnings = 0;

            var stepName = System.IO.Path.GetFileNameWithoutExtension(viewModel.GetPathName());

            var bRes = viewModel.Extension.SaveAs($@"D:\{stepName}.step", (int)swSaveAsVersion_e.swSaveAsCurrentVersion, (int)swSaveAsOptions_e.swSaveAsOptions_Silent, null, ref error, ref warnings);

            if (bRes == true)
            {
                MessageBox.Show("Export step Done!");
            }
            else
            {
                MessageBox.Show("Export Error!");
            }

代码已经发布在码云和github.

C# SolidWorks 二次开发 API —注释引用点的坑

最近有个小需求,就是要把注释箭头指向的点的坐标提取出来。
刚开始发现Note.GetAttachPos功能,Annotation.GetPosition有这个功能。
但是经过测试发现,当注释的引线是多折线的时候,上两个函数就是读取的位置有时候对,有时候不对。
本来可以想着把所有的第二种换成第一种,那么获取的时候就应该正确了,但是发现API里面还不能直接转换。

经过大量的调试发现,如果使用的是多折线,但是只有一条折线信息的时候,可能是对的,如果是多折的,基本上不对。
当鼠标移动到引线上时,默认的一段直线直接显示的是注释的图标,当移动到是多段折线上时,显示的是另一个图标,说明它们不是一个对象。而更像是一个组合体。

经过api的检查,发现了这个多折线有一个专门的对象。里面是由多个线的信息组成。

然后又发现Annotation中两个方法 GetMultiJogLeaderCount 和 GetMultiJogLeaders,所以就更显明了。
在获取注释对象 Note的引用点位置时,需要做一个判断。
当GetMultiJogLeaderCount > 0 时,那么说明它是一个多折线的注释,需要使用 MultiJogLeader 来获取信息。遍历其它的关键点坐标。
这个坐标和视图的位置与比例有一定关联,它默认是的整个图纸的坐标。如果需要转换到视图中,还需要做个计算。

下面是一段宏的代码:

Option Explicit
Sub main()
    Dim swApp           As SldWorks.SldWorks
    Dim swModel         As ModelDoc2
    Dim swDraw          As DrawingDoc
    Dim swSelMgr        As SelectionMgr
    Dim swNote          As Note
    Dim swView          As View
    Dim viewPos         As Variant
    Dim notePos         As Variant
    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc
    
     Dim ann As Annotation
     
    If Not swModel Is Nothing Then
        If swModel.GetType <> swDocumentTypes_e.swDocDRAWING Then Exit Sub
        Set swDraw = swModel
        Set swSelMgr = swModel.SelectionManager
        
        Dim selLeaders As SldWorks.MultiJogLeader
          Dim lineData As Variant
          
          
          If swSelMgr.GetSelectedObjectType3(1, -1) <> swSelectType_e.swSelNOTES Then Exit Sub
          
        Set swNote = swSelMgr.GetSelectedObject6(1, 0)
        
        Set swView = swDraw.ActiveDrawingView
        viewPos = swView.Position
        notePos = swNote.GetAttachPos
       
        Set ann = swNote.GetAnnotation
                  
         If ann.GetMultiJogLeaderCount > 0 Then
         
         
         Set selLeaders = ann.GetMultiJogLeaders(0)
         
           If selLeaders Is Nothing = False Then
           
            
            lineData = selLeaders.GetLineAtIndex(0)
            For i = 0 To selLeaders.GetLineCount - 1
            
                 lineData = selLeaders.GetLineAtIndex(i)
                If Not IsEmpty(lineData) Then
                    
                    Debug.Print ("x:" & Math.Round((lineData(1) - viewPos(0)) * 1000# / swView.ScaleDecimal, 4))
                    Debug.Print ("y:" & Math.Round((lineData(2) - viewPos(1)) * 1000# / swView.ScaleDecimal, 4))
                                
                    
                End If
            Next i
           End If
           
           Else
           
         
         End If

           
       
        
' 'ann.UseDocDispLeader = True
       'Debug.Print (swView.Angle * 57.295779513)
' Debug.Print (Math.Round((notePos(0) - viewPos(0)) * 1000# / swView.ScaleDecimal, 4))
' Debug.Print (Math.Round((notePos(1) - viewPos(1)) * 1000# / swView.ScaleDecimal, 4))
' Debug.Print
    End If
End Sub

反之,按正常的GetAttachPos获取对象就可以了。