C# SolidWorks 二次开发 API—插入库特征

要想提高设计效率,做库特征是很常见的。例如我们下面这个视频,利用库特征在打了很多小孔。

利用库特征快速插入特征

这一次我们来看如何用代码插入库特征。

我们以API实例中的一个例子来说明一下过程:

        public DispatchWrapper[] ObjectArrayToDispatchWrapperArray(object[] Objects)
        {
            int ArraySize = 0;
            ArraySize = Objects.GetUpperBound(0);
            DispatchWrapper[] d = new DispatchWrapper[ArraySize + 1];
            int ArrayIndex = 0;
            for (ArrayIndex = 0; ArrayIndex <= ArraySize; ArrayIndex++)
            {
                d[ArrayIndex] = new DispatchWrapper(Objects[ArrayIndex]);
            }
            return d;
        }

        public DispatchWrapper[] LibRefs;

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

            //可以参考API帮助中的:Create Library Feature Data Object and Library Feature With References Example (C#)

            //Step1:新建一个零件.
            Feature swFeature = default(Feature);
            ModelDoc2 swModel = default(ModelDoc2);
            ModelDocExtension swModelDocExt = default(ModelDocExtension);
            SketchManager swSketchManager = default(SketchManager);
            SelectionMgr swSelectionManager = default(SelectionMgr);
            FeatureManager swFeatureManager = default(FeatureManager);
            LibraryFeatureData swLibFeat = default(LibraryFeatureData);
            bool status = false;
            object[] sketchLines = null;
            object Refs = null;
            object RefTypes = null;
            int RefCount = 0;
            int k = 0;
            int i = 0;
            DispatchWrapper[] LibRefs = null;

            string libPath = "C:\\ProgramData\\SOLIDWORKS\\SOLIDWORKS 2018\\design library\\features\\metric\\slots\\straight slot.sldlfp";

            // Create part
            swModel = (ModelDoc2)swApp.NewDocument("C:\\ProgramData\\SolidWorks\\SOLIDWORKS 2018\\templates\\Part.prtdot", 0, 0, 0);
            swModelDocExt = (ModelDocExtension)swModel.Extension;
            status = swModelDocExt.SelectByID2("Top Plane", "PLANE", 0, 0, 0, false, 0, null, 0);
            swModel.ClearSelection2(true);
            status = swModelDocExt.SetUserPreferenceToggle((int)swUserPreferenceToggle_e.swSketchAddConstToRectEntity, (int)swUserPreferenceOption_e.swDetailingNoOptionSpecified, false);
            status = swModelDocExt.SetUserPreferenceToggle((int)swUserPreferenceToggle_e.swSketchAddConstLineDiagonalType, (int)swUserPreferenceOption_e.swDetailingNoOptionSpecified, true);
            swSketchManager = (SketchManager)swModel.SketchManager;
            sketchLines = (object[])swSketchManager.CreateCornerRectangle(0, 0, 0, 1, 0.5, 0);
            swModel.ShowNamedView2("*Trimetric", 8);
            swModel.ClearSelection2(true);
            status = swModelDocExt.SelectByID2("Line2", "SKETCHSEGMENT", 0, 0, 0, false, 0, null, 0);
            status = swModelDocExt.SelectByID2("Line1", "SKETCHSEGMENT", 0, 0, 0, true, 0, null, 0);
            status = swModelDocExt.SelectByID2("Line4", "SKETCHSEGMENT", 0, 0, 0, true, 0, null, 0);
            status = swModelDocExt.SelectByID2("Line3", "SKETCHSEGMENT", 0, 0, 0, true, 0, null, 0);
            swFeatureManager = (FeatureManager)swModel.FeatureManager;
            swFeature = (Feature)swFeatureManager.FeatureExtrusion2(true, false, false, 0, 0, 0.01, 0.01, false, false, false,
            false, 0.0174532925199433, 0.0174532925199433, false, false, false, false, true, true, true,
            0, 0, false);
            swSelectionManager = (SelectionMgr)swModel.SelectionManager;
            swSelectionManager.EnableContourSelection = false;

            swModel = (ModelDoc2)swApp.ActiveDoc;

            string actName = swModel.GetPathName();

            #region 第一种方法

            //Step2:初始化库特征
            swLibFeat = (LibraryFeatureData)swFeatureManager.CreateDefinition((int)swFeatureNameID_e.swFmLibraryFeature);
            status = swLibFeat.Initialize(libPath);

            //step3:获取库特征需要的参考对象
            RefCount = swLibFeat.GetReferencesCount();
            Refs = (object[])swLibFeat.GetReferences2((int)swLibFeatureData_e.swLibFeatureData_FeatureRespect, out RefTypes);

            if ((RefTypes != null))
            {
                Debug.Print("Types of references required (edge = 1): ");
                int[] RefType = (int[])RefTypes;
                for (k = RefType.GetLowerBound(0); k <= RefType.GetUpperBound(0); k++)
                {
                    Debug.Print("    " + RefType[k].ToString());
                }
            }
            //setp4:设定库特征默认的配置名称
            swLibFeat.ConfigurationName = "Default";
            //setp5:选择一个面,并插入库特征
            status = swModelDocExt.SelectByID2("", "FACE", 0.522458766456054, 0.288038964184011, 0.00999999999987722, false, 0, null, 0);
            swFeature = (Feature)swFeatureManager.CreateFeature(swLibFeat);
            //step6:
            swLibFeat = null;
            swLibFeat = (LibraryFeatureData)swFeature.GetDefinition();
            status = swLibFeat.AccessSelections(swModel, null);

            //step7:选择真实的参考
            status = swModelDocExt.SelectByID2("", "EDGE", 0.960865149149924, 0.497807163546383, 0.0131011390528215, true, 0, null, 0);
            status = swModelDocExt.SelectByID2("", "EDGE", 0.99866860703213, 0.481385806014544, 0.0113313929676906, true, 0, null, 0);
            int selCount = 0;
            selCount = swSelectionManager.GetSelectedObjectCount2(-1);

            object[] selectedObjects = new object[selCount];

            for (i = 0; i < selCount; i++)
            {
                object selectedObject = null;
                selectedObject = (object)swSelectionManager.GetSelectedObject6(i + 1, -1);
                selectedObjects[i] = selectedObject;
            }

            // 转换对象
            LibRefs = (DispatchWrapper[])ObjectArrayToDispatchWrapperArray((selectedObjects));

            // 设定引用关系到刚生成的库特征
            swLibFeat.SetReferences(LibRefs);

            // 更新库功能
            status = swFeature.ModifyDefinition(swLibFeat, swModel, null);

            // 取消抑制库功能
            status = swModelDocExt.SelectByID2("straight slot<1>", "BODYFEATURE", 0, 0, 0, false, 0, null, 0);
            swModel.EditUnsuppress2();

            swModel.ClearSelection2(true);

            #endregion 第一种方法

            #region 第二种方法(已过时)

            ////先选中线,再插入库特征.

            ////要先打开库特征,然后切换到当前零件,选中参考特征,最后插入特征库

            //int errors = 0;
            //int warnings = 0;

            //swApp.OpenDoc6(libPath, 1, 0, "", errors, warnings);

            //swModel = swApp.ActivateDoc2(actName, true, errors);

            //status = swModelDocExt.SelectByID2("", "FACE", 0.522458766456054, 0.288038964184011, 9.99999999987722E-03, false, 0, null, 0);
            //status = swModelDocExt.SelectByID2("", "EDGE", 0.960865149149924, 0.497807163546383, 0.0131011390528215, true, 1, null, 0);
            //status = swModelDocExt.SelectByID2("", "EDGE", 0.99866860703213, 0.481385806014544, 0.0113313929676906, true, 2, null, 0);

            //swModel.InsertLibraryFeature(libPath);

            #endregion 第二种方法(已过时)
        }
  

 

C# SolidWorks 二次开发 API—指定过滤器

当我们需要用户选择时,可以利用代码创建指定的选择器.

其实就像手工点击工具条内的过滤器一样:

 

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

            ModelDoc2 modelDoc2 = swApp.ActiveDoc;
            //SelectionMgr selectionMgr = modelDoc2.SelectionManager;

            //设置可选择类型的数组
            swSelectType_e[] filters = new swSelectType_e[1];

            //让用户只能选择实体

            filters[0] = swSelectType_e.swSelSOLIDBODIES;

            swApp.SetSelectionFilters(filters, true);
        }

 

C# SolidWorks 二次开发 API—删除草图中的约束关系

这一个比较简单,其实就是遍历一下草图中的对象,然后获取关系,删除.

代码:

 private void btn_DeleteConstraints_Click(object sender, EventArgs e)
        {
            //请先打开clamp1这个零件

            ISldWorks swApp = Utility.ConnectToSolidWorks();
            ModelDoc2 swModel = swApp.ActiveDoc;
            SelectionMgr swSelMgr = swModel.SelectionManager;

            //选择草图
            swModel.Extension.SelectByID2("Sketch2", "SKETCH", 0, 0, 0, false, 4, null, 0);

            //进入编辑草图
            swModel.EditSketch();

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

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

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

            SketchSegment swSketchSeg;
            //遍历线
            for (int i = 0; i < vSketchSeg.Length; i++)
            {
                swSketchSeg = (SketchSegment)vSketchSeg[i];
                swSketchSeg.Select4(false, swSelData);
                //删除关系
                swModel.SketchConstraintsDelAll();
            }


            object[] vSketchPt = (SketchPoint[])swSketch.GetSketchPoints2();
            SketchPoint swSketchPt;
            //遍历点
            for (int i = 0; i < vSketchPt.Length; i++)
            {
                swSketchPt = (SketchPoint)vSketchPt[i];
                swSketchPt.Select4(false, swSelData);
                swModel.SketchConstraintsDelAll();
            }
            //退出编辑草图
            swModel.InsertSketch2(true);

            swModel.ClearSelection2(true);
        }

 

C# SolidWorks 二次开发 API—增加第三方数据流

今天增加了如何保存文件的第三数据流到solidworks的文件中.

例如xml文件,文本信息.

 private ModelDoc2 m_RefDoc; //增加第三方数据流 共用模型.

        private void btn_ThridData_Click(object sender, EventArgs e)
        {
            //https://www.codestack.net/solidworks-api/data-storage/third-party/embed-file/
            ISldWorks swApp = Utility.ConnectToSolidWorks();

            ModelDoc2 swModel = default(ModelDoc2);
            ModelDocExtension swModelDocExt = default(ModelDocExtension);

            swModel = swApp.ActiveDoc;
            m_RefDoc = swModel;

            switch (swModel.GetType())
            {
                case (int)swDocumentTypes_e.swDocPART:
                    (swModel as PartDoc).SaveToStorageNotify += new DPartDocEvents_SaveToStorageNotifyEventHandler(OnSaveToStorage);
                    break;

                case (int)swDocumentTypes_e.swDocASSEMBLY:
                    (swModel as AssemblyDoc).SaveToStorageNotify += new DAssemblyDocEvents_SaveToStorageNotifyEventHandler(OnSaveToStorage);
                    break;
            }

            swModel.SetSaveFlag();
 swApp.SendMsgToUser("请手动保存文件!这样会把数据流写入文件中.");
        }

        private int OnSaveToStorage()
        {
            IStream iStr = (IStream)m_RefDoc.IGet3rdPartyStorage("Tool.Name", true);

            using (ComStream comStr = new ComStream(iStr))
            {
                byte[] data = Encoding.Unicode.GetBytes("Paine's Tool");
                comStr.Write(data, 0, data.Length);
            }

            m_RefDoc.IRelease3rdPartyStorage("Tool.Name");

            return 0;
        }

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

            // ModelDoc2 swModel = default(ModelDoc2);

            IModelDoc2 doc = swApp.IActiveDoc2;
            ISelectionMgr selMgr = doc.ISelectionManager;
            //  IComponent2 comp = selMgr.GetSelectedObjectsComponent3(1, -1);

            IStream iStr = (IStream)doc.IGet3rdPartyStorage("Tool.Name", false);

            if (iStr != null)
            {
                using (ComStream comStr = new ComStream(iStr))
                {
                    byte[] data = new byte[comStr.Length];
                    comStr.Read(data, 0, (int)comStr.Length);

                    string strData = Encoding.Unicode.GetString(data);
                    MessageBox.Show(strData);
                }

                doc.IRelease3rdPartyStorage("Tool.Name");
            }
        }
   
    public class ComStream : Stream
    {
        //The managed stream being wrapped
        private IStream originalStream_;

        public ComStream(IStream stream)
        {
            if (stream != null)
            {
                originalStream_ = stream;
            }
            else
            {
                throw new ArgumentNullException("stream");
            }
        }

        ~ComStream()
        {
            Close();
        }

        // property to get original stream object
        public IStream UnderlyingStream
        {
            get
            {
                return originalStream_;
            }
        }

        // reads a specified number of bytes from the stream object
        // into memory starting at the current seek pointer
        public unsafe override int Read(byte[] buffer, int offset, int count)
        {
            if (originalStream_ == null)
            {
                throw new ObjectDisposedException("originalStream_");
            }

            if (offset != 0)
            {
                throw new NotSupportedException("only 0 offset is supported");
            }

            int bytesRead;

            IntPtr address = new IntPtr(&bytesRead);

            originalStream_.Read(buffer, count, address);

            return bytesRead;
        }

        // writes a specified number of bytes into the stream object
        // starting at the current seek pointer
        public override void Write(byte[] buffer, int offset, int count)
        {
            if (originalStream_ == null)
            {
                throw new ObjectDisposedException("originalStream_");
            }

            if (offset != 0)
            {
                throw new NotSupportedException("only 0 offset is supported");
            }

            originalStream_.Write(buffer, count, IntPtr.Zero);
        }

        // changes the seek pointer to a new location relative to the beginning
        // of the stream, the end of the stream, or the current seek position

        public unsafe override long Seek(long offset, SeekOrigin origin)
        {
            if (originalStream_ == null)
            {
                throw new ObjectDisposedException("originalStream_");
            }

            long position = 0;

            IntPtr address = new IntPtr(&position);

            originalStream_.Seek(offset, (int)origin, address);

            return position;
        }

        public override long Length
        {
            get
            {
                if (originalStream_ == null)
                {
                    throw new ObjectDisposedException("originalStream_");
                }

                STATSTG statstg;

                originalStream_.Stat(out statstg, 1 /* STATSFLAG_NONAME*/ );

                return statstg.cbSize;
            }
        }

        public override long Position
        {
            get
            {
                return Seek(0, SeekOrigin.Current);
            }
            set
            {
                Seek(value, SeekOrigin.Begin);
            }
        }

        // changes the size of the stream object
        public override void SetLength(long value)
        {
            if (originalStream_ == null)
            {
                throw new ObjectDisposedException("originalStream_");
            }

            originalStream_.SetSize(value);
        }

        // closes (disposes) the stream
        public override void Close()
        {
            if (originalStream_ != null)
            {
                originalStream_.Commit(0);

                // Marshal.ReleaseComObject( originalStream_ );
                originalStream_ = null;

                GC.SuppressFinalize(this);
            }
        }

        public override void Flush()
        {
            originalStream_.Commit(0);
        }

        public override bool CanRead
        {
            get
            {
                return true;
            }
        }

        public override bool CanWrite
        {
            get
            {
                return true;
            }
        }

        public override bool CanSeek
        {
            get
            {
                return true;
            }
        }
    }

 

C# SolidWorks 二次开发 API — 高级选择器

Solidworks在装配体中提供了一项高级选择的功能.

这个功能可以很快的选择我们想要选择的一些零件.尤其是比较大的装配体,效率比遍历装配体之后 再通过程序过滤来选择想要的零件快.

 

上代码:

  #region 高级选择

        private void btn_Adv_Select_Click(object sender, EventArgs e)
        {
            //请先打开C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2018\samples\tutorial\api\landing_gear.sldasm

            //参考资料为API 帮助中的 Use Advanced Component Selection Example (C#)

            ISldWorks swApp = Utility.ConnectToSolidWorks();
            ModelDoc2 swModel = default(ModelDoc2);

            swModel = swApp.ActiveDoc;

            int DocType = 0;
            DocType = swModel.GetType();

            if (DocType != (int)swDocumentTypes_e.swDocASSEMBLY)
            {
                swApp.SendMsgToUser("当前不是装配体!");
                return;
            }

            AdvancedSelectionCriteria advancedSelectionCriteria = default(AdvancedSelectionCriteria);

            AssemblyDoc assemblyDoc = (AssemblyDoc)swModel;

            advancedSelectionCriteria = assemblyDoc.GetAdvancedSelection();

            int count = advancedSelectionCriteria.GetItemCount();

            //清空选择条件
            for (int i = 0; i < advancedSelectionCriteria.GetItemCount(); i++)
            {
                advancedSelectionCriteria.DeleteItem(i);
            }

            //增加选择条件 : 文件名包含lnk
            advancedSelectionCriteria.AddItem("Document name -- SW Special", 16, "lnk", false);
            //增加选择条件(或者) : 文件名包含hub
            advancedSelectionCriteria.AddItem("Document name -- SW Special", 16, "hub", false);

            //解释当前的选择条件
            ReportAllValues(advancedSelectionCriteria);

            //选择
            var SelectSuccess = advancedSelectionCriteria.Select();

            if (SelectSuccess == true)//选择成功
            {
                SelectionMgr selectionMgr = swModel.SelectionManager;
                Component2 swComp;
                //遍历已经选择的零件
                for (int j = 0; j < selectionMgr.GetSelectedObjectCount(); j++)
                {
                    swComp = selectionMgr.GetSelectedObject6(j + 1, 0);

                    swModel = swComp.GetModelDoc2();

                    //显示文件名
                    Debug.Print(swModel.GetPathName());
                }
            }
        }

        public string GetStringFromEnum(int EnumVal)
        {
            string functionReturnValue = null;
            //From enum swAdvSelecType_e
            if (EnumVal == 1)
            {
                functionReturnValue = "And";
            }
            else if (EnumVal == 2)
            {
                functionReturnValue = "Or";
            }
            else if (EnumVal == 16384)
            {
                functionReturnValue = "is yes";
            }
            else if (EnumVal == 32768)
            {
                functionReturnValue = "is no";
            }
            else if (EnumVal == 8)
            {
                functionReturnValue = "is not";
            }
            else if (EnumVal == 16)
            {
                functionReturnValue = "contains";
            }
            else if (EnumVal == 32)
            {
                functionReturnValue = "Is_Contained_By";
            }
            else if (EnumVal == 64)
            {
                functionReturnValue = "Interferes_With";
            }
            else if (EnumVal == 128)
            {
                functionReturnValue = "Does_Not_Interferes_With";
            }
            else if (EnumVal == 4)
            {
                functionReturnValue = "is (exactly)";
            }
            else if (EnumVal == 8192)
            {
                functionReturnValue = "not =";
            }
            else if (EnumVal == 512)
            {
                functionReturnValue = "<";
            }
            else if (EnumVal == 2048)
            {
                functionReturnValue = "<=";
            }
            else if (EnumVal == 4096)
            {
                functionReturnValue = "=";
            }
            else if (EnumVal == 1024)
            {
                functionReturnValue = ">=";
            }
            else if (EnumVal == 256)
            {
                functionReturnValue = ">";
            }
            else
            {
                functionReturnValue = "Condition NOT found";
            }
            return functionReturnValue;
        }

        public void ReportAllValues(AdvancedSelectionCriteria AdvancedSelectionCriteria)
        {
            Debug.Print("");

            int Count = 0;
            Count = AdvancedSelectionCriteria.GetItemCount();
            Debug.Print("GetItemCount returned " + Count);

            int i = 0;
            string aProperty = "";
            int Condition = 0;
            string Value = "";
            bool IsAnd = false;
            int Rindex = 0;
            string ConditionString = null;
            string PrintString = null;

            string IndexFmt = null;
            string RindexFmt = null;
            string AndOrFmt = null;
            string PropertyFmt = null;
            string ConditionFmt = null;
            string ValueFmt = null;
            IndexFmt = "!@@@@@@@@";
            RindexFmt = "!@@@@@@@@@";
            AndOrFmt = "!@@@@@@@@@";
            PropertyFmt = "!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
            ConditionFmt = "!@@@@@@@@@@@@@@@";
            ValueFmt = "#.00";

            //Debug.Print
            PrintString = string.Format("Index", IndexFmt) + "     " + string.Format("Rindex", RindexFmt) + "  " + string.Format("And/Or", AndOrFmt) + "  " + string.Format("Property", PropertyFmt) + "                     " + string.Format("Condition", ConditionFmt) + "     " + string.Format("Value", ValueFmt);
            Debug.Print(PrintString);
            for (i = 0; i <= Count - 1; i++)
            {
                Rindex = AdvancedSelectionCriteria.GetItem(i, out aProperty, out Condition, out Value, out IsAnd);
                ConditionString = GetStringFromEnum(Condition);
                PrintString = string.Format(i.ToString(), IndexFmt) + "         " + string.Format(Rindex.ToString(), RindexFmt) + "       " + string.Format((IsAnd == false ? "OR" : "AND"), AndOrFmt) + "      " + string.Format(aProperty, PropertyFmt) + "  " + string.Format(ConditionString, ConditionFmt) + "  " + string.Format(Value, ValueFmt);
                Debug.Print(PrintString);
            }
            Debug.Print("");
        }

        #endregion 高级选择

 

 

C# SolidWorks 二次开发 API—提示信息与进度条

有些情况 我们需要像solidworks的内部命令一样提示用户现在该做什么,或者说要显示一下当前进度.

第一种方法就是自己设计一个界面,上面放进度条,这种可以弄成自己想要的样式,但是我们今天要说的是自带的方法:

win10下进度条是在系统任务栏中显示,win7应该是在solidworks的状态栏中.

 

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

            ModelDoc2 swModel = default(ModelDoc2);
            ModelDocExtension swModelDocExt = default(ModelDocExtension);

            Frame swFrame = swApp.Frame();

            swFrame.SetStatusBarText("这里是提示信息-->");

            swApp.SendMsgToUser("下面提示显示进度条:");

            UserProgressBar userProgressBar;

            swApp.GetUserProgressBar(out userProgressBar);

            userProgressBar.Start(0, 100, "Status");

            int Position = 0;

            for (int i = 0; i <= 100; i++)
            {
                Position = i * 10;

                if (Position == 100)
                {
                    Position = 0;
                    break;
                }

                var lRet = userProgressBar.UpdateProgress(Position);
                userProgressBar.UpdateTitle("当前进度--->" + Position);

                swApp.SendMsgToUser("当前进度--->" + Position);
            }

            userProgressBar.End();
        }