简体   繁体   English

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

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

The contextmenu will show in any case but the menu should be enable only if the mouse is on the selected text and not anywhere in the richTextBox area. 在任何情况下都将显示上下文菜单,但仅当鼠标位于所选文本上而不位于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;
                    }
                }
            }
        }

This enable the menuitems only when a text was selected. 仅当选择了文本时,这才启用菜单项。 Now i want to add another condition that also if the mouse position is on the selected text then enable true. 现在,我想添加另一个条件,即如果鼠标位置位于所选文本上,则启用true。

If not enable false. 如果未启用,则为false。 So there should be two conditions one if text selected and second if the mouse is on any part of the selected text. 因此,应该有两个条件,一个是如果选择了文本,第二个是如果鼠标位于所选文本的任何部分。 Not sure yet how to make the second condition. 尚不确定如何使第二个条件。

Update 更新资料

What i tried now: 我现在尝试的是:

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

But when i make right click on the selected text it will enable the menu but then if i make right click in other places in the richtextbox area the menu will be still enabled and i want it to be enabled only on the selected text. 但是,当我右键单击所选文本时,它将启用菜单,但是如果我右键单击Richtextbox区域中的其他位置,则菜单仍将启用,并且我希望仅在所选文本上启用它。

And if no selected text at all enable false the menu. 如果根本没有选中的文本,则使菜单为假。

I'm adding the context menu once in the form load event: 我在表单加载事件中添加一次上下文菜单:

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

Here's my take on it. 这是我的看法。 In this sample I'm not opening a context menu, instead I am appending to the RichTextBox when the mouse is clicked in the proper position. 在此示例中,我没有打开上下文菜单,而是在适当位置单击鼠标时将其附加到RichTextBox。

This snippet needs a bit of work to be production worthy, especially around defining the "fudgeFactored" area but, the premise is there. 该片段需要进行一些工作才能使产品有价值,尤其是在定义“ fudgeFactored”区域周围,但是前提是在那里。 In the code below I'm only caring about the starting position of the text selection, though if I was to make this a production script, I'd look at where it starts, where it ends, and then I would add the fudgeFactor to it. 在下面的代码中,我只关心文本选择的起始位置,尽管如果要将此文本用作生产脚本,我会看看它的起始位置,结束位置,然后将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);
            }
        }
    }
}

You can use the richTextBox.GetCharIndexFromPosition function to get the index(position in the richTextBox text) of the character closest to the checked point. 您可以使用richTextBox.GetCharIndexFromPosition函数来获取最接近选中点的字符的索引(在richTextBox文本中的位置)。 Then simply verify if this index is between the start and end of the selection 然后只需验证此索引是否在选择的开始和结束之间

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

Since you are checking if the Left button is pressed during MouseMove as a way of detecting user selection in the following line if(e.Button == System.Windows.Forms.MouseButtons.Left) 由于您正在检查在MouseMove期间是否按下了向左按钮,以此作为检测用户选择下一行if(e.Button == System.Windows.Forms.MouseButtons.Left)

Your code does not handle unselection as well as text selection made in different ways (Keyboard) This can be improved by hooking up to the SelectionChangedEvent to detect selection. 您的代码无法处理取消选择以及以不同方式进行的文本选择(键盘),这可以通过连接到SelectionChangedEvent来检测选择得到改善。 The same could be said about starting the context menu from the keyboard. 从键盘启动上下文菜单也可以这样说。

To handle both cases you could: 要处理这两种情况,您可以:

Introduce two fields: 介绍两个字段:

bool _isTextSelected = false;
bool _isInSelectedText = false;

Extract the code to enable the context menu to separate method 提取代码以使上下文菜单能够分离方法

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

        }
    }

Call this method when any of these two states changes 当这两个状态中的任何一个发生更改时,请调用此方法

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM