仅当鼠标位置位于 richTextBox 中的选定文本上时,如何才能启用上下文菜单?

How can i enable contextmenu menu only if the mouse position is on selected text in richTextBox?

上下文菜单将在任何情况下显示,但仅当鼠标位于所选文本上而不是 richTextBox 区域中的任何位置时才应启用菜单。

private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                for (int i = 0; i < contextMenu.MenuItems.Count; i++)
                {
                    if (richTextBox1.SelectedText != "")
                    {
                        contextMenu.MenuItems[i].Enabled = true;
                    }
                    else
                    {
                        contextMenu.MenuItems[i].Enabled = false;
                    }
                }
            }
        }

这仅在选择文本时启用菜单项。 现在我想添加另一个条件,如果鼠标位置在所选文本上,则启用 true。

如果不启用false。所以应该有两个条件,一个是文本被选中,另一个是鼠标位于所选文本的任何部分。还不确定如何满足第二个条件。

更新

我现在尝试了什么:

private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                int positionToSearch = richTextBox1.GetCharIndexFromPosition(e.Location);
                bool isInSelectedText = positionToSearch >= richTextBox1.SelectionStart && positionToSearch < richTextBox1.SelectionStart + richTextBox1.SelectionLength;
                for (int i = 0; i < contextMenu.MenuItems.Count; i++)
                {
                    if (richTextBox1.SelectedText != "" &&
                        isInSelectedText == true)
                    {
                        contextMenu.MenuItems[i].Enabled = true;
                    }
                    else
                    {
                        contextMenu.MenuItems[i].Enabled = false;
                    }
                }
            }
        }

但是当我右键单击所选文本时,它会启用菜单,但是如果我在 richtextbox 区域的其他地方右键单击,菜单仍将启用,我希望它只在选定的文本。

如果根本没有选择文本,则启用 false 菜单。

我在表单加载事件中添加了一次上下文菜单:

private void Form1_Load(object sender, EventArgs e)
        {
            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;

            for (int i = 0; i < contextMenu.MenuItems.Count; i++)
            {
                contextMenu.MenuItems[i].Enabled = false;
            }
        }

这是我的看法。在此示例中,我没有打开上下文菜单,而是在适当位置单击鼠标时附加到 RichTextBox。

此代码段需要一些工作才能具有生产价值,尤其是在定义 "fudgeFactored" 区域时,但前提是存在。在下面的代码中,我只关心文本选择的起始位置,但如果我要将其作为生产脚本,我会查看它的开始位置、结束位置,然后我会将 fudgeFactor 添加到它。

using System;
using System.Drawing;
using System.Windows.Forms;

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


        private void doit(Point mouseClickedAtPosition)
        {
            if (txtbx_1.SelectedText != null)
            {
                //find out where the selected text is
                Point selectionposition = txtbx_1.GetPositionFromCharIndex(txtbx_1.SelectionStart);

                /*
                 * the user is not likely to click in the right spot every time,
                 * so let's make a fudgeFactor
                 */
                int fudgeFactor = 15;


                if ((mouseClickedAtPosition.X <= selectionposition.X + fudgeFactor && mouseClickedAtPosition.X >= selectionposition.X - fudgeFactor) && (mouseClickedAtPosition.Y <= selectionposition.Y + fudgeFactor && mouseClickedAtPosition.Y >= selectionposition.Y - fudgeFactor))
                {
                    /*
                     * If the right click happened within the fudgeFactored area, then append to the box(open your menu)
                     */
                    txtbx_1.AppendText("positions are matching");
                }
                else
                {
                    /*
                     * User did not right-click in the proper area
                     * don't show your menu
                     */
                    txtbx_1.AppendText("not matching" + Environment.NewLine);
                }
            }
        }

        private void txtbx_1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                doit(e.Location);
            }
        }
    }
}

您可以使用richTextBox.GetCharIndexFromPosition函数来获取最接近字符的索引(richTextBox文本中的位置)。然后简单地验证这个索引是否在选择的开始和结束之间

int positionToSearch = richTextBox1.GetCharIndexFromPosition(e.Location);
bool isInSelectedText = positionToSearch >= richTextBox1.SelectionStart && positionToSearch < richTextBox1.SelectionStart + richTextBox1.SelectionLength

因为您正在检查左按钮是否在 MouseMove 期间被按下,作为检测用户在下一行中选择的方式 if(e.Button == System.Windows.Forms.MouseButtons.Left)

您的代码无法处理取消选择以及以不同方式进行的文本选择(键盘) 这可以通过连接到 SelectionChangedEvent 来检测选择来改进。 从键盘启动上下文菜单也是如此。

要处理这两种情况,您可以:

引入两个字段:

bool _isTextSelected = false;
bool _isInSelectedText = false;

提取代码以启用上下文菜单分离方法

    private void EnableContextMenu()
    {
        for (int i = 0; i < contextMenu.MenuItems.Count; i++)
        {
            if (_isInSelectedText == true && _isTextSelected)
            {
                contextMenu.MenuItems[i].Enabled = true;
            }
            else
            {
                contextMenu.MenuItems[i].Enabled = false;
            }

        }
    }

当这两个状态中的任何一个发生变化时调用此方法

private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
    _isTextSelected = richTextBox1.SelectedText != "";
    EnableContextMenu();
}

private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
{
    int positionToSearch = richTextBox1.GetCharIndexFromPosition(e.Location);
    _isInSelectedText = positionToSearch >= richTextBox1.SelectionStart && positionToSearch < richTextBox1.SelectionStart + richTextBox1.SelectionLength;
    EnableContextMenu();
}