Yes, you can.
First you need to add two event handlers to your code. These should be added to every open document and to each newly opened/created document.
ComponentManager.ToolTipOpened += ComponentManager_ToolTipOpened;
document.Editor.PointMonitor += Editor_PointMonitor;
In the point monitor event handler you should monitor the object being hovered over and determine if it is the object that you wish to display the tooltip for. In the code below I am looking at AutoCAD MEP objects to determine if they need to display a custom tooltip.
private static ObjectId toolTipObjectId = ObjectId.Null;
public static void PointMonitor(object sender, PointMonitorEventArgs e)
{
toolTipObjectId = ObjectId.Null;
if (Application.GetSystemVariable("RollOverTips").ToString() != "1" || !SuperToolTipSettings.EnableSuperToolTips)
return;
if ((e.Context.History & PointHistoryBits.FromKeyboard) == PointHistoryBits.FromKeyboard)
return;
FullSubentityPath[] paths = e.Context.GetPickedEntities();
if (paths == null || paths.Length == 0)
return;
ObjectId[] ids = paths[0].GetObjectIds();
if (ids == null || ids.Length == 0)
return;
var i = 0;
if (!ids[i].IsValid)
return;
GetClass(ids, i)
;
}
private static void GetClass(ObjectId[] ids, int i)
{
if ((ids[i].ObjectClass.Name == "AecbDbDuct") ||
(ids[i].ObjectClass.Name == "AecbDbDuctFitting") ||
(ids[i].ObjectClass.Name == "AecbDbDuctCustomFitting") ||
(ids[i].ObjectClass.Name == "AecbDbDuctFlex") ||
(ids[i].ObjectClass.Name == "AecbDbPipe") ||
(ids[i].ObjectClass.Name == "AecbDbPipeFitting") && SuperToolTipSettings.DisplayPipeFittings) ||
(ids[i].ObjectClass.Name == "AecbDbPipeCustomFitting") ||
(ids[i].ObjectClass.Name == "AecbDbPipeFlex") && SuperToolTipSettings.DisplayFlexPipe) ||
(ids[i].ObjectClass.Name == "AecbDbCableTray" && SuperToolTipSettings.DisplayCableTray) ||
(ids[i].ObjectClass.Name == "AecbDbCableTrayFitting") ||
(ids[i].ObjectClass.Name == "AecbDbConduit") ||
(ids[i].ObjectClass.Name == "AecbDbConduitFitting" && SuperToolTipSettings.DisplayConduitFittings) ||
(ids[i].ObjectClass.Name == "AecbDbSchematicPipe") ||
(ids[i].ObjectClass.Name == "AecbDbSchematicPipeFitting") ||
(ids[i].ObjectClass.Name == "AecbDbSchematic") ||
(ids[i].ObjectClass.Name == "AecbDbSchematicSymbol") ||
(ids[i].ObjectClass.Name == "AecbDbDevice") ||
(ids[i].ObjectClass.Name == "AecbDbPanel") ||
(ids[i].ObjectClass.Name == "AecbDbWire") ||
(ids[i].ObjectClass.Name == "AecbDbMvPart"))
{
toolTipObjectId = ids[i];
}
if (ids[i].ObjectClass.Name == "AcDbBlockReference")
{
GetClass(ids, i + 1);
}
}
The code above is recursive and will delve into block references and xrefs to find the object and store the objectID of the object being hovered over.
Once you have the objectId of a object you wish to display a new tooltip for you will need to display the tooltip. The code in the tooltipopened event handler takes care of this.
public static void ComponentManager_ToolTipOpened(object sender, EventArgs e)
{
if (toolTipObjectId != ObjectId.Null && Application.GetSystemVariable("RollOverTips").ToString() == "1")
{
var toolTip = sender as ToolTip;
// This check is needed to distinguish between the ribbon tooltips and the entity tooltips
if (toolTip != null)
{
Member member = null;
using (Transaction transaction = HostApplicationServices.WorkingDatabase.TransactionManager.StartOpenCloseTransaction())
{
member = transaction.GetObject(toolTipObjectId, 0) as Member;
transaction.Commit();
}
if (member != null)
{
var memberToolTip = new SuperToolTipDisplay
{
MaxWidth = 600,
ClassName = {Text = "Object Type"}
};
// Repeat this section for each property of the object to add to the tooltip
// I added generic text for this sample but you would instead get properties from the object
// and display them here. The blockName would be the name of the property and the blockValue
// would be the value of the property.
{
var blockName = new TextBlock();
var blockValue = new TextBlock();
blockName.Text = "Property Name";
blockName.Margin = new Thickness(0.0, 5.0, 0.0, 0.0);
blockName.HorizontalAlignment = HorizontalAlignment.Left;
blockName.VerticalAlignment = VerticalAlignment.Center;
blockValue.Text = "Property Value";
blockValue.Margin = new Thickness(10.0, 5.0, 10.0, 0.0);
blockValue.TextWrapping = TextWrapping.Wrap;
blockValue.HorizontalAlignment = HorizontalAlignment.Left;
blockValue.VerticalAlignment = VerticalAlignment.Center;
memberToolTip.StackPanelName.Children.Add(blockName);
memberToolTip.StackPanelValue.Children.Add(blockValue);
// Because BlockValue textblock can have wrapped text we need to set the height
// of the BlockName textblock to equal that of the BlockValue textblock.
// We need to give the wpf layout engine time to calculate the actual height
// so that we can set the values.
memberToolTip.StackPanelValue.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new DispatcherOperationCallback(delegate
{
blockName.Height = blockValue.ActualHeight;
return null;
}), null);
}
// Swap out the AutoCAD ToolTip with our own ToolTip
toolTip.Content = memberToolTip;
member.Dispose();
}
}
// Reset the object for the next tooltip
toolTipObjectId = ObjectId.Null;
}
The xaml for the wpf user control to replace the tooltip.
<UserControl x:Class="SuperToolTipDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="RootGrid" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock x:Name="ClassName" TextWrapping="Wrap" Text="TextBlock" Margin ="10,10,10,10" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<DockPanel x:Name="LineContainer" HorizontalAlignment="Left" Margin="10,30,10,10" VerticalAlignment="Top">
<StackPanel x:Name="StackPanelName" Orientation="Vertical" VerticalAlignment="Top" MaxWidth="290"/>
<WrapPanel x:Name="StackPanelValue" Orientation="Vertical" VerticalAlignment="Top" />
</DockPanel>
</Grid>
</UserControl>
That should be enough to get you going. I grabbed the code out of an active project and think that I got everything.
In summary, you check the object being hovered over to get its objectId and check that objectid againt a list of objects you are monitoring. Then once the tooltip for that object is opened check to see if it is a object that we want and then replace the tooltip panel with one of our own creation. I have been unsuccessful in adding an image to the tooltip but I believe it is possible.
See this link. http://stackoverflow.com/questions/10873263/autocad-infobox-functionality