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