Winforms 为什么GetCharIndexFromPosition()不';文本框的最后一个字符是否不能正确返回?
这是我的代码,这是一个简单的示例,我试图获得有关Winforms 为什么GetCharIndexFromPosition()不';文本框的最后一个字符是否不能正确返回?,winforms,textbox,Winforms,Textbox,这是我的代码,这是一个简单的示例,我试图获得有关GetCharIndexFromPosition()方法TextBox的清晰信息 在鼠标移动中,我使用文本框的当前鼠标位置获取字符索引位置,并基于它设置文本框的选择开始。因此,如果我移动鼠标,则选择开始或插入符号位置将基于鼠标移动进行设置。但是,当鼠标移动到文本末尾时,选择“开始”未设置为“最后”。它是最后的,但在它之前 例如,如果文本框包含文本“stack”,则如果鼠标位置在“k”之后,则插入符号位置应在末尾,但它显示在“c”和“k”之间GetC
GetCharIndexFromPosition()
方法TextBox
的清晰信息
在鼠标移动中,我使用文本框的当前鼠标位置获取字符索引位置,并基于它设置文本框的选择开始。因此,如果我移动鼠标,则选择开始或插入符号位置将基于鼠标移动进行设置。但是,当鼠标移动到文本末尾时,选择“开始”未设置为“最后”。它是最后的,但在它之前
例如,如果文本框包含文本“stack”,则如果鼠标位置在“k”之后,则插入符号位置应在末尾,但它显示在“c”和“k”之间GetCharIndexPosition()
未正确返回最后一个字符的值。让我知道这个问题的解决方案
提前谢谢
问候,
Venkatesan R这是一种已知的记录行为。
GetCharIndexFromPosition
方法的备注部分包含以下重要的注释:
如果指定的位置不在控件的客户端矩形内,或超出控件中的最后一个字符,则返回值为最后一个字符的索引
解决方法是使用反向方法调整返回的索引
像这样的
public partial class Form1 : Form
{
TextBox textBox;
public Form1()
{
InitializeComponent();
textBox = new TextBox() { Height = 30, Width = 200, Text = "Syncfusion Software", Font = new Font("Arial", 11) };
textBox.MouseMove += textBox_MouseMove;
this.Controls.Add(textBox);
}
void textBox_MouseMove(object sender, MouseEventArgs e)
{
var selectionStart = textBox.GetCharIndexFromPosition(e.Location);
textBox.SelectionStart = selectionStart;
textBox.SelectionLength = 0;
}
}
p.S.顺便说一句,我不知道这个方法想要实现什么,但可以肯定的是,它阻止了通过鼠标行为进行标准文本选择。这让我非常困扰,因此,我将伊万·斯托夫的想法扩展到一种设计过度的方法,该方法计算最后一个字符的像素宽度,并将其除以二,以准确模拟其他字符的相同行为 该方法是为拖放场景编写的,在拖放场景中,将鼠标悬停在鼠标上方时,将选择调整为拖放位置
void textBox_MouseMove(object sender, MouseEventArgs e)
{
var charIndex = textBox.GetCharIndexFromPosition(e.Location);
var charPosition = textBox.GetPositionFromCharIndex(charIndex);
if (e.Location.X > charPosition.X) charIndex++;
textBox.Select(charIndex, 0);
}
当然,如果更改文本框的字体或字体大小,则必须将\u textBoxLastChar
重置回'\0'
// Cached, so it doesn't get recalculated on each moved pixel.
private Char _textBoxLastChar = '\0';
private Int32 _textBoxLastCharHalfWidth = 0;
private void TextBox_DragOver(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(DataFormats.UnicodeText))
return;
TextBox tb = sender as TextBox;
if (tb == null)
return;
Int32 textLen = tb.Text.Length;
if (textLen > 0 && _textBoxLastChar != tb.Text[textLen - 1])
{
_textBoxLastChar = tb.Text[textLen - 1];
_textBoxLastCharHalfWidth = (Int32)Math.Round(GetStringWidth(_textBoxLastChar.ToString(), tb.Font) / 2);
}
Point localPoint = tb.PointToClient(new Point(e.X, e.Y));
Int32 index = tb.GetCharIndexFromPosition(localPoint);
// fix for fact it returns the last char position when you go outside text bounds.
Int32 charPosition = tb.GetPositionFromCharIndex(index).X;
if (textLen != 0 && index == textLen - 1 && localPoint.X > charPosition + _textBoxLastCharHalfWidth)
index++;
if (!tb.Focused)
tb.Focus();
tb.SelectionStart = index;
tb.SelectionLength = 0;
}
public static Double GetStringWidth(String text, Font f)
{
//create a bmp / graphic to use MeasureString on
Single areaSize = f.Size * 20;
using (Bitmap b = new Bitmap(1, 1))
using (Graphics g = Graphics.FromImage(b))
{
SizeF sizeOfString = g.MeasureString(text, f, new SizeF(areaSize, areaSize), StringFormat.GenericTypographic);
return sizeOfString.Width;
}
}