Overview

BeepPopupListFormStrip provides a sophisticated context menu control that extends BeepListBox functionality to create modern, theme-aware popup menus. It offers flexible positioning, automatic sizing, click-outside-to-close behavior, and seamless integration with the BeepPopupForm system for professional contextual interfaces.

Built on the BeepListBox foundation, BeepPopupListFormStrip features automatic popup management, smart positioning, item selection handling, theme integration, and comprehensive event support. Perfect for right-click menus, dropdown options, action lists, and contextual navigation in modern Windows Forms applications.

Key Features

??? Smart Popup System

Automatic popup positioning with BeepPopupForm integration and outside-click handling

?? Flexible Positioning

Show context menus at any screen location with automatic boundary detection

?? Theme Integration

Complete theme support with modern styling and consistent visual appearance

?? BeepListBox Heritage

Inherits all BeepListBox functionality including icons, custom items, and layouts

? Event-Driven

Comprehensive event handling for item clicks, selection changes, and menu lifecycle

?? Responsive Design

Automatic sizing based on content with configurable appearance options

Visual Preview

Standard Context Menu

Right-click me! ?? Context menu appears here
?? Edit Ctrl+E
?? Copy Ctrl+C
?? Paste Ctrl+V
??? Delete Del
?? Properties Alt+Enter

BeepPopupListFormStrip showing common contextual actions with icons and shortcuts

Data Grid Context Menu

Name
Email
Status
John Smith
john@example.com
Active
Jane Doe
jane@example.com
Inactive
??? View Details
?? Edit Record
?? Send Email
?? Call Contact
?? Generate Report
?? Export Data
??? Delete Record

Data-centric context menu with record-specific operations and visual grouping

Basic Usage

Simple Context Menu

// Create a BeepPopupListFormStrip
var contextMenu = new BeepPopupListFormStrip();

// Add menu items
contextMenu.ListItems.Add(new SimpleItem
{
    Text = "Edit",
    ImagePath = "edit-icon.svg",
    GuidId = Guid.NewGuid().ToString()
});

contextMenu.ListItems.Add(new SimpleItem
{
    Text = "Copy",
    ImagePath = "copy-icon.svg",
    GuidId = Guid.NewGuid().ToString()
});

contextMenu.ListItems.Add(new SimpleItem
{
    Text = "-", // Separator
    IsSeparator = true,
    GuidId = Guid.NewGuid().ToString()
});

contextMenu.ListItems.Add(new SimpleItem
{
    Text = "Delete",
    ImagePath = "delete-icon.svg",
    GuidId = Guid.NewGuid().ToString()
});

// Handle item clicks
contextMenu.ItemClicked += (sender, item) =>
{
    switch (item.Text)
    {
        case "Edit":
            EditSelectedItem();
            break;
        case "Copy":
            CopySelectedItem();
            break;
        case "Delete":
            DeleteSelectedItem();
            break;
    }
};

// Show context menu on right-click
someControl.MouseDown += (sender, e) =>
{
    if (e.Button == MouseButtons.Right)
    {
        var screenLocation = someControl.PointToScreen(e.Location);
        contextMenu.Show(screenLocation);
    }
};

Data Grid Context Menu

public void SetupDataGridContextMenu(DataGridView dataGrid)
{
    var contextMenu = new BeepPopupListFormStrip();

    // Build context menu items
    var menuItems = new[]
    {
        new SimpleItem { Text = "View Details", ImagePath = "view-icon.svg", GuidId = Guid.NewGuid().ToString() },
        new SimpleItem { Text = "Edit Record", ImagePath = "edit-icon.svg", GuidId = Guid.NewGuid().ToString() },
        new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
        new SimpleItem { Text = "Send Email", ImagePath = "email-icon.svg", GuidId = Guid.NewGuid().ToString() },
        new SimpleItem { Text = "Call Contact", ImagePath = "phone-icon.svg", GuidId = Guid.NewGuid().ToString() },
        new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
        new SimpleItem { Text = "Export Data", ImagePath = "export-icon.svg", GuidId = Guid.NewGuid().ToString() },
        new SimpleItem { Text = "Generate Report", ImagePath = "report-icon.svg", GuidId = Guid.NewGuid().ToString() },
        new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
        new SimpleItem { Text = "Delete Record", ImagePath = "delete-icon.svg", GuidId = Guid.NewGuid().ToString() }
    };

    foreach (var item in menuItems)
    {
        contextMenu.ListItems.Add(item);
    }

    // Handle context menu actions
    contextMenu.ItemClicked += (sender, item) =>
    {
        if (dataGrid.SelectedRows.Count == 0) return;

        var selectedRow = dataGrid.SelectedRows[0];
        
        switch (item.Text)
        {
            case "View Details":
                ShowRecordDetails(selectedRow);
                break;
            case "Edit Record":
                EditRecord(selectedRow);
                break;
            case "Send Email":
                SendEmailToContact(selectedRow);
                break;
            case "Call Contact":
                InitiatePhoneCall(selectedRow);
                break;
            case "Export Data":
                ExportRowData(selectedRow);
                break;
            case "Generate Report":
                GenerateRecordReport(selectedRow);
                break;
            case "Delete Record":
                DeleteRecord(selectedRow);
                break;
        }
    };

    // Attach to data grid
    dataGrid.MouseDown += (sender, e) =>
    {
        if (e.Button == MouseButtons.Right)
        {
            var hitTest = dataGrid.HitTest(e.X, e.Y);
            if (hitTest.RowIndex >= 0)
            {
                // Select the row that was right-clicked
                dataGrid.ClearSelection();
                dataGrid.Rows[hitTest.RowIndex].Selected = true;

                // Show context menu
                var screenLocation = dataGrid.PointToScreen(e.Location);
                contextMenu.Show(screenLocation);
            }
        }
    };
}

Control Integration Pattern

public class ContextMenuProvider
{
    private readonly Dictionary contextMenus;

    public ContextMenuProvider()
    {
        contextMenus = new Dictionary();
        InitializeContextMenus();
    }

    private void InitializeContextMenus()
    {
        // Text control context menu
        var textContextMenu = CreateTextContextMenu();
        contextMenus[typeof(TextBox)] = textContextMenu;
        contextMenus[typeof(BeepTextBox)] = textContextMenu;

        // Image control context menu
        var imageContextMenu = CreateImageContextMenu();
        contextMenus[typeof(PictureBox)] = imageContextMenu;
        contextMenus[typeof(BeepImage)] = imageContextMenu;

        // List control context menu
        var listContextMenu = CreateListContextMenu();
        contextMenus[typeof(ListBox)] = listContextMenu;
        contextMenus[typeof(BeepListBox)] = listContextMenu;
    }

    private BeepPopupListFormStrip CreateTextContextMenu()
    {
        var menu = new BeepPopupListFormStrip();
        
        menu.ListItems.AddRange(new[]
        {
            new SimpleItem { Text = "Cut", ImagePath = "cut.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Copy", ImagePath = "copy.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Paste", ImagePath = "paste.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Select All", ImagePath = "select-all.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Find", ImagePath = "search.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Replace", ImagePath = "replace.svg", GuidId = Guid.NewGuid().ToString() }
        });

        menu.ItemClicked += (sender, item) =>
        {
            var activeControl = GetActiveTextControl();
            if (activeControl == null) return;

            switch (item.Text)
            {
                case "Cut":
                    if (activeControl is TextBoxBase textBox)
                        textBox.Cut();
                    break;
                case "Copy":
                    if (activeControl is TextBoxBase tb)
                        tb.Copy();
                    break;
                case "Paste":
                    if (activeControl is TextBoxBase tbPaste)
                        tbPaste.Paste();
                    break;
                case "Select All":
                    if (activeControl is TextBoxBase tbSelect)
                        tbSelect.SelectAll();
                    break;
                case "Find":
                    ShowFindDialog(activeControl);
                    break;
                case "Replace":
                    ShowReplaceDialog(activeControl);
                    break;
            }
        };

        return menu;
    }

    private BeepPopupListFormStrip CreateImageContextMenu()
    {
        var menu = new BeepPopupListFormStrip();
        
        menu.ListItems.AddRange(new[]
        {
            new SimpleItem { Text = "Copy Image", ImagePath = "copy.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Save Image As...", ImagePath = "save.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Zoom In", ImagePath = "zoom-in.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Zoom Out", ImagePath = "zoom-out.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Actual Size", ImagePath = "zoom-actual.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Properties", ImagePath = "properties.svg", GuidId = Guid.NewGuid().ToString() }
        });

        menu.ItemClicked += (sender, item) =>
        {
            var activeImage = GetActiveImageControl();
            if (activeImage == null) return;

            switch (item.Text)
            {
                case "Copy Image":
                    CopyImageToClipboard(activeImage);
                    break;
                case "Save Image As...":
                    SaveImageAs(activeImage);
                    break;
                case "Zoom In":
                    ZoomImage(activeImage, 1.2f);
                    break;
                case "Zoom Out":
                    ZoomImage(activeImage, 0.8f);
                    break;
                case "Actual Size":
                    ResetImageZoom(activeImage);
                    break;
                case "Properties":
                    ShowImageProperties(activeImage);
                    break;
            }
        };

        return menu;
    }

    public void AttachContextMenu(Control control)
    {
        if (contextMenus.TryGetValue(control.GetType(), out var contextMenu))
        {
            control.MouseDown += (sender, e) =>
            {
                if (e.Button == MouseButtons.Right)
                {
                    var screenLocation = control.PointToScreen(e.Location);
                    contextMenu.Show(screenLocation);
                }
            };
        }
    }

    // Helper methods
    private Control GetActiveTextControl() => Form.ActiveForm?.ActiveControl as TextBoxBase;
    private Control GetActiveImageControl() => Form.ActiveForm?.ActiveControl as PictureBox;
    private void ShowFindDialog(Control control) { /* Implementation */ }
    private void ShowReplaceDialog(Control control) { /* Implementation */ }
    private void CopyImageToClipboard(Control imageControl) { /* Implementation */ }
    private void SaveImageAs(Control imageControl) { /* Implementation */ }
    private void ZoomImage(Control imageControl, float factor) { /* Implementation */ }
    private void ResetImageZoom(Control imageControl) { /* Implementation */ }
    private void ShowImageProperties(Control imageControl) { /* Implementation */ }
}

Properties

Inherited from BeepListBox

Property Type Description
ListItems BindingList<SimpleItem> Collection of context menu items
ShowCheckBox bool Whether to show checkboxes (default: false for context menus)
SelectedIndex int Index of currently selected item
SelectedItem SimpleItem Currently selected menu item

Context Menu Specific

Property Type Description
PopupForm BeepPopupForm Internal popup form hosting the context menu

SimpleItem Structure

Property Type Description
Text string Display text for the menu item
ImagePath string Path to icon image file
IsSeparator bool Whether the item is a visual separator (Text = "-")
GuidId string Unique identifier for the menu item
Tag object Additional data associated with the item
Enabled bool Whether the menu item is enabled

Events

Context Menu Events

Event Event Args Description
ItemClicked EventHandler<SimpleItem> Fired when a context menu item is clicked

Inherited Events from BeepListBox

Event Event Args Description
SelectedItemChanged EventHandler Fired when the selected item changes
ListItemClicked Override method Handles individual item clicks from BeepButton controls

Examples

Tree View Context Menu

public void SetupTreeViewContextMenu(TreeView treeView)
{
    var contextMenu = new BeepPopupListFormStrip();

    // Node-specific menu items that change based on node type
    contextMenu.ItemClicked += (sender, item) =>
    {
        if (treeView.SelectedNode == null) return;

        var node = treeView.SelectedNode;
        
        switch (item.Text)
        {
            case "Add Child":
                AddChildNode(node);
                break;
            case "Edit":
                EditNode(node);
                break;
            case "Delete":
                DeleteNode(node);
                break;
            case "Expand All":
                node.ExpandAll();
                break;
            case "Collapse All":
                node.Collapse();
                break;
            case "Properties":
                ShowNodeProperties(node);
                break;
        }
    };

    // Build context menu dynamically based on selected node
    treeView.MouseDown += (sender, e) =>
    {
        if (e.Button == MouseButtons.Right)
        {
            var node = treeView.GetNodeAt(e.X, e.Y);
            if (node != null)
            {
                treeView.SelectedNode = node;
                
                // Clear existing items
                contextMenu.ListItems.Clear();

                // Add items based on node type/level
                if (node.Level == 0) // Root node
                {
                    contextMenu.ListItems.AddRange(new[]
                    {
                        new SimpleItem { Text = "Add Child", ImagePath = "add.svg", GuidId = Guid.NewGuid().ToString() },
                        new SimpleItem { Text = "Expand All", ImagePath = "expand.svg", GuidId = Guid.NewGuid().ToString() },
                        new SimpleItem { Text = "Collapse All", ImagePath = "collapse.svg", GuidId = Guid.NewGuid().ToString() },
                        new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
                        new SimpleItem { Text = "Properties", ImagePath = "properties.svg", GuidId = Guid.NewGuid().ToString() }
                    });
                }
                else // Child nodes
                {
                    contextMenu.ListItems.AddRange(new[]
                    {
                        new SimpleItem { Text = "Add Child", ImagePath = "add.svg", GuidId = Guid.NewGuid().ToString() },
                        new SimpleItem { Text = "Edit", ImagePath = "edit.svg", GuidId = Guid.NewGuid().ToString() },
                        new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
                        new SimpleItem { Text = "Delete", ImagePath = "delete.svg", GuidId = Guid.NewGuid().ToString() },
                        new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
                        new SimpleItem { Text = "Properties", ImagePath = "properties.svg", GuidId = Guid.NewGuid().ToString() }
                    });
                }

                // Show context menu
                var screenLocation = treeView.PointToScreen(e.Location);
                contextMenu.Show(screenLocation);
            }
        }
    };
}

private void AddChildNode(TreeNode parentNode)
{
    var newNode = new TreeNode("New Node");
    parentNode.Nodes.Add(newNode);
    parentNode.Expand();
    // Begin edit mode
    newNode.BeginEdit();
}

private void EditNode(TreeNode node)
{
    node.BeginEdit();
}

private void DeleteNode(TreeNode node)
{
    if (MessageBox.Show($"Delete '{node.Text}'?", "Confirm Delete", 
        MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
    {
        node.Remove();
    }
}

private void ShowNodeProperties(TreeNode node)
{
    var properties = new Dictionary
    {
        ["Text"] = node.Text,
        ["Level"] = node.Level,
        ["Index"] = node.Index,
        ["Children"] = node.Nodes.Count,
        ["Tag"] = node.Tag?.ToString() ?? "None"
    };

    // Show properties dialog
    var propertiesForm = new NodePropertiesForm(properties);
    propertiesForm.ShowDialog();
}

File Explorer Context Menu

public class FileExplorerContextMenu
{
    private BeepPopupListFormStrip fileContextMenu;
    private BeepPopupListFormStrip folderContextMenu;
    private BeepPopupListFormStrip emptySpaceContextMenu;

    public FileExplorerContextMenu()
    {
        InitializeContextMenus();
    }

    private void InitializeContextMenus()
    {
        // File context menu
        fileContextMenu = new BeepPopupListFormStrip();
        fileContextMenu.ListItems.AddRange(new[]
        {
            new SimpleItem { Text = "Open", ImagePath = "open.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Open With", ImagePath = "open-with.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Cut", ImagePath = "cut.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Copy", ImagePath = "copy.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Delete", ImagePath = "delete.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Rename", ImagePath = "rename.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Properties", ImagePath = "properties.svg", GuidId = Guid.NewGuid().ToString() }
        });

        // Folder context menu
        folderContextMenu = new BeepPopupListFormStrip();
        folderContextMenu.ListItems.AddRange(new[]
        {
            new SimpleItem { Text = "Open", ImagePath = "open.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Open in New Window", ImagePath = "new-window.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Cut", ImagePath = "cut.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Copy", ImagePath = "copy.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Delete", ImagePath = "delete.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Rename", ImagePath = "rename.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Properties", ImagePath = "properties.svg", GuidId = Guid.NewGuid().ToString() }
        });

        // Empty space context menu
        emptySpaceContextMenu = new BeepPopupListFormStrip();
        emptySpaceContextMenu.ListItems.AddRange(new[]
        {
            new SimpleItem { Text = "New", ImagePath = "new.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Paste", ImagePath = "paste.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Refresh", ImagePath = "refresh.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "-", IsSeparator = true, GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "View", ImagePath = "view.svg", GuidId = Guid.NewGuid().ToString() },
            new SimpleItem { Text = "Sort By", ImagePath = "sort.svg", GuidId = Guid.NewGuid().ToString() }
        });

        // Wire up events
        fileContextMenu.ItemClicked += (s, item) => HandleFileAction(item);
        folderContextMenu.ItemClicked += (s, item) => HandleFolderAction(item);
        emptySpaceContextMenu.ItemClicked += (s, item) => HandleEmptySpaceAction(item);
    }

    public void AttachToListView(ListView listView)
    {
        listView.MouseDown += (sender, e) =>
        {
            if (e.Button == MouseButtons.Right)
            {
                var item = listView.GetItemAt(e.X, e.Y);
                var screenLocation = listView.PointToScreen(e.Location);

                if (item != null)
                {
                    // Select the item
                    listView.SelectedItems.Clear();
                    item.Selected = true;

                    // Show appropriate context menu based on item type
                    var isFolder = (bool)(item.Tag ?? false);
                    if (isFolder)
                    {
                        folderContextMenu.Show(screenLocation);
                    }
                    else
                    {
                        fileContextMenu.Show(screenLocation);
                    }
                }
                else
                {
                    // Right-clicked on empty space
                    emptySpaceContextMenu.Show(screenLocation);
                }
            }
        };
    }

    private void HandleFileAction(SimpleItem item)
    {
        switch (item.Text)
        {
            case "Open":
                OpenSelectedFile();
                break;
            case "Open With":
                ShowOpenWithDialog();
                break;
            case "Cut":
                CutSelectedItems();
                break;
            case "Copy":
                CopySelectedItems();
                break;
            case "Delete":
                DeleteSelectedItems();
                break;
            case "Rename":
                RenameSelectedItem();
                break;
            case "Properties":
                ShowFileProperties();
                break;
        }
    }

    private void HandleFolderAction(SimpleItem item)
    {
        switch (item.Text)
        {
            case "Open":
                OpenSelectedFolder();
                break;
            case "Open in New Window":
                OpenFolderInNewWindow();
                break;
            // ... other folder actions
        }
    }

    private void HandleEmptySpaceAction(SimpleItem item)
    {
        switch (item.Text)
        {
            case "New":
                ShowNewItemMenu();
                break;
            case "Paste":
                PasteItems();
                break;
            case "Refresh":
                RefreshView();
                break;
            // ... other empty space actions
        }
    }

    // Implementation methods
    private void OpenSelectedFile() { /* Implementation */ }
    private void ShowOpenWithDialog() { /* Implementation */ }
    private void CutSelectedItems() { /* Implementation */ }
    private void CopySelectedItems() { /* Implementation */ }
    private void DeleteSelectedItems() { /* Implementation */ }
    private void RenameSelectedItem() { /* Implementation */ }
    private void ShowFileProperties() { /* Implementation */ }
    private void OpenSelectedFolder() { /* Implementation */ }
    private void OpenFolderInNewWindow() { /* Implementation */ }
    private void ShowNewItemMenu() { /* Implementation */ }
    private void PasteItems() { /* Implementation */ }
    private void RefreshView() { /* Implementation */ }
}

Theming

BeepPopupListFormStrip inherits full theming capabilities from BeepListBox with additional popup-specific styling:

Theme Application

var contextMenu = new BeepPopupListFormStrip
{
    Theme = "DarkTheme"
};

// Theme automatically applies to:
// - Menu item backgrounds and text
// - Hover and selection states
// - Border and separator colors
// - Popup form background
// - Icon color adjustments

// Manual theme refresh
contextMenu.ApplyTheme();

Context Menu Theming Properties

  • PanelBackColor - Context menu background
  • ButtonBackColor - Menu item backgrounds
  • ButtonForeColor - Menu item text color
  • ButtonHoverBackColor - Hover state background
  • ButtonSelectedBackColor - Selected item background
  • BorderColor - Menu border and separators
  • ShadowColor - Drop shadow effects

Custom Popup Styling

// Override ApplyTheme for custom popup styling
public class CustomContextMenuStrip : BeepPopupListFormStrip
{
    public override void ApplyTheme()
    {
        base.ApplyTheme();
        
        if (popupForm != null && _currentTheme != null)
        {
            // Custom popup form styling
            popupForm.BackColor = _currentTheme.PanelBackColor;
            popupForm.Opacity = 0.98; // Slight transparency
            
            // Add custom shadow effects
            if (_currentTheme.ShowShadow)
            {
                popupForm.DropShadow = true;
                popupForm.ShadowDepth = 8;
            }
        }
    }
}

Best Practices

??? User Experience

  • Context awareness: Show only relevant actions for the selected item/context
  • Logical grouping: Use separators to group related menu items
  • Clear icons: Use intuitive icons that match the action being performed
  • Keyboard shortcuts: Display keyboard shortcuts for common actions

?? Positioning & Behavior

  • Screen boundaries: Ensure context menus stay within screen bounds
  • Quick access: Keep frequently used actions at the top of the menu
  • Auto-hide: Close menus when clicking outside or pressing Escape
  • Selection feedback: Provide clear visual feedback for menu item selection

?? Implementation

  • Dynamic menus: Build menu contents based on current context/selection
  • State management: Enable/disable menu items based on current state
  • Error handling: Gracefully handle menu actions that might fail
  • Memory management: Properly dispose of popup forms and resources

? Performance

  • Lazy creation: Create context menus only when needed
  • Reuse menus: Reuse context menu instances where appropriate
  • Efficient updates: Update menu contents efficiently without recreation
  • Resource cleanup: Dispose of unused menu resources properly
?? Design Tip

Keep context menus focused and concise. More than 10-12 items can overwhelm users - consider using submenus for complex actions.

? Best Practice

Always handle the ItemClicked event to provide immediate feedback and action execution when menu items are selected.

?? Memory Warning

Ensure proper disposal of BeepPopupForm instances to prevent memory leaks, especially in applications with frequent context menu usage.