I don't know if this is exactly what you're looking for, but this snippet from @Anonymous shows how to add somethin in the AutoCAD tooltip.
/// PointMonitorClient.cs Copyright(c) 2009 Tony Tanzillo
/// CaddZone AutoCAD Programming Samples - PointMonitorClient.cs
///
/// This sample code shows how to use the Editor's PointMonitor
/// event to display information about the entity currently under
/// the pickbox in AutoCAD's tooltip.
///
/// In this example, we display the length of the Curve object
/// which the pickbox is hovering over, but in practicle use you
/// may display anything at all about any type of object(s).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Acad = Autodesk.AutoCAD.ApplicationServices.Application;
[assembly: ExtensionApplication(typeof(PointMonitorToolTipExample.PointMonitorClient))]
namespace PointMonitorToolTipExample
{
// IExtensionApplication
public class MyApplication : IExtensionApplication
{
public void Initialize()
{
PointMonitorClient.Initialize();
}
public void Terminate()
{
}
}
internal class PointMonitorClient
{
// This is a dummy method that invokes the static constructor
// below. We place code that should never run more than once in
// the static constructor, because .NET guarantees us that a
// static c'tor will never run multiple times.
public static void Initialize()
{
}
// Handle the PointMonitor event of all currently open documents,
// and add event handlers to manage the point monitor events of
// all subsequently opened and closed documents:
// Static constructor
static PointMonitorClient()
{
Acad.DocumentManager.DocumentCreated += documentCreated;
Acad.DocumentManager.DocumentToBeDestroyed += documentToBeDestroyed;
foreach (Document doc in Acad.DocumentManager)
doc.Editor.PointMonitor += pointMonitor;
}
// The DocumentCreated event handler adds the PointMonitor event handler
// to each subsequently-opened document:
static void documentCreated(object sender, DocumentCollectionEventArgs e)
{
if (e.Document != null)
e.Document.Editor.PointMonitor += pointMonitor;
}
// The DocumentToBeDestroyed event handler removes the PointMonitor
// event handler from each document when it is closing:
static void documentToBeDestroyed(object sender, DocumentCollectionEventArgs e)
{
if (e.Document != null)
e.Document.Editor.PointMonitor -= pointMonitor;
}
// The PointMonitor Event Handler
static void pointMonitor(object sender, PointMonitorEventArgs e)
{
// For this purpose we ignore events triggered by keyboard input:
if ((e.Context.History & PointHistoryBits.FromKeyboard) == PointHistoryBits.FromKeyboard)
return;
// Get all entities in the aperture target:
FullSubentityPath[] paths = e.Context.GetPickedEntities();
// If none were found, bail out
if (paths == null || paths.Length == 0)
return;
// There will be one FullSubentityPath in the array for each
// top-level entity in the aperture target, so when there's
// multiple entities in aperture target, we must select the
// correct one.
//
// The first ObjectId in the first FullSubEntityPath (if there's
// more than one) is the entity that should be highlighted by
// rollover highlighting, so we use that same object here. Note
// that this example does not support nested objects even though
// that's possible given the data returned by GetPickedEntities().
ObjectId[] ids = paths[0].GetObjectIds();
if (ids == null || ids.Length == 0)
return;
ObjectId id = ids[0]; // The first ObjectId is the top-level entity
// Use the RXClass returned by the ObjectId's ObjectClass property
// to determine if the object is a Curve. Note that this is a more
// efficient way to query the type of an object, verses opening it
// and examining its managed wrapper type:
if (id.IsValid && id.ObjectClass.IsDerivedFrom(curveClass))
{
// Start a transaction:
using (Transaction tr = id.Database.TransactionManager.StartTransaction())
{
// Open the object and cast it to a Curve:
Curve curve = tr.GetObject(id, OpenMode.ForRead) as Curve;
// Try to get the curve's length:
double length = curve.TryGetLength(-1.0);
// If a valid length was returned, then
// convert it to current distance units
// format and add that to the tooltip text:
if (length > 0.0)
{
e.AppendToolTipText(
string.Format(
"Curve length: {0}",
Converter.DistanceToString(length)));
}
tr.Commit();
}
}
}
static RXClass curveClass = RXObject.GetClass(typeof(Curve));
static RXClass blockRefClass = RXClass.GetClass(typeof(BlockReference));
}
public static class ExtensionMethods
{
// This extension method returns the length of any curve
// which has a valid length (Rays and XLines do not have
// a length, or more precisely, are of infinite length, so
// we must deal with those as well as various other cases).
// When a curve doesn't have a valid length or is of infinite
// length, an exception is thrown by one of the members used
// here, so we just catch the exception and return the default
// parameter.
// Note that some curves (namely arcs and elliptical arcs)
// do not necessarily have a start parameter of 0.0, which
// means their length is the distance from the start param
// to the end param, so we must subtract the distance to the
// point at the start param from the distance to the point
// at the end param to ensure we get the actual length:
public static double TryGetLength(this Curve curve, double defaultValue)
{
try
{
return Math.Abs(curve.GetDistanceAtParameter(curve.EndParam) - curve.GetDistanceAtParameter(curve.StartParam));
}
catch
{
return defaultValue;
}
}
public static int CountInsertsInSpace(this BlockTableRecord btr, ObjectId spaceId)
{
int cnt = 0;
foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false))
{
BlockReference br = (BlockReference)brId.GetObject(OpenMode.ForRead);
if (br.OwnerId == spaceId) cnt++;
}
return cnt;
}
}
}