You need a bit study on Overrule's filter. In your case, you want to define your own custon filter: only block reference with given name or with given attribute tag is subject to your ObjectOverrule (cannot be erased).
I put together some quick code here:
using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
namespace StopBlockErasing
{
public class NonErasableBlockOverule : ObjectOverrule
{
private bool _originalOverruling;
private List<string> _blockNames;
public NonErasableBlockOverule()
{
//Get a block name list from settiings
_blockNames = new List<string>();
_blockNames.AddRange(
new string[] { "Block1", "Block2", "Block3" }
);
}
public void StartOverruling()
{
//Save current overruling status (on/off)
_originalOverruling = Overrule.Overruling;
this.SetCustomFilter();
//Add this overule
Overrule.AddOverrule(RXObject.GetClass(typeof(BlockReference)), this, true);
Overrule.Overruling = true;
}
public void StopOverruling()
{
Overrule.RemoveOverrule(RXObject.GetClass(typeof(BlockReference)), this);
//Restore original overruling status
Overrule.Overruling = _originalOverruling;
}
//Implement overrule custom filter: only blockreference with
//give name is applicable
public override bool IsApplicable(RXObject overruledSubject)
{
BlockReference bref = overruledSubject as BlockReference;
if (bref == null) return false;
return IsTargetBlock(bref.Name);
}
public override void Erase(DBObject dbObject, bool erasing)
{
base.Erase(dbObject, erasing);
throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NotApplicable);
}
#region private methods
private bool IsTargetBlock(string blkName)
{
foreach (string b in _blockNames)
{
if (b.ToUpper() == blkName.ToUpper()) return true;
}
return false;
}
#endregion
//------------------------------------------------------------
// Another version of IsApplication() implementing
// If a given attribute tag presents in the block
//------------------------------------------------------------
//public override bool IsApplicable(RXObject overruledSubject)
//{
// BlockReference bref = overruledSubject as BlockReference;
// if (bref == null) return false;
// //if we need to go through attribute to determine
// //whether the block should be erased or not
// if (bref.AttributeCollection.Count == 0) return false;
// Database db = bref.Database;
// using (Transaction tran = db.TransactionManager.StartTransaction())
// {
// foreach (ObjectId id in bref.AttributeCollection)
// {
// AttributeReference aref = tran.GetObject(
// id, OpenMode.ForRead) as AttributeReference;
// if (aref != null)
// {
// //Only remove a block, if one of its attribute tag is "AAA"
// if (aref.Tag.ToUpper() == "AAA") return true;
// }
// }
// }
// return false;
//}
}
} Here is the code to run it:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
[assembly: CommandClass(typeof(StopBlockErasing.MyCommands))]
namespace StopBlockErasing
{
class MyCommands
{
private static bool _blockOverruling = false;
private static NonErasableBlockOverule _myOverrule=null;
[CommandMethod("BlkOverrule")]
public static void MyCmd()
{
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
if (_myOverrule == null) _myOverrule = new NonErasableBlockOverule();
if (_blockOverruling)
{
_myOverrule.StopOverruling();
_blockOverruling=false;
ed.WriteMessage("\nNonErasableBlock Overrule is turned off.\n");
}
else
{
_myOverrule.StartOverruling();
_blockOverruling = true;
ed.WriteMessage("\nNonErasableBlock Overrule is turned on.\n");
}
}
}
} The code is in C#, but I think it would be easy to figure its VB.NET equivalent easily.
The IsApplicable is implemented this way: as long as the block name is "Block1", Block2" or "Block3", then the block cannot be erased. The extra IsApplicable() being commented out at the bottom is to check if a block has an attribute with Tag named as "AAA", if yes, the block is not erasable.
Notice the line:
this.SetCustomFilter();
You must call this method in order to tell Overrule to use your overriden IsApplicable() as custom filter.
I did run the code with my Acad2012 successfully (of make some block not erasable).
HTH.