Author Topic: Creating ribbons for AutoCAD  (Read 9140 times)

0 Members and 1 Guest are viewing this topic.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Creating ribbons for AutoCAD
« on: June 20, 2017, 04:44:31 PM »
I've never created ribbons dynamically before. I've always shipped a cui and imported it. I want to move away from that and dynamically create a ribbon when the assembly is loaded.

I've looked at the few examples of this I could find, but none of them appear to work, even if I try to load it manually.

I'd appreciate any assistance.

No code yet because I've only tested code from other public sources and haven't actually written any yet.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: Creating ribbons for AutoCAD
« Reply #1 on: June 21, 2017, 09:43:24 AM »
Can you post the code that does not work for you?


spiderinnet1.typepad.com has a large amount of samples that all work just fine for me.


You just need to remember to load the ribbon after autocad is idle in 2016 I believe that they added a ribbon component initialized event you can monitor to add your ribbon at that time.  Prior to that you needed to wait for Autocad to be idle and to monitor a few commands to reload your ribbon as those commands wiped it out.  I believe that "quickcui", "cui", "customize", "cuiload", and "wssettings" were the commands.  I still use those for my bricscad ribbon.
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: Creating ribbons for AutoCAD
« Reply #2 on: June 21, 2017, 11:56:28 AM »
Make sure you include checking things like using user-specified workspaces and switching between workspaces.  I've used programmatically generated CUI content before and almost all of them fail miserably with workspaces.  One of them wouldn't even *run* the overall plug-in unless a specifically named and configured workspace was in use;  *reeeeeally* annoying when you can't position the palettes, panels, etc. where you want.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Creating ribbons for AutoCAD
« Reply #3 on: June 21, 2017, 05:42:15 PM »
After posting this, last night I copied a bit of sample code from here and put it in its own project.

From my project, was able to create a sample ribbon. I am not sure what I differently, but it worked. Now I have to come up with a way to make it do what I need it to do. Some of the buttons aren't firing, but I'm sure it has something to do with my implementation.

The hope is to build this as part of my overall project as a ribbon that is loaded only when my project is loaded. I've got some ideas, and they show promise.

You just need to remember to load the ribbon after autocad is idle in 2016 I believe that they added a ribbon component initialized event you can monitor to add your ribbon at that time.  Prior to that you needed to wait for Autocad to be idle and to monitor a few commands to reload your ribbon as those commands wiped it out.  I believe that "quickcui", "cui", "customize", "cuiload", and "wssettings" were the commands.  I still use those for my bricscad ribbon.

I'll have to keep an eye out for that! That would be a huge problem.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie


Keith Brown

  • Swamp Rat
  • Posts: 601
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Creating ribbons for AutoCAD
« Reply #6 on: June 22, 2017, 08:47:28 PM »
Using dark/light themes is a cool idea ... but I have a question as to the hoops they jump through to use an icon file ... why don't they just use a gif with a transparent background? It imports perfectly into VS and is easily converted to a BitmapImage as needed.

I'll check the blog about the ribbon being visible.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

ChrisCarlson

  • Guest
Re: Creating ribbons for AutoCAD
« Reply #7 on: June 23, 2017, 09:53:11 AM »
I cannot add in on the .NET programming but with thumbnails AutoCAD will scale down your image, no need to make custom teensy tiny icons.

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: Creating ribbons for AutoCAD
« Reply #8 on: June 23, 2017, 10:12:15 AM »
Using dark/light themes is a cool idea ... but I have a question as to the hoops they jump through to use an icon file ... why don't they just use a gif with a transparent background? It imports perfectly into VS and is easily converted to a BitmapImage as needed.

I'll check the blog about the ribbon being visible.

I think they take RGBA PNGs now.  But I haven't had coffee yet.   :rip:
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Creating ribbons for AutoCAD
« Reply #9 on: June 23, 2017, 07:54:08 PM »
Using dark/light themes is a cool idea ... but I have a question as to the hoops they jump through to use an icon file ... why don't they just use a gif with a transparent background? It imports perfectly into VS and is easily converted to a BitmapImage as needed.

I'll check the blog about the ribbon being visible.

I think they take RGBA PNGs now.  But I haven't had coffee yet.   :rip:

I'm using VS2012 and building assemblies for 2014-2018. So far I've had no issues.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Creating ribbons for AutoCAD
« Reply #10 on: June 24, 2017, 03:19:36 PM »
I've now ran across an issue that I can't seem to work around.

I have a RibbonCombo that is placed on the ribbon.  I want to populate it similar to the Layer combo in the application ribbon, but I cannot get any of the events to fire. The only events that are raised are the ones for the RibbonCombo itself. I want to raise events when the child items are clicked.

I've read somewhere that the CommandHandler stops working when a button is added to the RibbonCombo. If that is true, how can this be resolved?
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2121
  • class keyThumper<T>:ILazy<T>
Re: Creating ribbons for AutoCAD
« Reply #11 on: June 24, 2017, 06:00:17 PM »

Keith,
How are you populating each list item ?
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Creating ribbons for AutoCAD
« Reply #12 on: June 24, 2017, 06:25:50 PM »
This is part of the code without a lot of the fluff where the buttons are being built

Code - C#: [Select]
  1. ......
  2.  
  3. RibbonButton btn1 = new RibbonButton();
  4. btn1.Text = "Button1";
  5. btn1.Id = "TOGGLE1";
  6. btn1.ShowImage = true;
  7. btn1.Image = Images.getBitmap(Properties.Resources.ToggleOnSm);
  8. btn1.CommandHandler = new RibbonCommandHandler();
  9.  
  10. RibbonButton btn2 = new RibbonButton();
  11. btn2.Text = "Button2";
  12. btn2.Id = "TOGGLE2";
  13. btn2.ShowImage = true;
  14. btn2.Image = Images.getBitmap(Properties.Resources.ToggleOnSm);
  15. btn2.CommandHandler = new RibbonCommandHandler();
  16.  
  17. RibbonCombo cmbo = new RibbonCombo();
  18. cmbo.Add(btn1);
  19. cmbo.Add(btn2);
  20.  
  21. ......
  22.  

This is the RibboncommandHandler class

Code - C#: [Select]
  1. public class RibbonCommandHandler : System.Windows.Input.ICommand
  2.         {
  3.             public bool CanExecute(object parameter)
  4.             {
  5.                 return true;
  6.             }
  7.  
  8.             public event EventHandler CanExecuteChanged;
  9.  
  10.             public void Execute(object parameter)
  11.             {
  12.                 Document doc = acadApp.DocumentManager.MdiActiveDocument;
  13.                 if (parameter is RibbonButton)
  14.                 {
  15.                     RibbonButton button = parameter as RibbonButton;
  16.                     doc.Editor.WriteMessage("\nRibbonButton Executed: " + button.Text + "\n");
  17.                 }
  18.             }
  19.         }



Just to see if there was something I was missing, I first added the RibbonCombo to my class as a global and adding events, but Click is not one of them. It is also not an event for the RibbonButton.

I then tried subclassing them both, adding the requisite click event handlers, MouseButtonDown etc ... it fires as it should when it isn't in a RibbonCombo, but is never fired if it is.

To test it, I added btn1 to the ribbon panel directly and to the combo .. one fires, one does not. It's as if the RibbonCombo is handling all events prior to them being raised in the calling class, or blocking all events.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2121
  • class keyThumper<T>:ILazy<T>
Re: Creating ribbons for AutoCAD
« Reply #13 on: June 26, 2017, 01:03:19 AM »

Keith,
I believe I have a solution that is working.
Just needs a bit more testing. I have to go out till this evening (15:00 here now) so I'll post something hopefully before you have your second coffee for the day over there.

Long story short : add a handler for the combo.CurrentChanged event in a constructor for the containing Custom class

Regards,
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2121
  • class keyThumper<T>:ILazy<T>
Re: Creating ribbons for AutoCAD
« Reply #14 on: June 26, 2017, 07:10:33 AM »
I have a situation that may not suit you Keith.

For the RibbonCombo the CurrentChanged event does NOT consider selecting the currently displayed item (either from the pull-down list or directly) should cause an event to fire.
I sort of agree with this when selecting the displayed item directly, but I think the event should fire if the item is selected from the drop-down.

Anyway ... that situation could be taken to AutoDesk ; perhaps someone there has a resolution for this.

The event fires and is trapped for all other buttons.

Source code is attached (membership required to download)





Code - C#: [Select]
  1. using System;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5. using Autodesk.Windows;
  6.  
  7. using CadApp = Autodesk.AutoCAD.ApplicationServices.Core.Application;
  8.  
  9. [assembly: CommandClass(typeof(RibbonGalleryTest.RibbonComboAndGalleryCommands))]
  10.  
  11. namespace RibbonGalleryTest
  12. {
  13.     public class RibbonComboAndGalleryCommands
  14.     {
  15.         public RibbonComboAndGalleryCommands() => ribbonCombo1.CurrentChanged +=
  16.             new EventHandler<RibbonPropertyChangedEventArgs>(
  17.                 RibbonCombo1_CurrentChanged);
  18.  
  19.         private void RibbonCombo1_CurrentChanged(object sender, RibbonPropertyChangedEventArgs e)
  20.         {
  21.             RibbonButton button = ribbonCombo1.Current as RibbonButton;
  22.             CadApp.ShowAlertDialog(button.Text);
  23.         }
  24.  
  25.         public RibbonCombo ribbonCombo1 = new RibbonCombo();
  26.  
  27.         /// ////////////////////////////////////////////////////
  28.         ///
  29.         [CommandMethod("kb_CreateGallery")]
  30.         public void CreateGallery()
  31.         {
  32.             RibbonControl ribbonControl = ComponentManager.Ribbon;
  33.  
  34.             var ribbonTab = new RibbonTab() {
  35.                 Name = "RibbonComboAndGalleryTest",
  36.                 Title = "RibbonComboAndGallery Test",
  37.                 Id = "ID_RibbonComboAndGalleryTab"
  38.             };
  39.             ribbonControl.Tabs.Add(ribbonTab);
  40.  
  41.             CreatePanel1(ribbonTab);
  42.             CreatePanel2(ribbonTab);
  43.             CreatePanel3(ribbonTab);
  44.  
  45.             ribbonTab.IsActive = true;
  46.         }
  47.  
  48.         /// ////////////////////////////////////////////////////
  49.         ///
  50.         private void CreatePanel3(RibbonTab ribbonTab)
  51.         {
  52.             var panel3Src = new RibbonPanelSource() {
  53.                 Name = "MyPanel3",
  54.                 Title = "My Panel 3",
  55.                 Id = "ID_MyPanel3"
  56.             };
  57.             var panel3 = new RibbonPanel() {
  58.                 Source = panel3Src
  59.             };
  60.             ribbonTab.Panels.Add(panel3);
  61.  
  62.             var buttonSplit31 = new RibbonSplitButton() {
  63.                 Name = "Button31",
  64.                 Text = "SplitterButton31",
  65.                 Id = "ID_Button31",
  66.                 CommandHandler = new RibbonCommandHandler(),
  67.                 ShowText = true,
  68.                 ShowImage = true,
  69.                 IsSplit = true
  70.  
  71.             };
  72.             var button32 = new RibbonButton() {
  73.                 Name = "Button32",
  74.                 Text = "My Button32",
  75.                 Id = "ID_Button32",
  76.                 ShowText = true,
  77.                 ShowImage = true,
  78.                 Width = 250,
  79.                 CommandHandler = new RibbonCommandHandler()
  80.             };
  81.             var button33 = new RibbonButton() {
  82.                 Name = "Button33",
  83.                 Text = "My Button33",
  84.                 Id = "ID_Button33",
  85.                 ShowText = true,
  86.                 ShowImage = true,
  87.                 CommandHandler = new RibbonCommandHandler()
  88.             };
  89.             var button34 = new RibbonButton() {
  90.                 Name = "Button34",
  91.                 Text = "My Button34",
  92.                 Id = "ID_Button34",
  93.                 ShowText = true,
  94.                 //ShowImage = true,
  95.                 CommandHandler = new RibbonCommandHandler()
  96.             };
  97.  
  98.             buttonSplit31.Items.Add(button32);
  99.             buttonSplit31.Items.Add(button33);
  100.             buttonSplit31.Items.Add(button34);
  101.  
  102.             panel3Src.Items.Add(buttonSplit31);
  103.         }
  104.  
  105.         /// ////////////////////////////////////////////////////
  106.         ///
  107.         private void CreatePanel2(RibbonTab ribbonTab)
  108.         {
  109.             var panel2Src = new RibbonPanelSource() {
  110.                 Name = "MyPanel2",
  111.                 Title = "My Panel 2",
  112.                 Id = "ID_MyPanel2"
  113.             };
  114.             var panel2 = new RibbonPanel() {
  115.                 Source = panel2Src
  116.             };
  117.             ribbonTab.Panels.Add(panel2);
  118.             var button21 = new RibbonButton() {
  119.                 Name = "Button21",
  120.                 Text = "My Button21",
  121.                 Id = "ID_Button21",
  122.                 CommandHandler = new RibbonCommandHandler()
  123.             };
  124.  
  125.             var button22 = new RibbonButton() {
  126.                 Name = "Button22",
  127.                 Text = "My Button22",
  128.                 Id = "ID_Button22",
  129.                 CommandHandler = new RibbonCommandHandler()
  130.             };
  131.             var button23 = new RibbonButton() {
  132.                 Name = "Button23",
  133.                 Text = "My Button23",
  134.                 Id = "ID_Button23",
  135.                 ShowText = true,
  136.                 CommandHandler = new RibbonCommandHandler()
  137.             };
  138.  
  139.             var button24 = new RibbonButton() {
  140.                 Name = "Button24",
  141.                 Text = "My Button24",
  142.                 Id = "ID_Button24",
  143.                 ShowText = true,
  144.                 CommandHandler = new RibbonCommandHandler()
  145.             };
  146.             var button25 = new RibbonButton() {
  147.                 Name = "Button25",
  148.                 Text = "My Button25",
  149.                 Id = "ID_Button25",
  150.                 ShowText = true,
  151.                 Size = RibbonItemSize.Large,
  152.                 Orientation = System.Windows.Controls.Orientation.Vertical,
  153.                 CommandHandler = new RibbonCommandHandler()
  154.             };
  155.  
  156.  
  157.             // assign to publically declared Item
  158.             ribbonCombo1.Name = "MyCombo1";
  159.             ribbonCombo1.Id = "ID_MyCombo1";
  160.             ribbonCombo1.Text = "Choose";
  161.             ribbonCombo1.IsEnabled = true;
  162.             ribbonCombo1.ShowText = true;
  163.             ribbonCombo1.MinWidth = 250;
  164.  
  165.             ribbonCombo1.Items.Add(button21);
  166.             ribbonCombo1.Items.Add(button22);
  167.             ribbonCombo1.Current = button22;
  168.  
  169.  
  170.             var vertPanel = new RibbonRowPanel();
  171.  
  172.             vertPanel.Items.Add(button23);
  173.             vertPanel.Items.Add(new RibbonRowBreak());
  174.             vertPanel.Items.Add(button24);
  175.             vertPanel.Items.Add(new RibbonRowBreak());
  176.             vertPanel.Items.Add(ribbonCombo1);
  177.  
  178.             panel2Src.Items.Add(vertPanel);
  179.             panel2Src.Items.Add(new RibbonSeparator());
  180.             panel2Src.Items.Add(button25);
  181.  
  182.  
  183.         }
  184.  
  185.         private void CreatePanel1(RibbonTab ribbonTab)
  186.         {
  187.             var panelSrc = new RibbonPanelSource() {
  188.                 Name = "MyPanel1",
  189.                 Title = "My Panel 1",
  190.                 Id = "ID_MyPanel1"
  191.             };
  192.  
  193.             var gallery1 = new RibbonGallery() {
  194.                 Name = "MyGallery1",
  195.                 Id = "ID_MyGallery1"
  196.             };
  197.             var button1 = new RibbonButton() {
  198.                 Name = "Button1",
  199.                 Text = "My Button1",
  200.                 Id = "ID_Button1",
  201.                 ShowText = true,
  202.                 ShowImage = true,
  203.                 CommandHandler = new RibbonCommandHandler()
  204.             };
  205.             var button2 = new RibbonButton() {
  206.                 Name = "Button2",
  207.                 Text = "My Button2",
  208.                 Id = "ID_Button2",
  209.                 ShowText = true,
  210.                 ShowImage = true,
  211.                 CommandHandler = new RibbonCommandHandler()
  212.             };
  213.             var button3 = new RibbonButton() {
  214.                 Name = "Button3",
  215.                 Text = "My Button3",
  216.                 Id = "ID_Button3",
  217.                 CommandHandler = new RibbonCommandHandler()
  218.             };
  219.  
  220.             var button4 = new RibbonButton() {
  221.                 Name = "Button4",
  222.                 Text = "My Button4",
  223.                 Id = "ID_Button4",
  224.                 CommandHandler = new RibbonCommandHandler()
  225.             };
  226.  
  227.             gallery1.Items.Add(button1);
  228.             gallery1.Items.Add(button2);
  229.             gallery1.Items.Add(button3);
  230.             gallery1.Items.Add(button4);
  231.  
  232.             gallery1.DisplayMode = GalleryDisplayMode.ComboBox;
  233.  
  234.             panelSrc.Items.Add(gallery1);
  235.             var panel = new RibbonPanel { Source = panelSrc };
  236.  
  237.             ribbonTab.Panels.Add(panel);
  238.         }
  239.     }
  240.  
  241.     public class RibbonCommandHandler : System.Windows.Input.ICommand
  242.     {
  243.         public bool CanExecute(object parameter)
  244.         {
  245.             return true;
  246.         }
  247.  
  248.         public event EventHandler CanExecuteChanged;
  249.  
  250.         public void Execute(object parameter)
  251.         {
  252.             var ed = CadApp.DocumentManager.MdiActiveDocument.Editor;
  253.  
  254.             if (parameter is RibbonButton) {
  255.                 RibbonButton button = parameter as RibbonButton;
  256.                 ed.WriteMessage($"\nRibbonButton has Executed: {button.Text}\n");
  257.             }
  258.         }
  259.     }
  260. }
  261.  

Code - C#: [Select]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3.  
  4. using CadApp = Autodesk.AutoCAD.ApplicationServices.Core.Application;
  5.  
  6. namespace RibbonGalleryTest
  7. {
  8.     public class Initialization : IExtensionApplication
  9.     {
  10.         public void Initialize()
  11.         {
  12.             CadApp.Idle += OnIdle;
  13.         }
  14.  
  15.         private void OnIdle(object sender, EventArgs e)
  16.         {
  17.             var doc = CadApp.DocumentManager.MdiActiveDocument;
  18.             if (doc != null) {
  19.                 CadApp.Idle -= OnIdle;
  20.                 doc.Editor.WriteMessage("\nRibbonGalleryTest loaded.");
  21.                 doc.Editor.WriteMessage("\nCommand 'kb_CreateGallery' to run.\n");
  22.             }
  23.         }
  24.  
  25.         public void Terminate()
  26.         { }
  27.     }
  28. }
  29.  


Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.