The Ribbon API allows developers to programmatically customize the AutoCAD Ribbon interface (Tabs, Panels, and Buttons). This functionality is provided by the AdWindows.dll assembly (namespace Autodesk.Windows), which is separate from the standard AutoCAD API DLLs.
Important
AdWindows.dll Required: To use these features, you must add a reference to AdWindows.dll found in the AutoCAD installation directory.
AdWindows.dll is not included in the standard AutoCAD .NET API NuGet packages. It must be referenced directly from the AutoCAD installation directory. Do not copy this DLL to your project - instead, reference it from the AutoCAD installation with Copy Local = False.
-
Right-click on your project in Solution Explorer
-
Select "Add" → "Reference..."
-
Click "Browse..." button at the bottom
-
Navigate to AutoCAD installation directory:
- AutoCAD 2024:
C:\Program Files\Autodesk\AutoCAD 2024\ - AutoCAD 2025:
C:\Program Files\Autodesk\AutoCAD 2025\ - Civil 3D 2024:
C:\Program Files\Autodesk\AutoCAD 2024\
- AutoCAD 2024:
-
Select
AdWindows.dlland click "Add" -
CRITICAL: Set Copy Local to False
- In Solution Explorer, expand "Dependencies" → "Assemblies"
- Find
AdWindowsin the list - Click on it to view Properties window
- Set
Copy LocaltoFalse
- AutoCAD already has
AdWindows.dllloaded in memory - Copying it to your output directory can cause version conflicts
- The DLL is always available when your plugin runs inside AutoCAD
- Reduces your plugin's deployment size
Alternatively, you can manually edit your .csproj file:
<ItemGroup>
<!-- AutoCAD Core References -->
<Reference Include="acdbmgd">
<HintPath>C:\Program Files\Autodesk\AutoCAD 2024\acdbmgd.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="acmgd">
<HintPath>C:\Program Files\Autodesk\AutoCAD 2024\acmgd.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- AdWindows for Ribbon API -->
<Reference Include="AdWindows">
<HintPath>C:\Program Files\Autodesk\AutoCAD 2024\AdWindows.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- WPF References (required for Ribbon) -->
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="WindowsBase" />
<Reference Include="System.Xaml" />
</ItemGroup>Note
<Private>False</Private> is equivalent to Copy Local = False
When using AdWindows.dll, you also need these WPF assemblies (they're part of .NET Framework):
- PresentationCore - Core WPF functionality
- PresentationFramework - WPF UI framework
- WindowsBase - Base WPF classes
- System.Xaml - XAML support
These can be added via "Add Reference" → "Assemblies" → "Framework" in Visual Studio.
- Cause: DLL path is incorrect or AutoCAD version mismatch
- Solution: Verify the path matches your AutoCAD installation
- Cause: Missing
using Autodesk.Windows;directive - Solution: Add
using Autodesk.Windows;at the top of your file
- Cause: Plugin might be loading before Ribbon is initialized
- Solution: Delay Ribbon creation or check
ComponentManager.Ribbon != null
If supporting multiple AutoCAD versions, use conditional compilation:
#if ACAD2024
// AutoCAD 2024-specific code
#elif ACAD2025
// AutoCAD 2025-specific code
#endifAnd define multiple build configurations in your .csproj:
<PropertyGroup Condition="'$(Configuration)' == 'Debug2024'">
<DefineConstants>ACAD2024</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug2025'">
<DefineConstants>ACAD2025</DefineConstants>
</PropertyGroup>Autodesk.Windows
| Class | Description |
|---|---|
ComponentManager |
Static manager to access the RibbonControl. |
RibbonControl |
Represents the entire Ribbon UI. |
RibbonTab |
A specific tab (e.g., "Home", "Plug-ins"). |
RibbonPanel |
A container within a tab. |
RibbonButton |
A clickable button element. |
RibbonPanelSource |
Defined content for a panel. |
using Autodesk.Windows;
using System.Windows.Media.Imaging; // For icons
public void CreateRibbon()
{
RibbonControl ribbon = ComponentManager.Ribbon;
if (ribbon == null) return;
// 1. Create Tab
RibbonTab tab = new RibbonTab();
tab.Title = "My Tools";
tab.Id = "MY_TOOLS_TAB";
// 2. Create Panel Source (Content)
RibbonPanelSource panelSource = new RibbonPanelSource();
panelSource.Title = "General";
// 3. Create Panel (Visual container)
RibbonPanel panel = new RibbonPanel();
panel.Source = panelSource;
// 4. Add items to Panel Source
RibbonButton btn = new RibbonButton();
btn.Text = "Run Cmd";
btn.ShowText = true;
btn.CommandParameter = "MYCOMMAND "; // Note space
btn.CommandHandler = new AdskCommandHandler(); // Optional custom handler
panelSource.Items.Add(btn);
// 5. Assemble
tab.Panels.Add(panel);
ribbon.Tabs.Add(tab);
// 6. Set Active
tab.IsActive = true;
}public void AddToAddinsTab()
{
RibbonControl ribbon = ComponentManager.Ribbon;
RibbonTab addinsTab = null;
// Find "Add-ins" tab
foreach (RibbonTab tab in ribbon.Tabs)
{
if (tab.Id == "ACAD.ADDINS") // Standard ID
{
addinsTab = tab;
break;
}
}
if (addinsTab != null)
{
// Add custom panel to existing tab
// ... (create panel logic) ...
addinsTab.Panels.Add(myPanel);
}
}// Standard practice: Buttons send command strings to AutoCAD
// But you can also intercept clicks directly using ICommand
public class AdskCommandHandler : System.Windows.Input.ICommand
{
public bool CanExecute(object parameter) => true;
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
if (parameter is RibbonButton btn)
{
// Custom C# logic here
System.Windows.MessageBox.Show("Clicked " + btn.Text);
}
}
}// Ribbons use WPF ImageSources
btn.Image = LoadImage("my_icon_16.png");
btn.LargeImage = LoadImage("my_icon_32.png");
btn.Size = RibbonItemSize.Large;
// Helper to load resource
private System.Windows.Media.ImageSource LoadImage(string resourceName)
{
// ... WPF BitmapImage loading logic ...
return new BitmapImage(new Uri("pack://application:,,,/MyAssembly;component/" + resourceName));
}RibbonSplitButton splitBtn = new RibbonSplitButton();
splitBtn.Text = "Options";
splitBtn.ShowText = true;
splitBtn.Items.Add(new RibbonButton { Text = "Option A" });
splitBtn.Items.Add(new RibbonButton { Text = "Option B" });// Check if Ribbon exists (it might be closed by user)
if (ComponentManager.Ribbon == null) return;
// Force rebuild/update layout if dynamic changes don't show
// usually not needed if added to collections correctly.btn.ToolTip = "This is a basic tooltip";
// Enhanced content
RibbonToolTip extendedTip = new RibbonToolTip();
extendedTip.Title = "Detailed Help";
extendedTip.Content = "This command performs complex calculation.";
extendedTip.ExpandedContent = "More details...";
// btn.ToolTip = extendedTip; // Assign objectRibbonRowPanel row = new RibbonRowPanel();
// Adds items horizontally in the panel
row.Items.Add(btn1);
row.Items.Add(btnSeparator);
row.Items.Add(btn2);
panelSource.Items.Add(row);- CUIx vs API: It is generally easier and more robust to define Ribbons using a
.cuix(Custom User Interface) file rather than hard-coding C# generation. The API is best for dynamic modifications at runtime. - References: You must reference
AdWindows.dll,PresentationCore,PresentationFramework, andWindowsBase. - Identifiers: Use unique IDs for tabs and panels to avoid conflicts with other plugins.
- Icons: Use embedded resources for icons to keep deployment simple.