Here is my effort cobbled together from the ADN doc Kean mentions and the ARX sample CircleStandard:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace tcgsAcStdCircles
{
[ProgId("tcgsAcStdCircles.AcStdCirclesTest")]
[ClassInterface(ClassInterfaceType.None)]
[Guid("B26515F6-D667-467d-9F9F-E2A0B3ADD594")]
[ComVisible(true)]
public class AcStdCirclesTest : AcStMgr.IAcStPlugin2
{
#region Private field(s)
private string _name;
private string _author;
private string _description;
private string _href;
private string _version;
private string _propName;
private AcStMgr.AcStManager _manager;
private AcStdCirclesTest _plugin;
private AcStMgr.AcStError _error;
private AXDBLib.AcadDatabase _checkDb;
private AXDBLib.AcadDatabase _dwsDb;
private List<CircleCache> _circleCache;
private List<int> _idsToCheck;
private bool _useDb;
private int _currentIndex;
private int _recommendedFixIndex;
private int _fixCount;
#endregion
#region Default ctor
public AcStdCirclesTest()
{
_name = "Circles";
_author = "TCGSoftware";
_description = "Checks that properties of circles in a drawing match those in an associated standards file.";
_href = "www.tcgsoftware.com";
_version = "1.0";
_idsToCheck = new List<int>();
_circleCache = new List<CircleCache>();
_useDb = false;
}
#endregion
#region IAcStPlugin2 Members
public string Author
{
get { return _author; }
}
public void CheckSysvar(string syvarName, bool bGetAllFixes, ref bool bPassFail)
{
// Not implemented yet.
}
public void Clear()
{
_name = string.Empty;
_description = string.Empty;
_author = string.Empty;
_href = string.Empty;
_version = string.Empty;
if (_circleCache != null)
{
for (int i = 0; i < _circleCache.Count; i++)
{
if (_circleCache[i].Fix != null)
{
_circleCache[i].Fix.Reset();
_circleCache[i] = null;
}
}
_circleCache = null;
}
_plugin = null;
_manager = null;
if (_error != null)
{
_error.Reset();
_error = null;
}
_checkDb = null;
_dwsDb = null;
_idsToCheck.Clear();
_idsToCheck = null;
}
public string Description
{
get { return _description; }
}
public bool Done()
{
return (_error == null);
}
public void FixError(AcStMgr.AcStError pError, AcStMgr.AcStFix pFix, out string pFailedReason)
{
pFailedReason = "0";
if (pError != null)
{
object fixVal = null;
int badEntId = pError.BadObjectId;
AXDBLib.AcadCircle badEnt = _checkDb.ObjectIdToObject(badEntId) as AXDBLib.AcadCircle;
if (pFix == null)
{
// if the fix object is null, then attempt to get a recommended fix
AcStMgr.AcStFix tmpFix = GetRecommendedFix(pError);
if (tmpFix == null)
{
pError.ResultStatus = AcStMgr.AcStResultStatus.acStResNoRecommendedFix;
}
else
{
// Fix the naughty circle
pFix = tmpFix;
tmpFix = null;
pFix.PropertyValueGet(_propName, ref fixVal);
try
{
badEnt.color = (AXDBLib.ACAD_COLOR)fixVal;
pError.ResultStatus = AcStMgr.AcStResultStatus.acStResFixed;
}
catch
{
pError.ResultStatus = AcStMgr.AcStResultStatus.acStResFixFailed;
}
}
}
else
{
// Fix the naughty circle
pFix.PropertyValueGet(_propName, ref fixVal);
try
{
badEnt.color = (AXDBLib.ACAD_COLOR)fixVal;
pError.ResultStatus = AcStMgr.AcStResultStatus.acStResFixed;
}
catch
{
pError.ResultStatus = AcStMgr.AcStResultStatus.acStResFixFailed;
}
}
}
}
public void GetAllFixes(AcStMgr.AcStError pError, ref object fixArray, ref int recommendedFixIndex)
{
if (pError != null)
{
AcStMgr.IAcStFix[] arr = new AcStMgr.IAcStFix[_circleCache.Count];
// use our fix candidates if we have any
if (_circleCache.Count > 0)
{
for (int i = 0; i < _circleCache.Count; i++)
{
AXDBLib.ACAD_COLOR errorVal = (AXDBLib.ACAD_COLOR)pError.PropertyValueGet("Color");
if (errorVal.CompareTo(_circleCache[i].Colour) != 0)
{
arr[i] = _circleCache[i].Fix;
}
}
fixArray = arr;
GetRecommendedFix(pError);
recommendedFixIndex = _recommendedFixIndex;
}
if (recommendedFixIndex == -1)
pError.ResultStatus = AcStMgr.AcStResultStatus.acStResNoRecommendedFix;
}
}
public AcStMgr.AcStError GetError()
{
return _error;
}
public object GetObjectFilter()
{
string[] filter = { "AcDbCircle" };
return filter;
}
public void GetPropertyDiffs(AcStMgr.AcStError pError, AcStMgr.AcStFix pFix,
ref object pPropNames, ref object pErrorValues, ref object pFixValues, ref object pFixableStatuses)
{
if (pError != null)
{
List<string> propNames = new List<string>();
string propName = string.Empty;
List<string> errorValues = new List<string>();
object errorVal = null;
List<string> fixValues = new List<string>();
object fixVal = null;
List<bool> fixableStatuses = new List<bool>();
for (int i = 0; i < pError.PropertyCount; i++)
{
pError.PropertyGetAt(i, ref propName, ref errorVal);
_propName = propName;
// Retrieve corresponding Fix property value
try
{
pFix.PropertyValueGet(propName, ref fixVal);
if (((AXDBLib.ACAD_COLOR)errorVal).CompareTo((AXDBLib.ACAD_COLOR)fixVal) != 0)
{
propNames.Add(propName);
errorValues.Add(errorVal.ToString());
fixValues.Add(fixVal.ToString());
fixableStatuses.Add(true);
}
}
catch
{
// explicit catch-all here.
}
}
pPropNames = propNames.ToArray();
pErrorValues = errorValues.ToArray();
pFixValues = fixValues.ToArray();
pFixableStatuses = fixableStatuses.ToArray();
_fixCount++;
}
}
public AcStMgr.AcStFix GetRecommendedFix(AcStMgr.AcStError pError)
{
AcStMgr.AcStFix recommendedFix = new AcStMgr.AcStFix();
_recommendedFixIndex = 0;
if (_circleCache.Count == 0)
{
pError.ResultStatus = AcStMgr.AcStResultStatus.acStResNoRecommendedFix;
}
else
{
AXDBLib.AcadCircle circ = (AXDBLib.AcadCircle)_checkDb.ObjectIdToObject(pError.BadObjectId);
double diff = System.Math.Abs(circ.Radius - _circleCache[0].Radius);
for (int i = 0; i < _circleCache.Count; i++)
{
if (diff > Math.Abs(circ.Radius - _circleCache[i].Radius))
{
diff = Math.Abs(circ.Radius - _circleCache[i].Radius);
_recommendedFixIndex = i;
}
}
recommendedFix.Description = "Colour fix";
recommendedFix.StandardFileName = _circleCache[_recommendedFixIndex].StandardFileName;
recommendedFix.FixObjectName = "Color";
if (recommendedFix.PropertyCount == 0)
{
recommendedFix.PropertyValuePut("Color", _circleCache[_recommendedFixIndex].Colour);
}
}
return recommendedFix;
}
public string HRef
{
get { return _href; }
}
public int Icon
{
get { return 1; }
}
public void Initialize(AcStMgr.AcStManager pMgr)
{
_manager = pMgr;
_plugin = this;
}
public string Name
{
get { return _name; }
}
public void Next()
{
_error = null;
bool foundError = false;
if ((_idsToCheck.Count > 0) && (_circleCache.Count > 0))
{
if (_currentIndex < _idsToCheck.Count)
{
_currentIndex++;
while (_currentIndex < _idsToCheck.Count)
{
AXDBLib.AcadCircle circ = _checkDb.ObjectIdToObject(_idsToCheck[_currentIndex]) as AXDBLib.AcadCircle;
// iterate over our list of cached circle props and look for a match
foreach (CircleCache cc in _circleCache)
{
if (circ.color.CompareTo(cc.Colour) != 0)
{
foundError = true;
}
else
{
// if it matches any one standard, then we can
// stop checking immediately
foundError = false;
break;
}
}
if (foundError)
{
AcStMgr.AcStError error = new AcStMgr.AcStError();
error.Description = "Color is non-standard";
error.BadObjectId = circ.ObjectID;
error.BadObjectName = circ.color.ToString();
error.Plugin = _plugin;
error.ErrorTypeName = "Color ";
error.ResultStatus = AcStMgr.AcStResultStatus.acStResFlagsNone;
if (error.PropertyCount == 0)
{
error.PropertyValuePut("Color", circ.color);
}
_error = error;
foundError = false;
break;
}
_currentIndex++;
}
}
}
}
public void SetContext(object objIdArray, bool bUseDb)
{
_useDb = bUseDb;
if (!bUseDb && objIdArray != null)
{
int[] ids = objIdArray as int[];
_idsToCheck.AddRange(ids);
}
}
public void SetupForAudit(AXDBLib.AcadDatabase pDb, string szPathName,
object stdNameArray, object stdPathArray, object stdDbArray)
{
if (pDb != null)
{
_checkDb = pDb;
if (_checkDb != null)
{
// cache list of all circles in the drawing to check
foreach (AXDBLib.AcadEntity entToCheck in _checkDb.ModelSpace)
{
AXDBLib.AcadCircle circ = entToCheck as AXDBLib.AcadCircle;
if (circ != null)
{
_idsToCheck.Add(circ.ObjectID);
}
}
}
object[] stdDbs = stdDbArray as object[];
string[] stdNames = stdNameArray as string[];
// cache all objects in DWS files we're interested in
// in this case, circles.
for (int i = 0; i < stdDbs.Length; i++)
{
_dwsDb = (AXDBLib.AcadDatabase)stdDbs[i];
foreach (AXDBLib.AcadCircle stdCircle in _dwsDb.ModelSpace)
{
CircleCache cc = new CircleCache();
cc.Radius = stdCircle.Radius;
cc.Colour = stdCircle.color;
cc.StandardFileName = stdNames[i];
AcStMgr.AcStFix fix = new AcStMgr.AcStFix();
fix.Description = "Colour fix";
fix.StandardFileName = cc.StandardFileName;
fix.FixObjectName = "Color: " + stdCircle.color.ToString();
if (fix.PropertyCount == 0)
{
fix.PropertyValuePut("Color", stdCircle.color);
}
cc.Fix = fix;
_circleCache.Add(cc);
fix = null;
cc = null;
}
Marshal.ReleaseComObject(_dwsDb);
_dwsDb = null;
}
}
}
public void StampDatabase(AXDBLib.AcadDatabase pDb, ref bool pStampIt)
{
pStampIt = false;
if (pDb != null)
{
foreach (AXDBLib.AcadEntity dbEnt in pDb.ModelSpace)
{
AXDBLib.AcadCircle circ = dbEnt as AXDBLib.AcadCircle;
if (circ != null)
{
pStampIt = true;
return;
}
}
}
}
public void Start(AcStMgr.AcStError pStartError)
{
if (pStartError != null)
{
int badId = pStartError.BadObjectId;
if (_idsToCheck.Contains(badId))
{
_currentIndex = _idsToCheck.IndexOf(badId);
Next();
}
}
else
{
_currentIndex = -1;
Next();
}
}
public void UpdateStatus(AcStMgr.AcStError pError)
{
// Not implemented yet
}
public string Version
{
get { return _version; }
}
public void WritePluginInfo(object pPluginInfoSectionNode)
{
MSXML2.IXMLDOMNode pSectionNode;
MSXML2.IXMLDOMElement pPluginInfoElement;
MSXML2.IXMLDOMElement xmlElem;
pSectionNode = pPluginInfoSectionNode as MSXML2.IXMLDOMNode;
xmlElem = pSectionNode.ownerDocument.createElement("AcStPluginInfo");
pPluginInfoElement = (MSXML2.IXMLDOMElement)pSectionNode.appendChild(xmlElem);
pPluginInfoElement.setAttribute("PluginName", Name);
pPluginInfoElement.setAttribute("Version", Version);
pPluginInfoElement.setAttribute("Description", Description);
pPluginInfoElement.setAttribute("Author", Author);
pPluginInfoElement.setAttribute("HRef", HRef);
pPluginInfoElement.setAttribute("DWSName", "");
pPluginInfoElement.setAttribute("Status", "1");
}
#endregion
}
[ComVisible(false)]
public class CircleCache
{
public double Radius { get; set; }
public AXDBLib.ACAD_COLOR Colour { get; set; }
public string StandardFileName { get; set; }
public AcStMgr.AcStFix Fix { get; set; }
}
}
I'v done a few things slightly differently to Kean, however the basic gist is still the same.
I will tidy this up a bit once I get my head further into this.
Cheers,
Glenn.