C# 获取winforms文本框的光标位置

C# 获取winforms文本框的光标位置,c#,.net,winforms,C#,.net,Winforms,如何获取.NET中winforms文本框的当前光标(插入符号)位置?SelectionStart仅返回所选文本的开头(选择的左侧)。表示如果光标位于选择的右侧,则此值错误 澄清:在.NET文本框中选择开始指向选择的左侧,也指插入符号位于选择的右侧。这意味着在两张图片中,选择开始为2,但插入符号位置在第一张图片中为2,在右侧图片中为7 如果要选择左侧,可以使用: int index = textBox.SelectionStart; int index = textBox.SelectionS

如何获取.NET中winforms文本框的当前光标(插入符号)位置?SelectionStart仅返回所选文本的开头(选择的左侧)。表示如果光标位于选择的右侧,则此值错误


澄清:在.NET文本框中选择开始指向选择的左侧,也指插入符号位于选择的右侧。这意味着在两张图片中,选择开始为2,但插入符号位置在第一张图片中为2,在右侧图片中为7


如果要选择左侧,可以使用:

int index = textBox.SelectionStart;
int index = textBox.SelectionStart + textBox.SelectionLength;
如果希望选择右侧,可以使用:

int index = textBox.SelectionStart;
int index = textBox.SelectionStart + textBox.SelectionLength;
如果需要知道文本选择的方向,则可以尝试跟踪鼠标下移和鼠标上移事件,并在事件触发时比较光标位置

例如:

// On mouse down event.
int mouseDownX = MousePosition.X;

// On mouse up event.
int mouseUpX = MousePosition.X;

// Check direction.
if(mouseDownX < mouseUpX)
{
    // Left to Right selection.
    int index = textBox.SelectionStart;   
}
else
{
    // Right to Left selection.
    int index = textBox.SelectionStart + textBox.SelectionLength;
}
//鼠标按下事件。
int mouseDownX=MousePosition.X;
//鼠标向上移动事件。
int mouseUpX=MousePosition.X;
//检查方向。
if(mouseDownX
如前所述,
SelectionStart
属性在选择处于活动状态的文本框中获取实际插入符号位置是不可靠的。这是因为此属性始终指向选择的开始(提示:名称不存在),并且根据您使用鼠标选择文本的方式,插入符号可以定位在选择的左侧或右侧

此代码(使用LinqPAD测试)显示了一种替代方法

public class WinApi
{
    [DllImport("user32.dll")]
    public static extern bool GetCaretPos(out System.Drawing.Point lpPoint);
}

TextBox t = new TextBox();
void Main()
{
    Form f = new Form();
    f.Controls.Add(t);
    Button b = new Button();
    b.Dock = DockStyle.Bottom;
    b.Click += onClick;
    f.Controls.Add(b);
    f.ShowDialog();
}

// Define other methods and classes here
void onClick(object sender, EventArgs e)
{
    Console.WriteLine("Start:" + t.SelectionStart + " len:" +t.SelectionLength);
    Point p = new Point();
    bool result = WinApi.GetCaretPos(out p);
    Console.WriteLine(p);
    int idx = t.GetCharIndexFromPosition(p);
    Console.WriteLine(idx);
}
API
GetCaretPos
返回插入符号所在的客户端坐标点。您可以使用托管方法
GetCharIndexFromPosition
返回位置后的字符索引。当然,您需要向
System.Runtime.InteropServices
添加一个引用和一个using


不确定此解决方案是否存在缺陷,并等待更多专家告诉我们是否存在错误或原因。

根据Steve的回答,这是我的解决方案:

[DllImport("user32")]
private extern static int GetCaretPos(out Point p);

...

// get current caret position
Point caret;
GetCaretPos(out caret);
int caretPosition = tbx.GetCharIndexFromPosition(caret);
此外(不是我问题的一部分),我能够用以下代码设置插入符号和文本选择。user32.dll中还有一个SetCaret函数,它对我不起作用。但令人惊讶的是,Select()函数支持选择长度的负值

// determine if current caret is at beginning
bool caretAtBeginning = tbx.SelectionStart == caretIndex;

...

// set text selection and caret position
if (caretAtBeginning)
    tbx.Select(selStart + selLength, -selLength);
else
    tbx.Select(selStart, selLength);

注意:此帖子摘自问题,并代表OP发布。

此帖子可能会被某些人使用:

int lastSelectionStart = 0;

int getCaretPosition()
{
    if (tbx.SelectionLength == 0)
    {
        lastSelectionStart = tbx.SelectionStart;
        return lastSelectionStart;
    }
    else
    {
        if (tbx.SelectionStart == lastSelectionStart)
        {
            return tbx.SelectionStart + tbx.SelectionLength;
        }
        else
        {
            return lastSelectionStart - tbx.SelectionLength;
        }
    }
}

您所说的“如果光标位于所选内容的右侧,则表示此值错误”的意思可能重复?
SelectionStart+SelectionLength
有帮助吗?@musefan:请阅读整个问题!SelectionStart并不能解决我的问题。对于那些(OP)不理解自己问题的人,请先阅读以下内容:当您选择文本并键入内容时会发生什么?它在选择的开始处插入,因此必须在插入符号位置处插入。无论选择哪个方向,插入符号都将位于选择的开始处What?从技术上讲,光标始终位于选定内容的左侧,这就是为什么使用SelectionLength来获取右侧位置。好的,这可能是一种解决方法。因此,我还必须跟踪键盘。如果没有更好的解决办法,我就不得不接受这个。谢谢你的想法。不幸的是,只有当文本框有焦点时,这才有效。因此,如果需要未聚焦文本框的插入符号位置,这将不起作用(除非您交换当前焦点以获得该位置,但这是一个丑陋的攻击)。