图元绘制性能问题
在Solidworks二次开发中绘制草图,生成特征时可能会看到图元的绘制动画,虽然看起来赏心悦目,但这无疑拖慢了代码执行速度,让我们看一下有哪些可以优化的点。
草图绘制✏️
图元绘制动画;
草图自动添加约束;
没添加一次图元刷新一下显示界面;
添加尺寸时,可能以为设置原因导致用户需要输入,这会中断代码执行。
其中问题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问题了,这时候我们需要观察一下代码执行的时候哪些区域在跳动或者闪烁:
首先可以确定的是图形区域,这里我们将EnableGraphicsUpdate 设置为false;
另外,在绘制中,属性面板可能会发生闪烁来显示绘制图元的属性,这时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中看到撤销动作。性能提升的同时还可以在此方法中开启撤销😊✨✨✨✨✨