单击文本框时,如何给它焦点但不更改其中的光标位置

时间:2016-01-03 11:33:09

标签: c# .net winforms

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

结果如下:

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

但是,如果不是通过键盘而是通过鼠标输入文本框,则 然后没有选择任何东西:

似乎会发生这样的事情:

当我们用鼠标进入文本框时,
点击确实会引发Enter event,但鼠标点击还会将光标的位置设置为文本框内用户点击鼠标的位置。
在事件处理程序运行之后,光标的这个设置就会发生

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

我的问题:

如何让鼠标确实抬起Enter event,而不是更改文本框内的光标位置?
因此,我将能够保留我的选择(在代码中发生)并且不会被覆盖..

编辑:
这样做的目的是为了能够轻松选择 MM:SS 部分时间,这通常是正在编辑的部分(HH或mmm部分很少更改)。

2 个答案:

答案 0 :(得分:2)

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

像这样的东西

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

答案 1 :(得分:1)

我想建议另一种方式:

Control.Enter事件处理程序的开头,我把它放在:

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

这只是等待鼠标左键被释放..

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

TextBox1.Select(3,5);

然后它运作良好 - 选择发生,而不被覆盖。