Announcements
Due to scheduled maintenance, the Autodesk Community will be inaccessible from 10:00PM PDT on Oct 16th for approximately 1 hour. We appreciate your patience during this time.
Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Add button to existing ribbon panel

23 REPLIES 23
Reply
Message 1 of 24
Anonymous
6397 Views, 23 Replies

Add button to existing ribbon panel

I have followed this post by Jeremy Tammik on how to add a button to an existing ribbon panel, but I am facing the same problem: the button is added but it's disabled. Not much use for a button when you can't click on it!

 

http://thebuildingcoder.typepad.com/blog/2013/02/adding-a-button-to-existing-ribbon-panel.html

 

Right now, I am creating my own ribbon, adding panels to it and adding two buttons. But I don't want to create a whole new ribbon for just two buttons. I would like to add my buttons to the "Architecture" ribbon (which is called "build_rac" internally). The way I have implemented my Addin right now it's using the "commandData As Autodesk.Revit.UI.ExternalCommandData" to communicate with Revit. With the example by Jeremy, there's no "commandData As Autodesk.Revit.UI.ExternalCommandData", so even if I do get my button enabled, I can't interact with Revit.

 

I am stunned why accessing the ribbon is this difficult!!!

 

Any help is appreciated!

23 REPLIES 23
Message 2 of 24
Anonymous
in reply to: Anonymous

During OnStartUp you could register an event handler for UIApplication.Idling within a class that has a static bool property that can be set true when your button is clicked and its UIElementActivated event is triggered.

 

When the idling event is called the switch should be checked and if false, return immediately. If set true then whatever API code you wanted to run can be called using the supplied UIApplication object. Don't forget to switch the property back to false before returning though 🙂

 

The idling event is called quite often and I don't think there will be much perceptable latency. I use a similar technique to run API commands from a modeless dialogue.

 

I've not actually tried adding a button to a factory supplied ribbon though, so my above suggestion assumes that you have succeeded in this and can click the button to receive the UIElementActivated event as shown in Jeremy's example code.

Message 3 of 24
Anonymous
in reply to: Anonymous

Hi Scott,

 

Thanks for pointing towards the UIApplication.Idling, it sounds exactly what I need to interact with Revit Smiley Happy

 

But first I have to fix the "disabled button state" issue. The button is added to the correct ribbon panel, but I can't click on it! And if I can't click on the button, I can't test anything on the UIApplication.Idling Smiley Sad

 

I could have sworn that somebody had posted a comment on Jeremy's blog, but all comments from Jeremy's blog have fanished (at least, I cant see any comments at all)!

Message 4 of 24
Anonymous
in reply to: Anonymous

I just took a look at Jeremy's sample code (http://thebuildingcoder.typepad.com/files/addbutton.zip). I compiled it for Revit 2014 and it runs fine for me and is not disabled. I also got it to throw up a message box with a test message from the event handler.

 

The Autodesk.Windows.RibbonButton class has an IsEnabled property, check that you have that set. Otherwise maybe check through the sample code and see what you maye be doing differently.

 

 

Message 5 of 24
Anonymous
in reply to: Anonymous

Here's something funny...(sort of)...

 

If I activate the "Architecture" ribbon, I can see that my button is enabled...but it's being disabled very quickly. I have managed to click on the Architecture tab and quickly click on my button. The message box I designed is being displayed.

 

So something within Revit is checking if the button should be enabled (for example, the "Room" and "Area Boundry" are also being disabled as soon as I select the Architecture tab.

 

I will poke around some more...

Message 6 of 24
Anonymous
in reply to: Anonymous

The "IsEnabled" is set at true...heck, I wrote this code which reacts at the UIApplication.Idling event, but the value is always "true" (but the button is never enabled 😞 )

 

Private Sub OnIdling(sender As Object, e As Autodesk.Revit.UI.Events.IdlingEventArgs)
        Dim oRibbon As adWin.RibbonControl = adWin.ComponentManager.Ribbon
        For Each oTab As adWin.RibbonTab In oRibbon.Tabs
            If oTab.Id = "Architecture" Then
                For Each oPanel As adWin.RibbonPanel In oTab.Panels
                    If oPanel.Source.Id.ToUpper = "BUILD_RAC" Then
                        For i As Integer = 0 To oPanel.Source.Items.Count - 1
                            Dim oRibbonItem As adWin.RibbonItem = oPanel.Source.Items.Item(i)
                            If TypeOf oRibbonItem Is adWin.RibbonButton Then
                                Dim oRibbonButton As adWin.RibbonButton = TryCast(oRibbonItem, adWin.RibbonButton)
                                If oRibbonButton.Name = "cmbJAZO" Then
                                    oRibbonButton.IsEnabled = True
                                    Exit Sub
                                End If
                            End If
                        Next i
                    End If
                Next
            End If
        Next
    End Sub
Message 7 of 24
CoderBoy
in reply to: Anonymous

In Revit 2014 and earlier, custom ribbon buttons can be disabled by Revit based on what kind of view is currently selected.

 

If you switch to a floor plan view, does your button become enabled?

 

 

Message 8 of 24
Anonymous
in reply to: Anonymous

The button is (being) disabled in all views (Floor Plans, Ceiling Plans, 3D Views, Elevations, Sections)

Message 9 of 24
Anonymous
in reply to: Anonymous

There is a RibbonButton property called IsCheckable that will disable the button if set to false, check that out.

 

Also check out the IsEnabledOverride and IsCheckableOverride properties to see what they do.

 

 

 

 

 

 

 

 

Message 10 of 24
arnostlobel
in reply to: Anonymous

I want to add a few points here:
 
First of all, using the idling mechanism is not the way to go in this scenario and I’d like to discourage using it. Please keep in mind that the Idling mechanism was introduced certain and particular patterns mostly around communication between external modeless dialogs and the Revit API. Using Idling outside of this is always tricky and often controversial, plus may be unstable. One think to realize is that Idling means that Revit UI is at rest at the moment. Thus manipulating Revit’s UI (such as adding buttons) goes against that assumption and may lead into unexpected results.
 
Second, I think Teum_Ham should spend some time investigating why it is that certain buttons on the Architecture tab are disabled. I do not mean his newly added button; I mean other, existing buttons. Teum_Ham stated that “...for example, the "Room" and "Area Boundry" are also being disabled as soon as I select the Architecture tab.” That is suspicious and lead me to think that maybe Teum_Ham has Revit at state at which certain buttons simply need to be disabled.  Teum_Ham wondered: “something within Revit is checking if the button should be enabled...” to which I say: Of course! Most menus in Revit are context sensitive and will not have enabled buttons that have no business being enabled at a particular time and context. 
 
This second aspect is what I would start my investigation with. To give more meaningful advice, we need to know what is the state of Revit and the currently active Document in Revit at the time of clicking and switching to the Architectural tab. Is any command already running? Is there even an active document open? (Because if there is not, it would make perfect sense for the Room button to be disabled!)
 
After that is resolved and understood, I’d try to add the button from the regular OnStart call-back, or during ApplicationInitialized event. Those are the two places from which this kind of customization is supposed to be done. 
 
Thanks
 
Arnošt Löbel
Sr. Principal Engineer
Autodesk, Revit R&D 
Arnošt Löbel
Message 11 of 24
Anonymous
in reply to: arnostlobel

I did a little playing and I think I have a nice solution.

 

If you add your command button using standard API methods to its own ribbon panel on either your own tab or the built in add-ins tab, you can then find the panel using the above methods and insert it into any of the system tabs (using Autodesk.Windows.RibbonTab.Panels.Add()) . The button will then behave in the same way as it would on the original tab and the API doesn't seem to notice (well to the extent of my brief testing anyway). You can then remove the panel from the addins tab if desired and the panel will remain happily in its new home.

 

Message 12 of 24
Anonymous
in reply to: arnostlobel

Hi Arnošt,

 

See my reactions below:


@arnostlobel wrote:
I want to add a few points here:
 
First of all, using the idling mechanism is not the way to go in this scenario and I’d like to discourage using it. Please keep in mind that the Idling mechanism was introduced certain and particular patterns mostly around communication between external modeless dialogs and the Revit API. Using Idling outside of this is always tricky and often controversial, plus may be unstable. One think to realize is that Idling means that Revit UI is at rest at the moment. Thus manipulating Revit’s UI (such as adding buttons) goes against that assumption and may lead into unexpected results.

I used the Idling mechanism only to see if I can "enable" my button, but I have removed that code from the Addin (because it didn't change the behaviour)


@arnostlobel wrote:
Second, I think Teum_Ham should spend some time investigating why it is that certain buttons on the Architecture tab are disabled. I do not mean his newly added button; I mean other, existing buttons. Teum_Ham stated that “...for example, the "Room" and "Area Boundry" are also being disabled as soon as I select the Architecture tab.” That is suspicious and lead me to think that maybe Teum_Ham has Revit at state at which certain buttons simply need to be disabled.  Teum_Ham wondered: “something within Revit is checking if the button should be enabled...” to which I say: Of course! Most menus in Revit are context sensitive and will not have enabled buttons that have no business being enabled at a particular time and context. 
 
This second aspect is what I would start my investigation with. To give more meaningful advice, we need to know what is the state of Revit and the currently active Document in Revit at the time of clicking and switching to the Architectural tab. Is any command already running? Is there even an active document open? (Because if there is not, it would make perfect sense for the Room button to be disabled!)

I understand that certain buttons are unavailable because Revit is "context sensitive". Like the "Room" button is unavailable when there's no room defined in the project.

But to answer your questions:

- No, there is no other command running

- Yes, I have an active document (a project with just two walls)


@arnostlobel wrote:
After that is resolved and understood, I’d try to add the button from the regular OnStart call-back, or during ApplicationInitialized event. Those are the two places from which this kind of customization is supposed to be done. 

I am using the "PublicFunction OnStartup(application As Autodesk.Revit.UI.UIControlledApplication) As Autodesk.Revit.UI.ResultImplements Autodesk.Revit.UI.IExternalApplication.OnStartup" to create the button on the Architecture ribbon panel.

I also use this function to create my own ribbon with two buttons. These buttons work as expected. But like I said in my previous post, I don't want to create a complete new ribbon for just two buttons.

 

Do you need any more info?

 

Thanks!

Message 13 of 24
Anonymous
in reply to: Anonymous


@Anonymous wrote:

I did a little playing and I think I have a nice solution.

 

If you add your command button using standard API methods to its own ribbon panel on either your own tab or the built in add-ins tab, you can then find the panel using the above methods and insert it into any of the system tabs (using Autodesk.Windows.RibbonTab.Panels.Add()) . The button will then behave in the same way as it would on the original tab and the API doesn't seem to notice (well to the extent of my brief testing anyway). You can then remove the panel from the addins tab if desired and the panel will remain happily in its new home.

 


Hi Scott,

 

That sounds like a nice solution, but the "regular" revit panels I am creating are "Autodesk.Revit.UI.RibbonPanel" and the only way I can see to access the ribbon is, like you are suggesting, with the "Autodesk.Windows.RibbonTab".

 

So VisualStudio is throwing an error to me: Value of type 'Autodek.Revit.UI.RibbonPanel' cannot be converted to 'Autodesk.Windows.RibbonPanel'.

 

        Dim oRibbon As adWin.RibbonControl = adWin.ComponentManager.Ribbon
        For Each oTab As adWin.RibbonTab In oRibbon.Tabs
            If oTab.Id = "Architecture" Then
                oTab.Panels.Add(oJAZODoorPanel)
            End If
        Next

Maybe it's time to mention that I am working with the Revit 2013 API?

 

Message 14 of 24
Anonymous
in reply to: Anonymous

You need to find the Autodesk.Windows.RibbonPanel version of panel you created in the same way that you would find any of the other panels. The Id's of the API created panels are quite different from the system panels, you will need to do some parsing to get the one you are after reliably. The format is something like "CustomCtrl_%Tab Name%Panel Name".

 

There may be a trick with the timing though. I did my testing using a command button to execute the tab switching after everything was loaded so I am unsure whether the new panel can be found in the ribbon immediately after creation while still within the OnStartup method. You might have to subscribe to an event that is called later in order to search the ribbon and do the shuffling.

 

 

Message 15 of 24
arnostlobel
in reply to: Anonymous

I would also like to point out that using reflection and standard Windows API in order to inject custom buttons to Revit ribbons is neither supported nor recommended a technique by Autodesk (Please keep in mind that Jeremy’s blog, no matter how awesome, does not always reflect Autodesk’s point of view). Although I do not want to be the judge of what users can or not cannot do with their software, they should realize that working around the supported API may not only yield unexpected or undesirable results, but in most cases it also represents extra work. For this particular case, if a button is injected to the ribbon without using the Revit API, Revit will not know about it, thus will not know how to handle it properly (custom buttons are normally handled in a very specific way). So, in order to actually use such a button the programmer must rely on Idling events or External events (not available in R2013 yet). That is certainly an inconvenience and possible burden for the end user, and that is beside the fact that access to the API from an Idling event is limited – the programmer should not use any UI functionality (with a few exceptions).

 

Arnošt Löbel

Sr. Principal Engineer

Autodesk, Revit R&D

Arnošt Löbel
Message 16 of 24
Anonymous
in reply to: arnostlobel

Hi Arnošt,

 

If I can find a supported method of adding a button to an existing ribbon in the API, then I will use that method.

But untill now, I have not found a solution.

 

You have clearly made your point that the suggested workarounds are unsupported and possibly dangerous, but you have not provided us with a hint or example code which DOES show how I can add a button to an existing ribbon (the Architecture --> Build panel to be more precise).

 

If you could get an Autodesk Revit Developer to join this discussion, that would be highly appreciated!

 

Thanks

Message 17 of 24
jeremy_tammik
in reply to: arnostlobel

Hi Teum et al,

 

Did anyone mention the availability class name property yet in this discussion?

 

You can use a command availability class to enable and disable a command whenever you want:

 

http://thebuildingcoder.typepad.com/blog/2011/02/enable-ribbon-items-in-zero-document-state.html

 

Cheers,

 

Jeremy

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 18 of 24
Anonymous
in reply to: jeremy_tammik

Looking at this piece of code...

 

oMyRibbonPanel = application.CreateRibbonPanel(Autodesk.Revit.UI.Tab.Analyze, "My Ribbon Panel Name")

 

The "Autodesk.Revit.UI.Tab" has only two "members": (1) AddIns and (2) Analyze. Where's the rest?

 

If ALL ribbons would be available, that would solve my problem instantly...

Message 19 of 24
arnostlobel
in reply to: Anonymous

Teaum_Ham,
 
I am a developer on the Revit team. I thought it was apparent.
 
You are correct – I did not provide your with a supported solution because there is not one available currently. You may find it strange and inconvenient with respect to your particular application, but it had been decided in the past that allowing external applications to add custom buttons to standard Revit ribbons is not in the best interest of our end users. Please understand that we did not make that decision out of whim – we have a team of experienced UX designers who regularly survey end users to get their take on Revit features. Based on the research it was determined that the pros of completely customizing ribbons do not balance the cons of such an approach. Naturally, that may change in the future. You may rest assured that the moment the majority of our users speaks up requesting Revit with fully customizable ribbons we will make our best to make it available via the API as soon as possible.
 
Respectfully
 
Arnošt Löbel
Sr. Principal Engineer
Revit Core, Revit API
Arnošt Löbel
Message 20 of 24
Anonymous
in reply to: arnostlobel

Wow...I am a bit stunned...

 

You could have save me a couple of hours of my time if you had told me directly that adding buttons is not supported Smiley LOL

 

But the API and your explaination are contradicting eachother:

 

You say that "it had been decided in the past that allowing external applications to add custom buttons to standard Revit ribbons is not in the best interest of our end users", but yet the API is giving me the option to add a panel to the Analyze Ribbon.

 

A bit strange, isn't it?

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

Post to forums  

Rail Community


Autodesk Design & Make Report