【问题标题】:Enable copy, cut, past window in a rich text box在富文本框中启用复制、剪切、粘贴窗口
【发布时间】:2013-09-28 18:31:24
【问题描述】:

我的程序中有一个富文本框(richTextBox1),如下所示。但是当我右键单击它时,它并没有弹出“复制,剪切,过去”窗口。你能告诉我如何在我的富文本框中启用这个“复制、剪切、过去”窗口吗?我是 C# 新手,如果你知道如何解决这个问题,请一步一步告诉我

【问题讨论】:

  • RTB 没有像 TextBox 那样内置。 .NET 使它们看起来很相似,但实际上它们是非常不同的原生 Windows 组件。你可以从搞砸的边框看出一些。您必须自己制作,使用 ContextMenuStrip。
  • WPF RichTextBox 确实有这个菜单。只是说。或许最好不要使用稍微破旧的旧技术开始新项目。

标签: c# vb.net visual-studio


【解决方案1】:

如果你有多个RichTextBox,那么你可以使用这个extension方法:

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;
    }
}

并像这样使用它:richTextBox1.AddContextMenu();

截图:

【讨论】:

  • 一个绝对完美的简单解决方案。谢谢。人们似乎真的把这件事复杂化了……
  • 太好了,我用它。但总有改进的余地 - 例如添加 2 if (!rtb.ReadOnly) { - 或者有意义的变灰怎么样?对于没有经验的用户,您还可以添加一个提示:在 Form1.cs 中是不可能的,但在 Program.cs 中它可以工作。
  • 如何使用它在提供的扩展链接中给出。
  • 删除选项不可见 :(
  • @Faisal 仅当您选择文本时才会启用删除选项。您可以从此行更改此行为:tsmiDelete.Enabled = !rtb.ReadOnly &amp;&amp; rtb.SelectionLength &gt; 0;
【解决方案2】:

试试这个代码

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();
            }
        } 

如果你想用记事本(without styles )等其他应用程序复制粘贴,请替换以下方法

       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();
            }
        }  

【讨论】:

  • 非常感谢您向我展示了一个示例。为了使用此代码,我是否也必须创建一个MenuStrip?因为当我使用您的代码时,private void richTextBox1_MouseUp(object sender, MouseEventArgs e) 没有被调用。如果我双击原图所示的richTextBox1,它将在Form1.Designer.csForm1.cs自动生成代码:-private void richTextBox1_TextChanged(object sender, EventArgs e)你能告诉我我应该怎么做才能让我的程序生成代码private void richTextBox1_MouseUp(object sender, MouseEventArgs e)
  • 非常感谢您为我提供所有这些信息。如果我只在这个richTextBox1 内做copy, cut, past 的事情,它会起作用。如果我从 `richTextBox1` 切入并在记事本中过去,它也可以工作。但是如果我尝试从richTextBox1 复制并粘贴到记事本中,它就不起作用了。最重要的是,如果我想将记事本中的一些文本复制到这个 `richTextBox1` 中,则代码不起作用。非常感谢您对此的关注。
  • 非常感谢您提供的所有帮助并通过示例向我解释事情。感谢您的帮助。
  • 我认为不是MouseUp事件,应该是MouseDown事件。 ` private void richTextBox1_MouseDown(object sender, MouseEventArgs e)`
  • @Thilina H 不错的答案,但是您确实不需要每次右键单击文本时都创建上下文菜单。这是滞后和不方便的。相反,只需在 Form_Load 处创建并附加上下文菜单一次。
【解决方案3】:

标准的 RichTextBox 不包含用于剪切、复制和粘贴的上下文菜单。但是,您可以查看this article,其中包含实现您自己所需的完整代码!

【讨论】:

    【解决方案4】:

    我认为 Thilina H 提供的解决方案非常好,除了一些错误。

    1. MouseUp 事件导致右键单击在第二次单击后开始。我建议使用 MouseDown 事件而不是 MouseUp 事件。

    2. 我测试了第二个提供的 CopyAction 方法。在我的情况下, CopyAction 方法没有复制输入字符。我不得不像这样编辑代码:

      Clipboard.SetText(richTextBox1.SelectedText.Replace("\n", "\r\n"));
      
    3. richTextBox1.SelectedText 为空时,程序显示异常。我只是编辑了如下所示的 CopyAction 方法来解决问题。

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

    编码愉快!

    【讨论】:

    • 这用于复制换行符,但如上所述,每次右键单击文本时都不必创建 @Thilina 上下文菜单。这是滞后和不方便的。相反,只需在 Form_Load 处创建并附加上下文菜单一次。
    【解决方案5】:

    如果您需要将标准上下文菜单添加到多个 RichTextBox 实例,那么创建从 RichTextBox 继承的自定义扩展组件可能会更好。可以从解决方案资源管理器项目上下文菜单添加新组件添加 -> 新项目... -> 自定义控件。

    您还可以为上下文菜单打开定义处理程序,以检查是否选择了任何文本、剪贴板是否为空以及控件是否未设置为只读。

    支持其他有用的标准操作也很好,例如撤消、重做、删除和全选。

    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;
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      我只是想补充一下Thilina H的答案(被海报标记为正确答案的那个) 这是我的复制和粘贴功能,它们有点像记事本。

      void CopyAction(object sender, EventArgs e)
      {
          if (richTextBox1.SelectedText != null && richTextBox1.SelectedText != "")
          {
              Clipboard.SetText(richTextBox1.SelectedText);
          }
      }
      
      void PasteAction(object sender, EventArgs e)
      {
          if (Clipboard.ContainsText())
          {
              int selstart = richTextBox1.SelectionStart;
              if (richTextBox1.SelectedText != null && richTextBox1.SelectedText != "")
              {
                  richTextBox1.Text = richTextBox1.Text.Remove(selstart, richTextBox1.SelectionLength);
              }
      
              string clip = Clipboard.GetText(TextDataFormat.Text).ToString();
              richTextBox1.Text = richTextBox1.Text.Insert(selstart, clip);
              richTextBox1.SelectionStart = selstart + clip.Length;
          }
      }
      

      我希望它对某人有所帮助;

      【讨论】:

        【解决方案7】:

        感谢@Jaex

        https://stackoverflow.com/a/36624233/5132252

        https://stackoverflow.com/a/435510/5132252

            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
            internal static extern IntPtr GetFocus();
        
            private Control GetFocusedControl()
            {
                Control focusedControl = null;
                // To get hold of the focused control:
                IntPtr focusedHandle = GetFocus();
                if (focusedHandle != IntPtr.Zero)
                    // Note that if the focused Control is not a .Net control, then this will return null.
                    focusedControl = Control.FromHandle(focusedHandle);
                return focusedControl;
            }
        
            private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
            {
        
                if (Clipboard.ContainsText())
                {
                    var FocusedControl = GetFocusedControl();
        
                    if (FocusedControl != null)
                        switch (FocusedControl.GetType().Name)
                        {
                            case "RichTextBox":
                                {
                                    var RichTextBox = FocusedControl as RichTextBox;
                                    RichTextBox.Paste();
                                    break;
                                }
                            case "TextBox":
                                {
                                    var TextBox = FocusedControl as TextBox;
                                    TextBox.Paste();
                                    break;
                                }
        
                        }
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2021-07-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-18
          相关资源
          最近更新 更多