Ribbon Drop Down

Ribbon Drop Down

jsmeker
Participant Participant
3,833 Views
6 Replies
Message 1 of 7

Ribbon Drop Down

jsmeker
Participant
Participant

I'm looking to create a custom drop-down in the ribbon that is populated with values from an external MS Access database.  When an item is selected from the drop-down, I'd like to run some VBA code depending on what was selected.  Been searching for hours, and can't find any help here.

 

Any pointers on how to populate a dropdown with values from a database?  Or info on how to populate a ribbon dropdown with any data? I know I can make a user form, and use drop boxes there, but liked the idea of keeping it in the ribbon if possible.

 

Can anyone offer any tips, or reading materials to help me get started on this?  Thanks in advance!

 

Jeff

 

0 Likes
3,834 Views
6 Replies
Replies (6)
Message 2 of 7

norman.yuan
Mentor
Mentor

There is no way to dynamically create Ribbon items or change existing ribbon items in the ribbon menu system with VBA.

 

It can be done with AutoCAD .NET API, though, rather easily.

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 7

jsmeker
Participant
Participant

Thanks so much for the info.  Spent the last couple hours getting Visual Studio going, and see some examples of using C# with Revit to do a custom Hellow World Ribbon, but just doesn't match with AutoCad.  Any pointers to a beginner tutorial for AutoCad like the Revit one below:

 

https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2017/ENU/Revit-API/files/GUID-...

 

Thanks!

0 Likes
Message 4 of 7

norman.yuan
Mentor
Mentor

OK, if you go with AutoCAD .NET API, you can search the internet for "AutoCAD Ribbon API". You'd find there are basically 2 approaches to do that:

 

1. Uses AcCui.dll (in conjunction with AcWindows.dll). basically, the code will manipulate loaded CUI to change the ribbons. The change made by yor code can be saved in the CUI (that means the code only needs to run once at some point, if the change is saved). Most links you'd found are on this approach.

 

2. Use AdWindows.dll to dynamically create new ribbon items, or update existing ribbon items, regardless whatever the CUI loaded. This approch would be best for custom ribbon items to be tightly associated to custom application's action. That is, you can make the ribbon only be loaed with your custom application, regardless AutoCAD's setup (profile, CUI....).

 

In your case, I suspect you might want to go with 2, because your app need to first laod data from database, and then based on the loaded data, you would decide what ribbon items are needed.

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 7

norman.yuan
Mentor
Mentor

Here is an article that can get you started:

 

http://forums.augi.com/showthread.php?159453-CP204-2-API-for-CUIx-Files-and-the-Runtime-Ribbon-in-Au...

 

You need to have an AUGI account (free join in) to download it.

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 6 of 7

jsmeker
Participant
Participant

Thanks for this.  So I spent the last couple days getting this going.  Got a custom ribbon created using .NET, got it to load automatically using the registry and got command buttons to work properly.  But the whole reason for going away from VBA and to the API was to use a Combobox populated from an external database to run various text/dimension edit commands (plus other things I had ideas for).

 

I got a ComboBox created, can manually populate it with buttons (I think that's how it supposed to work) but for the life of me cannot figure out how to run a command based on a button selection from a ComboBox.  The problem is I cannot find any good documentation, or examples of this.  the closest I've found it this:

 

https://forums.autodesk.com/t5/net/create-custom-ribbon-tab-and-buttons-for-autocad-mechanical-2011/...

 

Have my code setup exactly like this, but nothing happens.  Just not sure if it's even correct.

 

Thinking about this further, I realize I could really hard code my commands into a split button, and forget about the ComboBox linked to the database.  But then, why not just use VBA and some custom buttons using CUI? 

 

Plus for the life of me, I cannot figure out how to add a built-in AutoCad icon into my program.  I was hoping I could just:

 

button.LargeImage = Images.getBitmap("RCDATA_32_PRINT");

So, all in all, kind of discouraged.  If anyone could point me to some good resources to ComboBox usage, I may continue on, otherwise heading back to VBA with my head down. ;(

 

And FYI - my latest code with the ComboBox setup like the example above that does not do anything:

 

//non working combobox stuff before switched in split buttons

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Media.Imaging;
using System.Reflection;
using Autodesk.AutoCAD.ApplicationServices;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Ribbon;
using Autodesk.Windows;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.LayerManager;
using Autodesk.AutoCAD.Internal;

[assembly: ExtensionApplication(typeof(MyExtension.MyApplication))]

namespace MyExtension
{
    // IExtensionApplication showing example
    // usage of the RibbonHelper class:

    public class MyApplication : IExtensionApplication
    {
        public void Initialize()
        {
            try
            {
                /// When the ribbon is available, do
                /// initialization for it:
                RibbonHelper.OnRibbonFound(this.SetupRibbon);

                /// TODO: Initialize your app
            }
            catch (System.Exception ex)
            {
                Document dwg = acadApp.DocumentManager.MdiActiveDocument;
                if (dwg != null)
                    dwg.Editor.WriteMessage(ex.ToString());
            }
        }

        public void Terminate()
        {
        }

        /// A method that performs one-time setup
        /// of Ribbon components:
        void SetupRibbon(RibbonControl ribbon)
        {
            /// TODO: Place ribbon initialization code here
            PrecisionRibbon.Ribbon r1 = new PrecisionRibbon.Ribbon();
            r1.PCTRibbon();
            /// Example only: Verify our method was called
            acadApp.ShowAlertDialog("SetupRibbon() called");
        }
    }
}

/// RibbonHelper class
namespace Autodesk.AutoCAD.Ribbon
{
    public class RibbonHelper
    {
        Action<RibbonControl> action = null;
        bool idleHandled = false;
        bool created = false;

        RibbonHelper(Action<RibbonControl> action)
        {
            if (action == null)
                throw new ArgumentNullException("initializer");
            this.action = action;
            SetIdle(true);
        }

        /// <summary>
        /// 
        /// Pass a delegate that takes the RibbonControl
        /// as its only argument, and it will be invoked
        /// when the RibbonControl is available. 
        /// 
        /// If the RibbonControl exists when the constructor
        /// is called, the delegate will be invoked on the
        /// next idle event. Otherwise, the delegate will be
        /// invoked on the next idle event following the 
        /// creation of the RibbonControl.
        /// 
        /// </summary>

        public static void OnRibbonFound(Action<RibbonControl> action)
        {
            new RibbonHelper(action);
        }

        void SetIdle(bool value)
        {
            if (value ^ idleHandled)
            {
                if (value)
                    acadApp.Idle += idle;
                else
                    acadApp.Idle -= idle;
                idleHandled = value;
            }
        }

        void idle(object sender, EventArgs e)
        {
            SetIdle(false);
            if (action != null)
            {
                var ps = RibbonServices.RibbonPaletteSet;
                if (ps != null)
                {
                    var ribbon = ps.RibbonControl;
                    if (ribbon != null)
                    {
                        action(ribbon);
                        action = null;
                    }
                }
                else if (!created)
                {
                    created = true;
                    RibbonServices.RibbonPaletteSetCreated +=
                       ribbonPaletteSetCreated;
                }
            }
        }

        void ribbonPaletteSetCreated(object sender, EventArgs e)
        {
            RibbonServices.RibbonPaletteSetCreated
               -= ribbonPaletteSetCreated;
            SetIdle(true);
        }
    }
}

namespace PrecisionRibbon
{
    public class Ribbon
    {
        ////////////////////////
        // define public combobox frame
        public RibbonCombo cmbDimAdders = new RibbonCombo();

        public Ribbon()
        {
            cmbDimAdders.CurrentChanged += new EventHandler<RibbonPropertyChangedEventArgs>(cmbDimAdders_CurrentChanged);
        }

        private void cmbDimAdders_CurrentChanged(object sender, RibbonPropertyChangedEventArgs e)
        {
            RibbonButton but = cmbDimAdders.Current as RibbonButton;
            acadApp.ShowAlertDialog(but.Text);
        }

        //individual combobox function 'buttons'
        [CommandMethod("MyRibbonTestCombo")]
        public void RibbonComboButtontest()
        {
            RibbonButton btnDimAdders = new RibbonButton();
            btnDimAdders.Text = "test";
            btnDimAdders.ShowText = true;
            btnDimAdders.CommandHandler = new MyCmdHandler();
            btnDimAdders.CommandParameter = "_plot ";

            //add 'buttons' to combobox
            cmbDimAdders.Items.Add(btnDimAdders);
            cmbDimAdders.Current = btnDimAdders;
        }


        [CommandMethod("PCTRibbon")]
        public void PCTRibbon()
        {
            //////////////////////////////////////////////////
            // create the buttons listed in the split button
            Autodesk.Windows.RibbonButton btnPartData = new RibbonButton();
            btnPartData.Text = "View Part Data";
            btnPartData.ShowText = true;
            btnPartData.CommandHandler = new MyCmdHandler();
            btnPartData.CommandParameter = "-vbarun pct_acad.dvb!Module1.subOpenPartDataSheet ";


            Autodesk.Windows.RibbonButton btnTitleRefresh = new RibbonButton();
            btnTitleRefresh.Text = "Title Refresh";
            btnTitleRefresh.ShowText = true;
            btnTitleRefresh.CommandHandler = new MyCmdHandler();
            btnTitleRefresh.CommandParameter = "-vbarun pct_acad.dvb!Module1.subUpdateEngTitleBlock ";

            Autodesk.Windows.RibbonButton btnStdUpdate = new RibbonButton();
            btnStdUpdate.Text = "Standards Update";
            btnStdUpdate.ShowText = true;
            btnStdUpdate.CommandHandler = new MyCmdHandler();
            btnStdUpdate.CommandParameter = "-vbarun pct_acad.dvb!Module1.subStyleUpdate ";
           

            ////////////////////////
            // create split button
            RibbonSplitButton btnSplitData = new RibbonSplitButton();
            // Required to avoid upsetting AutoCAD when using cmd locator
            btnSplitData.Text = "Data";
            btnSplitData.ShowText = true;
            btnSplitData.ShowImage = true;
            //btnSplitData.LargeImage = Images.getBitmap(Properties.Resources.large);
            //btnSplitData.Image = Images.getBitmap(Properties.Resources.Small);

            btnSplitData.Items.Add(btnPartData);
            btnSplitData.Items.Add(btnTitleRefresh);
            btnSplitData.Items.Add(btnStdUpdate);

            //////////////////////////////////////////////////
            // create the buttons listed in the split button
            Autodesk.Windows.RibbonButton btnPrintCurr = new RibbonButton();
            btnPrintCurr.Text = "Current Layout";
            btnPrintCurr.ShowText = true;
            btnPrintCurr.CommandHandler = new MyCmdHandler();
            btnPrintCurr.CommandParameter = "-vbarun pct_acad.dvb!Module1.subPrintCurrentToDefault ";
            

            Autodesk.Windows.RibbonButton btnPrintAll = new RibbonButton();
            btnPrintAll.Text = "All Layouts";
            btnPrintAll.ShowText = true;
            btnPrintAll.CommandHandler = new MyCmdHandler();
            btnPrintAll.CommandParameter = "-vbarun pct_acad.dvb!Module1.subPrintToDefault ";

            Autodesk.Windows.RibbonButton btnPrintCustom = new RibbonButton();
            btnPrintCustom.Text = "Custom Plot";
            btnPrintCustom.ShowText = true;
            btnPrintCustom.CommandHandler = new MyCmdHandler();
            btnPrintCustom.CommandParameter = "_plot ";

            Autodesk.Windows.RibbonButton btnPageSetup = new RibbonButton();
            btnPageSetup.Text = "Page Setup";
            btnPageSetup.ShowText = true;
            btnPageSetup.CommandHandler = new MyCmdHandler();
            btnPageSetup.CommandParameter = "_pagesetup ";

            ////////////////////////
            // create split button
            RibbonSplitButton btnSplitPrint = new RibbonSplitButton();
            // Required to avoid upsetting AutoCAD when using cmd locator
            btnSplitPrint.Text = "Print";
            btnSplitPrint.ShowText = true;
            btnSplitPrint.ShowImage = true;
            //btnSplitPrint.LargeImage = Images.getBitmap(Properties.Resources.large);
            //btnSplitPrint.Image = Images.getBitmap(Properties.Resources.Small);

            btnSplitPrint.Items.Add(btnPrintCurr);
            btnSplitPrint.Items.Add(btnPrintAll);
            btnSplitPrint.Items.Add(btnPrintCustom);
            btnSplitPrint.Items.Add(btnPageSetup);

        ////////////////////////
        // configure combobox frame
        cmbDimAdders.Text = "Dim Notes";
        cmbDimAdders.ShowText = true;
        cmbDimAdders.MinWidth = 250;

        // Create a Row to add the RibbonButton
        RibbonRowPanel subPanel1 = new RibbonRowPanel();
            subPanel1.Items.Add(btnSplitPrint);
            RibbonRowPanel subPanel2 = new RibbonRowPanel();
            subPanel2.Items.Add(btnSplitData);

            // Create a Ribbon panel source in which to
            // place ribbon items
            RibbonPanelSource panelSource =
              new RibbonPanelSource();
            panelSource.Title = "PCT Functions";
            panelSource.Items.Add(subPanel1);
            panelSource.Items.Add(new RibbonSeparator());
            panelSource.Items.Add(subPanel2);
            panelSource.Items.Add(new RibbonRowBreak());
            panelSource.Items.Add(cmbDimAdders);
            // Create a panel for holding the panel
            // source content
            RibbonPanel panel = new RibbonPanel();
            panel.Source = panelSource;

            // Create a tab to manage the above panel
            RibbonTab tab = new RibbonTab();
            tab.Title = "Custom Tab";
            tab.Id = "CustomTab";
            tab.IsContextualTab = false;
            tab.Panels.Add(panel);
            // Now add the tab to AutoCAD Ribbon bar...
            RibbonControl ribbonControl =
              Autodesk.AutoCAD.Ribbon.RibbonServices.
                RibbonPaletteSet.RibbonControl;
            ribbonControl.Tabs.Add(tab);
            // ... and activate the tab
            ribbonControl.ActiveTab = tab;

        }

        public class MyCmdHandler : System.Windows.Input.ICommand
        {
            public bool CanExecute(object parameter)
            {
                return true;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                Document dwg = acadApp.DocumentManager.MdiActiveDocument;

                if (parameter is RibbonButton)
                {
                    RibbonButton button = parameter as RibbonButton;
                    RibbonCommandItem cmd = parameter as RibbonCommandItem;
                    dwg.SendStringToExecute((string)cmd.CommandParameter, true, false, true);
                    dwg.Editor.WriteMessage("\nRibbonButton Executed: " + button.Text + "\n");
                }
            }
        }
    }
}





 

0 Likes
Message 7 of 7

norman.yuan
Mentor
Mentor

To me, it looks like you chose wrong type of RibbonItem to work with: what you need would be RibbonSplitButton, not RibbonCombo.

 

SplitButton groups a few buttons in a dropdown, and when a button is selected in the dropdown, the associated execution is triggered, and that button stays when dorpdown list is gone (so user can directly clicks it without get it from the drodownlist).

 

Combox groups a list of data and presents what is currently selected. The presented data can be edited if needed. 

 

While technically, you can add RibbonCommandItem into the item list of RibbonCombo as RibbonItem, I suspect once RibbonCommandItem is added into RibbonCombo, it would stop respond to the mouse click. If you look into AutoCAD's Ribbon menu, you can see how RibbonSplitButton and RibbonCombo is used.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes