Enable copy, cut, past window in a rich text box

49,611

Solution 1

Try with this code

UPDATED CODE:

        private void richTextBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {   //click event
                //MessageBox.Show("you got it!");
                ContextMenu contextMenu = new System.Windows.Forms.ContextMenu();
                MenuItem menuItem = new MenuItem("Cut");
                menuItem.Click += new EventHandler(CutAction);
                contextMenu.MenuItems.Add(menuItem);
                menuItem = new MenuItem("Copy");
                menuItem.Click += new EventHandler(CopyAction);
                contextMenu.MenuItems.Add(menuItem);
                menuItem = new MenuItem("Paste");
                menuItem.Click += new EventHandler(PasteAction);
                contextMenu.MenuItems.Add(menuItem);

                richTextBox1.ContextMenu = contextMenu;
            }
        }
        void CutAction(object sender, EventArgs e)
        {
            richTextBox1.Cut();
        }

        void CopyAction(object sender, EventArgs e)
        {
            Graphics objGraphics;
            Clipboard.SetData(DataFormats.Rtf, richTextBox1.SelectedRtf);
            Clipboard.Clear();
        }

        void PasteAction(object sender, EventArgs e)
        {
            if (Clipboard.ContainsText(TextDataFormat.Rtf))
            {
                richTextBox1.SelectedRtf
                    = Clipboard.GetData(DataFormats.Rtf).ToString();
            }
        } 

if you want to copy paste with another application like notepad (without styles ) please replace following methods

       void CopyAction(object sender, EventArgs e)
        {
            Clipboard.SetText(richTextBox1.SelectedText);
        }

        void PasteAction(object sender, EventArgs e)
        {
            if (Clipboard.ContainsText())
            {
                richTextBox1.Text
                    += Clipboard.GetText(TextDataFormat.Text).ToString();
            }
        }  

Solution 2

If you have more than one RichTextBox then you can use this extension method:

public static void AddContextMenu(this RichTextBox rtb)
{
    if (rtb.ContextMenuStrip == null)
    {
        ContextMenuStrip cms = new ContextMenuStrip()
        {
            ShowImageMargin = false
        };

        ToolStripMenuItem tsmiUndo = new ToolStripMenuItem("Undo");
        tsmiUndo.Click += (sender, e) => rtb.Undo();
        cms.Items.Add(tsmiUndo);

        ToolStripMenuItem tsmiRedo = new ToolStripMenuItem("Redo");
        tsmiRedo.Click += (sender, e) => rtb.Redo();
        cms.Items.Add(tsmiRedo);

        cms.Items.Add(new ToolStripSeparator());

        ToolStripMenuItem tsmiCut = new ToolStripMenuItem("Cut");
        tsmiCut.Click += (sender, e) => rtb.Cut();
        cms.Items.Add(tsmiCut);

        ToolStripMenuItem tsmiCopy = new ToolStripMenuItem("Copy");
        tsmiCopy.Click += (sender, e) => rtb.Copy();
        cms.Items.Add(tsmiCopy);

        ToolStripMenuItem tsmiPaste = new ToolStripMenuItem("Paste");
        tsmiPaste.Click += (sender, e) => rtb.Paste();
        cms.Items.Add(tsmiPaste);

        ToolStripMenuItem tsmiDelete = new ToolStripMenuItem("Delete");
        tsmiDelete.Click += (sender, e) => rtb.SelectedText = "";
        cms.Items.Add(tsmiDelete);

        cms.Items.Add(new ToolStripSeparator());

        ToolStripMenuItem tsmiSelectAll = new ToolStripMenuItem("Select All");
        tsmiSelectAll.Click += (sender, e) => rtb.SelectAll();
        cms.Items.Add(tsmiSelectAll);

        cms.Opening += (sender, e) =>
        {
            tsmiUndo.Enabled = !rtb.ReadOnly && rtb.CanUndo;
            tsmiRedo.Enabled = !rtb.ReadOnly && rtb.CanRedo;
            tsmiCut.Enabled = !rtb.ReadOnly && rtb.SelectionLength > 0;
            tsmiCopy.Enabled = rtb.SelectionLength > 0;
            tsmiPaste.Enabled = !rtb.ReadOnly && Clipboard.ContainsText();
            tsmiDelete.Enabled = !rtb.ReadOnly && rtb.SelectionLength > 0;
            tsmiSelectAll.Enabled = rtb.TextLength > 0 && rtb.SelectionLength < rtb.TextLength;
        };

        rtb.ContextMenuStrip = cms;
    }
}

And use it like this: richTextBox1.AddContextMenu();

Screenshot: screenshot

Solution 3

A standard RichTextBox does not contain a context menu for cut, copy and paste. However, you can look at this article which has the complete code needed to implement your own!

Solution 4

In case that you need to add standard context menu to multiple RichTextBox instances then it may be better to create custom extended component inherited from RichTextBox. New component can be added from Solution Explorer project context menu Add -> New Item... -> Custom Control.

You can also define handler for context menu opening to check if any text is selected, clipboard is not empty and if the control is not set as read only.

It is also good to support other useful standard actions like Undo, Redo, Delete, and Select All.

namespace Common
{
    public partial class RichTextBoxEx : RichTextBox
    {
        public RichTextBoxEx()
        {
            AddContextMenu();
        }

        public void AddContextMenu()
        {
            ContextMenuStrip cms = new ContextMenuStrip { ShowImageMargin = false };

            ToolStripMenuItem tsmiUndo = new ToolStripMenuItem("Undo");
            tsmiUndo.Click += (sender, e) => { if (CanUndo) Undo(); };
            tsmiUndo.ShortcutKeys = Keys.Z | Keys.Control;
            cms.Items.Add(tsmiUndo);

            ToolStripMenuItem tsmiRedo = new ToolStripMenuItem("Redo");
            tsmiRedo.Click += (sender, e) => { if (CanRedo) Redo(); };
            tsmiRedo.ShortcutKeys = Keys.Y | Keys.Control;
            cms.Items.Add(tsmiRedo);

            cms.Items.Add(new ToolStripSeparator());

            ToolStripMenuItem tsmiCut = new ToolStripMenuItem("Cut");
            tsmiCut.Click += (sender, e) => Cut();
            tsmiCut.ShortcutKeys = Keys.X | Keys.Control;
            cms.Items.Add(tsmiCut);

            ToolStripMenuItem tsmiCopy = new ToolStripMenuItem("Copy");
            tsmiCopy.Click += (sender, e) => Copy();
            tsmiCopy.ShortcutKeys = Keys.C | Keys.Control;
            cms.Items.Add(tsmiCopy);

            ToolStripMenuItem tsmiPaste = new ToolStripMenuItem("Paste");
            tsmiPaste.Click += (sender, e) => Paste();
            tsmiPaste.ShortcutKeys = Keys.V | Keys.Control;                
            cms.Items.Add(tsmiPaste);

            ToolStripMenuItem tsmiDelete = new ToolStripMenuItem("Delete");
            tsmiDelete.Click += (sender, e) => { SelectedText = ""; };                                
            cms.Items.Add(tsmiDelete);

            cms.Items.Add(new ToolStripSeparator());

            ToolStripMenuItem tsmiSelectAll = new ToolStripMenuItem("Select All");
            tsmiSelectAll.Click += (sender, e) => { SelectionStart = 0; SelectionLength = Text.Length; };
            tsmiSelectAll.ShortcutKeys = Keys.A | Keys.Control;
            cms.Items.Add(tsmiSelectAll);

            cms.Opening += delegate (object sender, CancelEventArgs e) 
            {
                tsmiUndo.Enabled = CanUndo && !this.ReadOnly;
                tsmiRedo.Enabled = CanRedo && !this.ReadOnly;
                tsmiCut.Enabled = (SelectionLength != 0) && !this.ReadOnly;
                tsmiCopy.Enabled = SelectionLength != 0;
                tsmiPaste.Enabled = Clipboard.ContainsText() && !this.ReadOnly;
                tsmiDelete.Enabled = (SelectionLength != 0) && !this.ReadOnly;
                tsmiSelectAll.Enabled = (TextLength > 0) && (SelectionLength < TextLength);
            };

            ContextMenuStrip = cms;
        }
    }
}

Solution 5

I think the solution provided by Thilina H is excellent except few bugs.

  1. MouseUp event causes the right click to start after second click. I recommend using MouseDown event instead of MouseUp event.

  2. I tested secondly provided CopyAction method. In my case CopyAction method didn't copy enter characters. I had to edit the code like this:

    Clipboard.SetText(richTextBox1.SelectedText.Replace("\n", "\r\n"));
    
  3. When richTextBox1.SelectedText is empty the program showed an exception. I simply edited the CopyAction method shown by below to fix the issue.

        if (chatBox.SelectedText != null && chatBox.SelectedText != "")
        {
            Clipboard.SetText(richTextBox1.SelectedText.Replace("\n", "\r\n"));
        }
    

Happy Coding!

Share:
49,611
D P.
Author by

D P.

it's me its me, it's me

Updated on March 03, 2020

Comments

  • D P.
    D P. about 4 years

    I have a rich text box(richTextBox1) in my program as shown bellow. But when I right click on it, it doesn't pop up a “copy, cut, past” window. Can you please tell me how can I enable this “copy, cut, past” window in to my Rich Text Box? I am new to C#, please let me know step by step, if you know how to solve this

    enter image description here