Implementing Copy, Cut, and Paste Context Menu in a Rich Text Box in C#

By FoxLearn 2/14/2025 6:53:03 AM   43
This guide will show you how to create a context menu with basic text editing options like Copy, Cut, and Paste for a RichTextBox in a WinForms application.

Since RichTextBox components don't offer built-in utilities for essential text-editing actions, such as copying, cutting, or selecting text, we’ll need to implement this feature ourselves. Follow these steps to add a functional context menu to your RichTextBox.

1. Create the ExtensionMethods Class

When implementing a feature used across multiple parts of your project, it’s best to create an extension method rather than repeatedly writing the same code. Instead of creating a new derived type for RichTextBox, you can extend the existing type with custom functionality.

First, create a new file named ExtensionMethods.cs

For example, How to create an extension method that adds a context menu to the RichTextBox.

using System.Windows.Forms;

public static class RichTextBoxExtensions
{
    public static void EnableContextMenu(this RichTextBox richTextBox)
    {
        if (richTextBox.ContextMenuStrip == null)
        {
            // Create a ContextMenuStrip without icons
            var contextMenu = new ContextMenuStrip { ShowImageMargin = false };

            // Add Undo, Redo, Cut, Copy, Paste, Delete, Select All actions
            AddMenuItem(contextMenu, "Undo", (sender, e) => richTextBox.Undo(), !richTextBox.ReadOnly && richTextBox.CanUndo);
            AddMenuItem(contextMenu, "Redo", (sender, e) => richTextBox.Redo(), !richTextBox.ReadOnly && richTextBox.CanRedo);
            contextMenu.Items.Add(new ToolStripSeparator());
            AddMenuItem(contextMenu, "Cut", (sender, e) => richTextBox.Cut(), !richTextBox.ReadOnly && richTextBox.SelectionLength > 0);
            AddMenuItem(contextMenu, "Copy", (sender, e) => richTextBox.Copy(), richTextBox.SelectionLength > 0);
            AddMenuItem(contextMenu, "Paste", (sender, e) => richTextBox.Paste(), !richTextBox.ReadOnly && Clipboard.ContainsText());
            AddMenuItem(contextMenu, "Delete", (sender, e) => richTextBox.SelectedText = "", !richTextBox.ReadOnly && richTextBox.SelectionLength > 0);
            contextMenu.Items.Add(new ToolStripSeparator());
            AddMenuItem(contextMenu, "Select All", (sender, e) => richTextBox.SelectAll(), richTextBox.TextLength > 0 && richTextBox.SelectionLength < richTextBox.TextLength);

            // Enable/disable actions dynamically when opening the menu
            contextMenu.Opening += (sender, e) =>
            {
                EnableDisableMenuItems(contextMenu, richTextBox);
            };

            richTextBox.ContextMenuStrip = contextMenu;
        }
    }

    private static void AddMenuItem(ContextMenuStrip menu, string text, EventHandler clickAction, bool isEnabled)
    {
        var menuItem = new ToolStripMenuItem(text)
        {
            Enabled = isEnabled
        };
        menuItem.Click += clickAction;
        menu.Items.Add(menuItem);
    }

    private static void EnableDisableMenuItems(ContextMenuStrip menu, RichTextBox richTextBox)
    {
        foreach (ToolStripMenuItem item in menu.Items)
        {
            if (item.Text == "Undo")
                item.Enabled = !richTextBox.ReadOnly && richTextBox.CanUndo;
            else if (item.Text == "Redo")
                item.Enabled = !richTextBox.ReadOnly && richTextBox.CanRedo;
            else if (item.Text == "Cut")
                item.Enabled = !richTextBox.ReadOnly && richTextBox.SelectionLength > 0;
            else if (item.Text == "Copy")
                item.Enabled = richTextBox.SelectionLength > 0;
            else if (item.Text == "Paste")
                item.Enabled = !richTextBox.ReadOnly && Clipboard.ContainsText();
            else if (item.Text == "Delete")
                item.Enabled = !richTextBox.ReadOnly && richTextBox.SelectionLength > 0;
            else if (item.Text == "Select All")
                item.Enabled = richTextBox.TextLength > 0 && richTextBox.SelectionLength < richTextBox.TextLength;
        }
    }
}

This code defines an extension method EnableContextMenu for the RichTextBox class. It dynamically creates a ContextMenuStrip and populates it with text-editing actions like Undo, Redo, Cut, Copy, Paste, Delete, and Select All. It also enables or disables actions based on the current state of the RichTextBox.

2. Enable the Context Menu on a RichTextBox

Now that the extension method is ready, you can use it on any RichTextBox to enable the context menu.

Simply call EnableContextMenu() on your RichTextBox instance.

using System;
using System.Windows.Forms;
using ExtensionMethods;

namespace Sandbox
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            // Enable Context Menu!
            richTextBox1.EnableContextMenu();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }
    }
}

This solution allows you to add a context menu to a RichTextBox that includes the most commonly used text-editing operations: Cut, Copy, Paste, Undo, Redo, Select All, and Delete.

By using an extension method, you avoid code duplication and make the feature reusable across your project. The context menu is dynamically populated based on the current state of the RichTextBox, ensuring that only relevant options are enabled.

Now, when you right-click on the RichTextBox, the context menu will appear with options enabled based on the current context of the text inside the box.