.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to replace AutoCAD rollover tooltips for a custom WPF user control?

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
ruipfbarreiros
2324 Views, 8 Replies

How to replace AutoCAD rollover tooltips for a custom WPF user control?

Hi,

 

How would I go about replacing the stock rollover tooltip for my own WPF user control whenever a certain type of object is hovered over?

 

Is it even possible?

 

Thanks

---------------------------------------

Using Building Design Suite 2019
8 REPLIES 8
Message 2 of 9
SENL1362
in reply to: ruipfbarreiros

http://adndevblog.typepad.com/autocad/2012/05/change-tooltip-of-ribbon-button-using-runtime-ribbon-a...
RibbonToolTip toolTip = myRibbonButton.ToolTip as RibbonToolTip;
if (toolTip == null)
return;
toolTip.Title = "New Title";
toolTip.Content = "New Content";
Message 3 of 9
ruipfbarreiros
in reply to: SENL1362

That works on ribbon tooltips only, right?
I meant the rollover tooltips when I hover a certain object in the drawing, for example an Xref block, a line or anyother object...
---------------------------------------

Using Building Design Suite 2019
Message 4 of 9
SENL1362
in reply to: ruipfbarreiros

sorry about this mis interpretation.

For tooltips on objects i'll (mis) use hyperlinks for that purpose, like in this pseudo code

 

using (HyperLinkCollection hyperlinks = TheEntity.Hyperlinks)
{
using (HyperLink newHyperLink = new HyperLink())
{
newHyperLink.Description = "Some Description";
newHyperLink.Name = "Some Name";
newHyperLink.SubLocation = "Some Description";
hyperlinks.Add(newHyperLink);
}
}

 

 

 

Message 5 of 9

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

Message 6 of 9
Keith.Brown
in reply to: Keith.Brown

I have been using this code for a couple years to display custom tooltips and it works extremely well and extremely fast.   I need to spend some time and come back to this code and "adjust" it to be able to display an image in the tooltip.  Let me know if you have any issues with it and I will create a sample project that will show the complete code.

Message 7 of 9

Thanks Keith.Brown! This is exactly what i've been looking for. This will certainly get me started! I reckon I should have no problem implementing bindings to display the entity's properties (using the MVVM pattern), am I right?
Again, thanks a lot!
---------------------------------------

Using Building Design Suite 2019
Message 8 of 9
norman.yuan
in reply to: Keith.Brown

Keith,

 

Inspired by the discussion here and your code, I post an article here. Do you still have issue of displaying image in tool tip? It seems I do not have problem showing image here. The picture used in my code is PNG with size of over 1MB, which could be considered "fairly big" for tool tip.

Norman Yuan

Drive CAD With Code

EESignature

Message 9 of 9
Keith.Brown
in reply to: norman.yuan

Hi Norman,

 

Nice write up and thanks for the shout out!

 

I was able to finally get an image to display.  At the time it was my lack of understanding of WPF that caused the issue but eventually  I did something very similar to your code where you are converting the image to get it to work.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost