仅当鼠标位置位于 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();
}
上下文菜单将在任何情况下显示,但仅当鼠标位于所选文本上而不是 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();
}