单击文本框时,如何使其聚焦但不更改其内部的光标位置

本文关键字:内部 位置 光标 文本 聚焦 何使其 单击 | 更新日期: 2023-09-27 18:28:58

我为Textbox.Enter event创建了一个事件处理程序,它选择文本框中的一部分文本,如下所示:
TextBox1.Select(3,5);

结果如下:

当通过[Tab][Shift]-[Tab]通过键盘输入文本框时,
文本中需要选择的部分选择得很好,就像上面的屏幕截图一样。

但是,如果不是通过键盘而是通过鼠标输入文本框,
则不选择任何内容:

看起来发生的事情是这样的:

当我们用鼠标输入文本框时,
单击确实会引发Enter event,但mouseclick也会将光标的位置设置为用户在文本框内用鼠标单击的位置
光标的此设置发生在事件处理程序运行之后。

因此,这意味着,事件处理程序执行的选择(使用TextBox1.Select(3,5);行)将被鼠标的位置覆盖,
这就是为什么用鼠标输入文本框似乎没有选择任何内容。

我的问题:

如何使鼠标确实升高Enter event,但不更改文本框内的光标位置
因此,我将能够保留我的选择(发生在代码中),而不会被覆盖。。

编辑:
这样做的目的是便于选择MM:SS时间部分,该部分通常是正在编辑的部分(HH或mmm部分很少更改)。

单击文本框时,如何使其聚焦但不更改其内部的光标位置

这是一个有点奇怪的请求,但如果你真的想这样做,你可以使用一种众所周知的通用方法,通过使用Control.BeginVoke方法来安排稍后执行的操作(在正常的windows消息/事件处理之后)。

像这样的

void textBox_Enter(object sender, EventArgs e)
{
    BeginInvoke(new Action(() => textBox.Select(3, 5)));
}

更新:根据您的评论,如果您想防止默认的鼠标按下行为,您需要通过创建和使用您自己的TextBox子类(如)来处理WM_MOUSEACTIVATE消息

class MyTextBox : TextBox
{
    protected override void WndProc(ref Message m)
    {
        const int WM_LBUTTONDOWN = 0x0201;
        const int WM_MOUSEACTIVATE = 0x0021;
        const int MA_ACTIVATEANDEAT = 2;
        const int MA_NOACTIVATEANDEAT = 4;
        if (m.Msg == WM_MOUSEACTIVATE && !Focused)
        {
            int mouseMsg = unchecked((int)((uint)(int)m.LParam >> 16)); // LOWORD(m.LParam)
            if (mouseMsg == WM_LBUTTONDOWN)
            {
                bool activated = Focus();
                m.Result = (IntPtr)(activated ? MA_ACTIVATEANDEAT : MA_NOACTIVATEANDEAT);
                return;
            }
        }
        base.WndProc(ref m);
    }
}

我想建议另一种方法:

Control.Enter事件处理程序的开头,我放置了以下内容:

while( (Control.MouseButtons&MouseButtons.Left)!=0 )
    Application.DoEvents();

这只是等待释放鼠标左键。。

只有当鼠标左键释放时,我们才能继续下一行代码,即

TextBox1.Select(3,5);

然后它工作得很好——选择发生,而不会被覆盖。