weigan
发布于 2024-08-17 / 92 阅读
0
0

Solidworks二次开发-性能最佳实践

图元绘制性能问题

在Solidworks二次开发中绘制草图,生成特征时可能会看到图元的绘制动画,虽然看起来赏心悦目,但这无疑拖慢了代码执行速度,让我们看一下有哪些可以优化的点。

草图绘制✏️

  1. 图元绘制动画;

  2. 草图自动添加约束;

  3. 没添加一次图元刷新一下显示界面;

  4. 添加尺寸时,可能以为设置原因导致用户需要输入,这会中断代码执行。

其中问题2和4和设置有关,这里我们引入一个扩展方法,这个方法在代码执行的过程中临时改变用户设置,并在执行完成后回复用户设置。

        /// <summary>
        /// 设置一个选项后执行动作,执行完后设置回系统默认值
        /// </summary>
        /// <param name="app">ISldwork interface</param>
        /// <param name="action">执行的动作</param>
        /// <param name="keyValuePairs">需要设置的枚举和值的对</param>
        public static void WithMutiToggleState(
            this ISldWorks app, 
            Action action, 
            params KeyValuePair<swUserPreferenceToggle_e, bool>[] keyValuePairs)
        {
            bool[] states = new bool[keyValuePairs.Length];
            try
            {
                for (int i = 0; i < keyValuePairs.Length; i++)
                {
                    states[i] = app.GetUserPreferenceToggle((int)keyValuePairs[i].Key);
                    app.SetUserPreferenceToggle((int)keyValuePairs[i].Key, keyValuePairs[i].Value);
                }
                action?.Invoke();
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                for (int i = 0; i < keyValuePairs.Length; i++)
                {
                    app.SetUserPreferenceToggle((int)keyValuePairs[i].Key, states[i]);
                }
            }
        }

在解决了2和4问题后,我们需要考虑的是1和3问题了,这时候我们需要观察一下代码执行的时候哪些区域在跳动或者闪烁:

  1. 首先可以确定的是图形区域,这里我们将EnableGraphicsUpdate 设置为false;

  2. 另外,在绘制中,属性面板可能会发生闪烁来显示绘制图元的属性,这时EnableFeatureTreeWindow 和 EnableFeatureTree 提供了必要的设置。

完成后的代码如下。

        /// <summary>执行代码时不刷新图像区域 和 特征树</summary>
        public static void WithNoRefresh(this IModelDoc2 doc, Action action)
        {
            if (doc is null)
            {
                throw new ArgumentNullException(nameof(doc));
            }

            IModelView swView = null;
            try
            {
                swView = doc.ActiveView as IModelView;
                swView.SuppressWaitCursorDuringRedraw = true;
                swView.EnableGraphicsUpdate = false;
                doc.FeatureManager.EnableFeatureTreeWindow = false;
                doc.FeatureManager.EnableFeatureTree = false;


                action?.Invoke();
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {

                doc.FeatureManager.EnableFeatureTreeWindow = true;
                doc.FeatureManager.EnableFeatureTree = true;

                swView.EnableGraphicsUpdate = true;
                swView.SuppressWaitCursorDuringRedraw = false;
            }
        }

特征绘制🧱

与草图绘制有所区别的是,特征绘制主要是图像区域和UI的闪烁,和Solidworks设置项关系不大,所以只需要`WithNoRefresh`此方法即可。但一般特征绘制也会伴随这草图绘制,下面我们就将这两个方法结合起来,创建一个统一的方法来提示绘制性能。

图元绘制🎨

以下方法是我们最终可以提升性能的最终方法,将你的代码放在action里尝试以下吧,看看速度能不能提升个10倍🚀🚀🚀🚀🚀🚀

        /// <summary>
        /// 使用SolidWorks Api做操作
        /// </summary>
        /// <param name="app"><see cref="ISldWorks"/></param>
        /// <param name="action">做的动作</param>
        /// <param name="noRefresh">是否更新图形区</param>
        /// <param name="actionName">撤销名称</param>
        /// <param name="ignoreUndo">此次操作不产生撤销操作</param>
        public static void WithApiDocState(
            this ISldWorks app, 
            Action<IModelDoc2> action, 
            bool noRefresh = true, 
            string actionName = "", 
            bool ignoreUndo = false)
        {
            var doc = app.ActiveDoc as ModelDoc2;
            if (doc == null)
            {
                throw new ArgumentNullException("No active doc");
            }
            try
            {
                if (!string.IsNullOrEmpty(actionName))
                    doc.Extension.StartRecordingUndoObject();

                app.WithMutiToggleState(() =>
                {
                    if (noRefresh)
                        doc.WithNoRefresh(() =>
                        {
                            action?.Invoke(doc);
                        });
                    else
                        action?.Invoke(doc);

                }, new KeyValuePair<swUserPreferenceToggle_e, bool>(swUserPreferenceToggle_e.swSketchInference, false),
                new KeyValuePair<swUserPreferenceToggle_e, bool>(swUserPreferenceToggle_e.swInputDimValOnCreate, false
                ));
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (!string.IsNullOrEmpty(actionName))
                    doc.Extension.FinishRecordingUndoObject2(actionName, ignoreUndo);
            }
        }

撤销支持🔄

注意看以上方法,提供了一个actionName 参数。当你指定了此参数,方法将调用api记录你对Solidworks的操作,执行完成后可以在solidworks中看到撤销动作。性能提升的同时还可以在此方法中开启撤销😊✨✨✨✨✨


评论