Supporting AutoCAD 2015’s dark theme

After a little fun last Tuesday around a pink theme for AutoCAD โ€“ for which I got at least a few "we should totally do that"s from internal folk in response, so watch this space ๐Ÿ˜‰ โ€“ today we're going to talk more seriously about what's needed to support the dark theme in your applications.

But before that, a big thanks to Lee Ambrosius, who owns โ€“ and does a fantastic job with โ€“ AutoCAD's developer documentation. Lee pointed out the online documentation which helped me create this post. If you're interested in the work Lee and team has been doing, please check out his blog post on the developer documentation updates in the 2015 release.

So, how best to support the dark theme? Firstly, after the nonsense I spouted last week it's important to make clear that there's no shortcut to supporting the dark theme: you will need to convert dialogs and user interface elements โ€“ even down to the icon level โ€“ to look good in this environment.

Let's start by looking at CUIx: the simplest way to get this working is to create resource-only DLLs for your icons. If you haven't done this before, the steps in this thread over on The Swamp are likely to be of help (be sure to heed Owen's advice at the end โ€“ that's an important step). One DLL should be named as your CUIx file โ€“ i.e. MyRibbon.cuix would have MyRibbon.dll containing the dark theme icons โ€“ while the other DLL should have the "_light" suffix โ€“ i.e. MyRibbon_light.dll.

As the themes change, the appropriate set of icons should be loaded and used for your various CUI-hosted elements without any custom code being needed (check the top-left of the below image to see our ribbon item get a different icon depending on the value of COLORTHEME).

Themes

For your custom dialogs it's going to be a little more tricky: for a modal dialog you should check the COLORTHEME system variable on launch and choose an appropriate theme for it. Unless you're modifying the sysvar from your code, directly or indirectly, it should be safe enough to assume that it won't change while your dialog is displayed.

For modeless dialogs you'll need to work a little harder: a sysvar reactor attached to the COLORTHEME system variable will notify your application when the value changes, at which point you can take appropriate action.

Here's an example of how you might have a flag in your code that gets set when you application launches (in our case when we run the WTC command) and that gets modified when you the sysvar changes. You'd ideally have this variable notify your UI for an update โ€“ perhaps via a dependency variable in WPF, or otherwise sending some kind of refresh notification โ€“ but in our case we're simply checking the flag via the GT command.

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.Runtime;

 

namespace ThemeWatching

{

  public class Commands

  {

    // Maintain a flag in our code to save checking the sysvar

 

    private bool _isDark = false;

 

    public void CheckTheme()

    {

      _isDark =

        (short)Application.GetSystemVariable("COLORTHEME") == 0;

    }

 

    [CommandMethod("WTC")]

    public void WatchThemeChanges()

    {

      // Let's check the theme when we install the event handler

 

      CheckTheme();

 

      // And we'll check again whenever COLORTHEME changes

      // (we could toggle, but this way seems safer, and the

      // marginal cost difference shouldn't matter during a

      // sysvar change)

 

      Application.SystemVariableChanged +=

        (s, e) =>

        {

          if (e.Name == "COLORTHEME" && e.Changed)

          {

            CheckTheme();

          }

        };

    }

 

    [CommandMethod("GT")]

    public void GetTheme()

    {

      var doc = Application.DocumentManager.MdiActiveDocument;

      if (doc == null) return;

 

      doc.Editor.WriteMessage(

        "\nCurrent theme this is {0}.", _isDark ? "dark" : "light"

      );

    }

  }

}

If you're using a UI framework that supports theming โ€“ WPF is a great example โ€“ then adjusting the look of your custom dialogs will be straightforward. It'll be more work if you don't currently use such a framework, but now might be a good time to consider doing so (a number exist for WinForms development, too, so WPF is not the only option if you don't want to throw away your existing WinForms UI investment). If you have experience to share around your use of UI frameworks that support theming, please do post a comment.

You can, of course, choose to have certain dialogs not adjust according to the theme โ€“ there are a number in AutoCAD, the CUI dialog being a prime example โ€“ and to then ask your users what's important to them in terms of UI aesthetics.

One response to “Supporting AutoCAD 2015’s dark theme”

  1. Kean,

    Previously it was possible to set an icons background to transparent by using colour 192,192,192. Is this still possible? In many cases this could eliminate the need for 2 icons.

    Brett

  2. Kean,

    Previously it was possible to set an icons background to transparent by using colour 192,192,192. Is this still possible? In many cases this could eliminate the need for 2 icons.

    Brett

    1. Brett,

      Yes, 192,192,192 still works as a transparent colour (I just checked).

      Regards,

      Kean

      1. Hello Kean,

        Thanks for solution.

        What about icons of toolbar please? I did not see they are updated when changed theme. I had to close acad and deleted .mnr files.

        Regards,
        Nam.

        1. Kean Walmsley Avatar

          Hi Nam,

          That's a separate topic that I'll need to look into, at some point. You might try asking on the discussion groups, in the meantime.

          Regards,

          Kean

  3. I cheat by re-using AutoCAD icons for all my ribbon tab commands. So I'm good to go ๐Ÿ™‚

    1. Any tips for how you accomplish this? Been searching for hours for how to pull this off.

      1. The CUI editor dialog lets you pick icons from the supplied set. So there is nothing really to do except choose.

  4. Hi Kean

    I can't find ANY AutoCAD dialogs that adjust to the dark theme, except for tool palettes. Options, Print, Customize, Configure Standards, Layer Translator, etc are all standard colours. Can you give me an example?

    Kind regards
    Michael

    1. Kean Walmsley Avatar

      Hi Michael,

      The theming support seems to be built into palettes - I assume the decision was made to prioritise modeless dialogs over modal ones. I still have it on my list to take a closer look at palette theming, at some point, in case.

      Regards,

      Kean

  5. So... whose brilliant idea was it to make the dark theme DLL the default?

    As far as icons go, the previous versions of AutoCAD are all light: with the light or dark theme selected, the ribbon buttons are still light-coloured, so they need to use the light resource DLL.

    But, the idea of the bundle installation system is that you have one bundle which supports multiple versions of AutoCAD. To really make this work, the default resource DLL, i.e. the one with the same name as the cuix file, should contain the light-coloured icons.

    In AutoCAD 2015, if the dark theme is selected, it should first look for MyRibbon_dark.dll, and if that doesn't exist, look for MyRibbon.dll. Then we could deploy a light-coloured MyRibbon.dll which is used by 2012-2014.

    Can you think of a workaround for this?

    1. Kean Walmsley Avatar

      Actually the bundle format is intended to support different versions of AutoCAD via different files, if needed. Have you looked into the ability to support different .cuix / resource .dlls per AutoCAD version (I admit I haven't personally, as yet)?

      Kean

      1. True, it's possible in the PackageContents.xml to declare ModuleName = "./Contents/Resources/2015/MyRibbon.cuix" with a unique resource DLL in that folder.

        It's a bit more work though. If _dark was the suffix, it wouldn't be necessary.

        Thanks for the solution.

  6. I can't get it to work. I have a dark theme .dll & a light them _light.dll and AutoCAD doesn't seem to care. I've read that transparent .png files were supposed to work too but that doesn't appear to be true either. Is this process case sensative as well? Anybody got any thoughts?

    I use "ResourceEditor.exe" to create & edit my .dll files. Paint.NET for my buttons.

    1. Kean Walmsley Avatar

      I suggest following the steps mention in this post (theswamp.org/ind...), to see if that helps.

      The transparent colour - as mentioned in the comments - is RGB 192,192,192.

      Kean

      1. this "mytoolbar.dll" & "mytoolbar_light.dll" switching automatically with the COLORTHEME variable doesn't work for toolbars. It may work for the ribbon & palettes but not for toolbars. depending on if you are in light or dark mode when the .mnr file is compiled depends on what set of icons you get with your toolbars.

        1. Kean Walmsley Avatar

          You're the second person to comment on that... have you posted to the discussion group (or to ADN), as yet?

          Kean

          1. no sir. Glad to hear I'm not crazy but I've wasted A LOT of time debugging this issue.

  7. thanks ,,,,,,,,,,,,,,,,,

  8. Transparency is essential to a ribbon that looks good.

    Autodesk's documentation on this topic is absolutely hopeless. And ADN have been almost as bad. They said, โ€œI donโ€™t think developers need to do any special handling.โ€ But, we do.

    This is how to get transparent images to work:
    - Your images must be .ICO files (32-bit with transparency)
    - Set up a resource only DLL following the guide over at the Swamp
    - Import your ICO files using the resource editor in Visual Studio
    - Close Visual Studio
    - Manually edit resource.h with a text editor and delete the automatically generated #define entries
    - Manually edit the Resource.rc file with a text editor and change the type "ICON" to "RCDATA", e.g.
    IDI_TRIANGLE16 ICON "C:\\CuiTest\\TriangleBlue16.ico"
    becomes
    IDI_TRIANGLE16 RCDATA "C:\\CuiTest\\TriangleBlue16.ico"
    - I usually rename the ICI_ prefix to RCDATA_ but I don't think this is a requirement

    PNG files do not work with this method. In fact, it causes a fatal exception in AutoCAD.

    Note: AutoCAD can't handle extra dots in the file names either. For example, the following set of files won't behave properly when the theme changes:
    - MyCompany.MyRibbon.cuix
    - MyCompany.MyRibbon.dll
    - MyCompany.MyRibbon_light.dll

    Renaming these files to remove the extra dot magically fixes it:
    - MyCompanyMyRibbon.cuix
    - MyCompanyMyRibbon.dll
    - MyCompanyMyRibbon_light.dll

    It's a bug, which I've reported.

    1. Kean Walmsley Avatar

      I'm sorry you had a bad experience getting this working. Thanks for sharing this information with readers of this blog, it'll be very helpful to people.

      Kean

  9. Philippe Leefsma has made a blog post on the AutoCAD DevBlog showing how to create a resource-only DLL with transparent icons, and also how to generate a CUIx file with C#.

    See it here:

    adndevblog.typepad.com/autocad/

    1. I know it's been 10 years on the web...
      But I just love this "supporting-autocad-2015s-dark-theme" over here.
      I used the above code to manage my toolpalette to work with acad 2025.
      Her is a little code I use to get the theme supported:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;

      namespace My_ToolPalette
      {
      internal class Theme_Colors
      {
      // Light Theme
      public System.Drawing.Color light_backcolor { get { return System.Drawing.SystemColors.Control; } }
      public System.Drawing.Color light_forecolor { get { return System.Drawing.SystemColors.ControlText; } }

      // Dark Theme
      public System.Drawing.Color dark_forecolor { get { return System.Drawing.Color.FromArgb(245, 245, 245); } }
      public System.Drawing.Color dark_backcolor { get { return System.Drawing.Color.FromArgb(59, 68, 83); } }

      }
      }

      And this:

      // Code:
      Theme_Colors _theme = new Theme_Colors();
      public void SetColors_Light()
      {
      this.panel1.BackColor = _theme.light_forecolor;
      this.BackColor = _theme.light_backcolor;
      this.ForeColor = _theme.light_forecolor;
      this.button1.ForeColor = _theme.light_forecolor;
      this.button1.BackColor = _theme.light_backcolor;
      this.groupBox1.BackColor = _theme.light_backcolor;
      this.groupBox1.ForeColor = _theme.light_forecolor;
      this.groupBox2.BackColor = _theme.light_backcolor;
      this.groupBox2.ForeColor = _theme.light_forecolor;
      }

      public void SetColors_Dark()
      {
      this.panel1.BackColor = _theme.dark_backcolor;
      this.BackColor = _theme.dark_backcolor;
      this.ForeColor = _theme.dark_forecolor;
      this.button1.ForeColor = _theme.dark_forecolor;
      this.button1.BackColor = _theme.dark_backcolor;
      this.groupBox1.BackColor = _theme.dark_backcolor;
      this.groupBox1.ForeColor = _theme.dark_forecolor;
      this.groupBox2.BackColor = _theme.dark_backcolor;
      this.groupBox2.ForeColor = _theme.dark_forecolor;
      }

Leave a Reply to Michael Cancel reply

Your email address will not be published. Required fields are marked *