在cad二次开发中,我发现使用.net切换图层的锁定状态后,命令结束,图元并不会亮显(或暗显),失去了原有命令的效果。
解决方案1
经过我的一番查找,发现以下api可以解决
LayerUtilities.RegenLayers(layerIds,LayerUtilities.RegenPending);
其中layerIds是你要刷新显示的图层表记录的id列表。
但是我发现,此api在cad2015和cad2018上是有差异的,在cad2018上使用此函数会报错,因为cad2015到cad2024的api都是大概相同的,一般编译一个版本即可通用。
但此api在在cad2017版本修改到了CoreLayerUtilities类中,导致无法在低版本中使用。
如果不想为了这一个地方添加复杂的条件编译,可以采用反射的方式。
public static void RegenLayers(IEnumerable<ObjectId> layerIds)
{
var type = Acaop.Version.Major >= 21
? Assembly.Load("accoremgd")?.GetType("Autodesk.AutoCAD.Internal.CoreLayerUtilities")
: Assembly.Load("acmgd")?.GetType("Autodesk.AutoCAD.Internal.LayerUtilities");
if (type == null)
return;
var mi = type.GetMethods()
.FirstOrDefault(e =>
{
if (e.Name != "RegenLayers")
return false;
var parameterInfos = e.GetParameters();
if (parameterInfos.Length != 2)
return false;
if (parameterInfos[0].ParameterType != typeof(ObjectId[]))
return false;
if (parameterInfos[1].ParameterType != typeof(int))
return false;
return true;
});
if (mi == null)
return;
var pi = type.GetProperties().FirstOrDefault(e => e.Name == "RegenPending");
var regenPending = (int)(pi?.GetValue(null) ?? 0);
mi.Invoke(null, [layerIds.ToArray(), regenPending]);
}
解决方案2
从惊惊那里知道的方法。
对图层表表记录的IsOff属性进行赋值(原值也可以)即可触发cad底层的某些机制,然后再对图元进行刷新就可以了。
此代码收录在了IFoxCAD的IFoxUtils.RegenLayers2中。
/// <summary>
/// 刷新图层状态,在修改图层的锁定或冻结状态后使用
/// </summary>
/// <param name="layerIds">图层id集合</param>
public static void RegenLayers2(IEnumerable<ObjectId> layerIds)
{
var isOff = false;
var layerRxc = RXObject.GetClass(typeof(LayerTableRecord));
var entityRxc = RXObject.GetClass(typeof(Entity));
foreach (var group in layerIds.Where(e => e.IsOk() && e.ObjectClass.IsDerivedFrom(layerRxc))
.GroupBy(e => e.Database))
{
var db = group.Key;
var doc = Acap.DocumentManager.GetDocument(db);
if (doc is null)
continue; // 获取不到文档说明是后台开图,后台开图就不用刷新了
using var dl = doc.LockDocument();
using var tr = new DBTrans(db);
var layerIdSet = group.ToHashSet();
foreach (var ltr in layerIdSet.Select(id => tr.GetObject(id, OpenMode.ForWrite))
.OfType<LayerTableRecord>())
{
Volatile.Write(ref isOff, ltr.IsOff);
ltr.IsOff = Volatile.Read(ref isOff);
}
for (var i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++)
{
if (!db.TryGetObjectId(new Handle(i), out var id) || !id.IsOk() ||
!id.ObjectClass.IsDerivedFrom(entityRxc))
continue;
var ent = (Entity)tr.GetObject(id, OpenMode.ForWrite, false, true);
if (!layerIdSet.Contains(ent.LayerId))
continue;
ent.RecordGraphicsModified(true);
try
{
ent.TransformBy(Matrix3d.Identity);
}
catch (Exception)
{
// 某些类型如blockbegin blockend等不能进行矩阵转换
}
}
}
}
评论