BeepExtendedButton
Advanced, theme-aware button with dual-action areas, split functionality, and integrated menu support for complex interactions
📋 Table of Contents
Overview
BeepExtendedButton provides an advanced button control with dual-action functionality, combining primary and secondary action areas within a single button interface. It features split-button behavior, extended menu integration, and sophisticated interaction patterns for complex user interfaces.
Built on the BeepControl foundation, BeepExtendedButton features dual-action zones, customizable button sections, menu item integration, icon management, hover state differentiation, and comprehensive theming support. Perfect for toolbars, command interfaces, split-button scenarios, and applications requiring rich button functionality.
Key Features
🔄 Dual-Action Areas
Separate clickable zones for primary and secondary actions within one button
📋 Menu Integration
Built-in support for menu items and command binding
🎨 Rich Iconography
Support for multiple icons with customizable positioning and sizing
⚡ Split Functionality
Classic split-button behavior with primary action and dropdown options
🎯 Precise Interaction
Distinct hover and click states for different button regions
🔧 Command Binding
Integration with command patterns and menu item hierarchies
Visual Preview
Extended Button Variations and States
Extended buttons showing dual-action areas, styles, states, and dropdown integration
Basic Usage
Simple Extended Button
// Create and configure a BeepExtendedButton
var extendedButton = new BeepExtendedButton();
extendedButton.Size = new Size(150, 35);
extendedButton.Text = "Save Document";
extendedButton.ButtonImagePath = @"icons\save.png";
extendedButton.ExtendedButtonImagePath = @"icons\arrow-down.png";
extendedButton.RightButtonSize = 25;
// Handle main button click (primary action)
extendedButton.MainButtonClick += (s, e) =>
{
SaveDocument();
ShowNotification("Document saved successfully!");
};
// Handle extended button click (secondary actions)
extendedButton.ExtendedButtonClick += (s, e) =>
{
ShowSaveOptionsMenu(extendedButton);
};
// Add to form
this.Controls.Add(extendedButton);
Menu Item Integration
// Create extended button with menu item binding
var menuButton = new BeepExtendedButton
{
Text = "Export Data",
Size = new Size(120, 32),
RightButtonSize = 20,
MenuItem = new MenuItemData
{
Name = "Export",
Command = "ExportCommand",
SubItems = new[]
{
new MenuItemData { Name = "Export to Excel", Command = "ExportExcel" },
new MenuItemData { Name = "Export to PDF", Command = "ExportPDF" },
new MenuItemData { Name = "Export to CSV", Command = "ExportCSV" }
}
}
};
// Set up icons
menuButton.ButtonImagePath = @"icons\export.png";
menuButton.ExtendedButtonImagePath = @"icons\chevron-down.png";
// Handle main action (default export)
menuButton.MainButtonClick += async (s, e) =>
{
await ExportToDefaultFormat();
};
// Handle extended menu
menuButton.ExtendedButtonClick += (s, e) =>
{
var contextMenu = CreateExportMenu(menuButton.MenuItem);
var location = menuButton.PointToScreen(new Point(0, menuButton.Height));
contextMenu.Show(location);
};
Properties
Core Properties
| Property | Type | Default | Description |
|---|---|---|---|
Text |
string | "" | Main button text label |
RightButtonSize |
int | 20 | Width of the extended button area |
MenuItem |
object | null | Associated menu item data object |
Image Properties
| Property | Type | Default | Description |
|---|---|---|---|
ButtonImagePath |
string | "" | Path to main button icon image |
ExtendedButtonImagePath |
string | "" | Path to extended button icon image |
ButtonImage |
Image | null | Main button icon image object |
ExtendedButtonImage |
Image | null | Extended button icon image object |
Layout Properties
| Property | Type | Default | Description |
|---|---|---|---|
ImageAlignment |
ContentAlignment | MiddleLeft | Alignment of main button image |
TextAlignment |
ContentAlignment | MiddleCenter | Alignment of button text |
ImageTextSpacing |
int | 4 | Spacing between image and text |
Events
| Event | Event Args | Description |
|---|---|---|
MainButtonClick |
EventArgs | Fired when main button area is clicked |
ExtendedButtonClick |
EventArgs | Fired when extended button area is clicked |
MainButtonHover |
EventArgs | Fired when mouse enters main button area |
ExtendedButtonHover |
EventArgs | Fired when mouse enters extended button area |
Examples
Toolbar with Extended Buttons
public partial class ExtendedToolbar : UserControl
{
private FlowLayoutPanel toolbarPanel;
private List<BeepExtendedButton> toolbarButtons;
public ExtendedToolbar()
{
InitializeComponents();
CreateToolbarButtons();
}
private void InitializeComponents()
{
toolbarPanel = new FlowLayoutPanel
{
Dock = DockStyle.Top,
Height = 45,
FlowDirection = FlowDirection.LeftToRight,
WrapContents = false,
Padding = new Padding(5)
};
toolbarButtons = new List<BeepExtendedButton>();
this.Controls.Add(toolbarPanel);
}
private void CreateToolbarButtons()
{
var buttonConfigs = new[]
{
new { Text = "New", Icon = "new.png", Command = "New", SubCommands = new[] { "Document", "Presentation", "Spreadsheet" } },
new { Text = "Open", Icon = "open.png", Command = "Open", SubCommands = new[] { "Recent Files", "From Computer", "From Cloud" } },
new { Text = "Save", Icon = "save.png", Command = "Save", SubCommands = new[] { "Save", "Save As", "Save Copy" } },
new { Text = "Print", Icon = "print.png", Command = "Print", SubCommands = new[] { "Quick Print", "Print Preview", "Print Setup" } }
};
foreach (var config in buttonConfigs)
{
var button = CreateExtendedButton(config.Text, config.Icon, config.Command, config.SubCommands);
toolbarButtons.Add(button);
toolbarPanel.Controls.Add(button);
}
}
private BeepExtendedButton CreateExtendedButton(string text, string iconPath, string command, string[] subCommands)
{
var button = new BeepExtendedButton
{
Text = text,
Size = new Size(90, 35),
Margin = new Padding(2),
ButtonImagePath = $@"icons\{iconPath}",
ExtendedButtonImagePath = @"icons\chevron-down.png",
RightButtonSize = 18,
Tag = command
};
// Main button click - execute primary command
button.MainButtonClick += (s, e) =>
{
ExecuteCommand(command);
};
// Extended button click - show submenu
button.ExtendedButtonClick += (s, e) =>
{
ShowSubCommandMenu(button, subCommands);
};
// Visual feedback on hover
button.MainButtonHover += (s, e) =>
{
ShowCommandTooltip(button, $"Execute {command}");
};
button.ExtendedButtonHover += (s, e) =>
{
ShowCommandTooltip(button, $"More {command} options");
};
return button;
}
private void ShowSubCommandMenu(BeepExtendedButton button, string[] subCommands)
{
var contextMenu = new ContextMenuStrip();
foreach (var subCommand in subCommands)
{
var menuItem = new ToolStripMenuItem(subCommand);
menuItem.Click += (s, e) =>
{
ExecuteCommand($"{button.Tag}_{subCommand.Replace(" ", "")}");
};
contextMenu.Items.Add(menuItem);
}
// Position menu below button
var location = button.PointToScreen(new Point(0, button.Height));
contextMenu.Show(location);
}
private void ExecuteCommand(string command)
{
switch (command)
{
case "New":
CreateNewDocument();
break;
case "New_Document":
CreateNewDocument("Document");
break;
case "New_Presentation":
CreateNewDocument("Presentation");
break;
case "Open":
OpenDocument();
break;
case "Open_RecentFiles":
ShowRecentFiles();
break;
case "Save":
SaveDocument();
break;
case "Save_SaveAs":
SaveDocumentAs();
break;
case "Print":
PrintDocument();
break;
case "Print_PrintPreview":
ShowPrintPreview();
break;
default:
MessageBox.Show($"Command executed: {command}");
break;
}
}
// Command implementations
private void CreateNewDocument(string type = "Document") { /* Implementation */ }
private void OpenDocument() { /* Implementation */ }
private void ShowRecentFiles() { /* Implementation */ }
private void SaveDocument() { /* Implementation */ }
private void SaveDocumentAs() { /* Implementation */ }
private void PrintDocument() { /* Implementation */ }
private void ShowPrintPreview() { /* Implementation */ }
private void ShowCommandTooltip(Control control, string text) { /* Implementation */ }
}
Split Button with Complex Menu
public partial class SplitButtonExample : Form
{
private BeepExtendedButton exportButton;
private BeepExtendedButton runButton;
public SplitButtonExample()
{
InitializeComponents();
SetupSplitButtons();
}
private void InitializeComponents()
{
this.Size = new Size(400, 300);
this.Text = "Split Button Example";
}
private void SetupSplitButtons()
{
// Export split button
exportButton = new BeepExtendedButton
{
Text = "Export Report",
Size = new Size(150, 40),
Location = new Point(20, 20),
ButtonImagePath = @"icons\export.png",
ExtendedButtonImagePath = @"icons\arrow-down.png",
RightButtonSize = 25
};
exportButton.MainButtonClick += async (s, e) =>
{
// Default export action
await ExportToDefaultFormat();
};
exportButton.ExtendedButtonClick += (s, e) =>
{
ShowExportMenu();
};
// Run split button with recent configurations
runButton = new BeepExtendedButton
{
Text = "Run Configuration",
Size = new Size(160, 40),
Location = new Point(20, 80),
ButtonImagePath = @"icons\run.png",
ExtendedButtonImagePath = @"icons\history.png",
RightButtonSize = 30
};
runButton.MainButtonClick += async (s, e) =>
{
// Run with last configuration
await RunWithLastConfiguration();
};
runButton.ExtendedButtonClick += (s, e) =>
{
ShowConfigurationHistory();
};
this.Controls.AddRange(new Control[] { exportButton, runButton });
}
private void ShowExportMenu()
{
var menu = new ContextMenuStrip();
// Export format options
var formatMenu = new ToolStripMenuItem("Export Format");
formatMenu.DropDownItems.Add("Excel (.xlsx)", null, (s, e) => ExportToExcel());
formatMenu.DropDownItems.Add("PDF Document", null, (s, e) => ExportToPDF());
formatMenu.DropDownItems.Add("CSV File", null, (s, e) => ExportToCSV());
formatMenu.DropDownItems.Add("JSON Data", null, (s, e) => ExportToJSON());
// Export options
var optionsMenu = new ToolStripMenuItem("Export Options");
optionsMenu.DropDownItems.Add("Include Headers", null, ToggleIncludeHeaders);
optionsMenu.DropDownItems.Add("Include Formatting", null, ToggleIncludeFormatting);
optionsMenu.DropDownItems.Add("Compress Output", null, ToggleCompression);
// Recent exports
var recentMenu = new ToolStripMenuItem("Recent Exports");
var recentExports = GetRecentExports();
foreach (var export in recentExports)
{
recentMenu.DropDownItems.Add($"{export.Name} ({export.Format})", null,
(s, e) => RepeatExport(export));
}
menu.Items.AddRange(new ToolStripItem[]
{
formatMenu,
optionsMenu,
new ToolStripSeparator(),
recentMenu,
new ToolStripSeparator(),
new ToolStripMenuItem("Export Settings...", null, ShowExportSettings)
});
var location = exportButton.PointToScreen(new Point(0, exportButton.Height));
menu.Show(location);
}
private void ShowConfigurationHistory()
{
var menu = new ContextMenuStrip();
// Recent configurations
var configurations = GetRecentConfigurations();
foreach (var config in configurations)
{
var item = new ToolStripMenuItem($"{config.Name}")
{
Tag = config,
Image = GetConfigurationIcon(config.Type)
};
item.Click += (s, e) => RunConfiguration(config);
menu.Items.Add(item);
}
if (configurations.Any())
{
menu.Items.Add(new ToolStripSeparator());
}
// Additional options
menu.Items.Add("Edit Configurations...", null, ShowConfigurationEditor);
menu.Items.Add("Save Current as...", null, SaveCurrentConfiguration);
menu.Items.Add(new ToolStripSeparator());
menu.Items.Add("Clear History", null, ClearConfigurationHistory);
var location = runButton.PointToScreen(new Point(0, runButton.Height));
menu.Show(location);
}
// Implementation methods
private async Task ExportToDefaultFormat() { /* Implementation */ }
private async Task RunWithLastConfiguration() { /* Implementation */ }
private void ExportToExcel() { /* Implementation */ }
private void ExportToPDF() { /* Implementation */ }
private void ExportToCSV() { /* Implementation */ }
private void ExportToJSON() { /* Implementation */ }
private void ToggleIncludeHeaders(object sender, EventArgs e) { /* Implementation */ }
private void ToggleIncludeFormatting(object sender, EventArgs e) { /* Implementation */ }
private void ToggleCompression(object sender, EventArgs e) { /* Implementation */ }
private void RepeatExport(object exportConfig) { /* Implementation */ }
private void ShowExportSettings(object sender, EventArgs e) { /* Implementation */ }
private void RunConfiguration(object config) { /* Implementation */ }
private void ShowConfigurationEditor(object sender, EventArgs e) { /* Implementation */ }
private void SaveCurrentConfiguration(object sender, EventArgs e) { /* Implementation */ }
private void ClearConfigurationHistory(object sender, EventArgs e) { /* Implementation */ }
private IEnumerable<object> GetRecentExports() => new object[0]; // { /* Implementation */ }
private IEnumerable<object> GetRecentConfigurations() => new object[0]; // { /* Implementation */ }
private Image GetConfigurationIcon(string type) => null; // { /* Implementation */ }
}
Theming
BeepExtendedButton provides comprehensive theming support with advanced styling for dual-action areas:
Theme Application
var extendedButton = new BeepExtendedButton
{
Theme = "Professional",
UseThemeColors = true
};
// Theme automatically applies:
// - MainButtonBackColor: Main button area background
// - ExtendedButtonBackColor: Extended button area background
// - ButtonBorderColor: Border styling for both areas
// - HoverColors: Hover states for each section
// - TextColors: Text and icon colors
// - SeparatorColor: Divider between button areas
Advanced Styling Features
- Dual-zone theming - Independent styling for main and extended areas
- State-aware colors - Different colors for normal, hover, and active states
- Icon integration - Theme-coordinated icon colors and effects
- Separator styling - Customizable divider between button sections
Best Practices
🎯 User Experience
- Clear separation: Make it obvious that there are two distinct clickable areas
- Logical actions: Primary action should be the most common operation
- Consistent sizing: Maintain proportional sizing between main and extended areas
- Visual feedback: Provide clear hover states for each clickable zone
🔧 Implementation
- Event handling: Handle both main and extended button events appropriately
- Menu positioning: Position dropdown menus to avoid screen edge clipping
- Icon consistency: Use consistent icon styles and sizing throughout
- Command patterns: Implement proper command binding for complex operations
♿ Accessibility
- Keyboard navigation: Support Tab navigation between button areas
- Screen readers: Provide descriptive labels for both button sections
- Focus indicators: Clear visual focus indicators for keyboard users
- Alternative access: Provide alternative ways to access extended functionality
Size the extended button area proportionally - typically 20-30% of the total button width for optimal usability.
Use extended buttons for actions with multiple options, keeping the most common action as the primary button.
Avoid making extended button areas too small (less than 20px width) as they become difficult to target accurately.