在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底层的某些机制,然后再对图元进行刷新就可以了。
此代码收录在了IFoxCADIFoxUtils.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等不能进行矩阵转换
            }
        }
    }
}