使WinForms TextBox的行为与浏览器的地址栏类似

当C#WinForms文本框收到焦点时,我希望它的行为与浏览器的地址栏类似。

要明白我的意思,请点击您的网络浏览器的地址栏。 您会注意到以下行为:

  • 如果文本框之前没有关注,则单击文本框应该选择所有文本。
  • 在文本框中鼠标向下并拖动时,应该只选择我用鼠标突出显示的文本。
  • 如果文本框已被聚焦,则单击不会选择所有文本。
  • 以编程方式或通过键盘选项卡聚焦文本框应选择全部文本。
  • 我想在WinForms中做到这一点。

    最快的警报:在回答之前请阅读以下内容! 多谢你们。 :-)

    在.Enter或.GotFocus事件期间调用.SelectAll()将不起作用,因为如果用户单击文本框,插入符号将放置在他单击的位置,从而取消选择所有文本。

    在.Click事件期间调用.SelectAll()将不起作用,因为用户将无法使用鼠标选择任何文本; .SelectAll()调用将继续覆盖用户的文本选择。

    在焦点/输入事件输入中调用BeginInvoke((Action)textbox.SelectAll)不起作用,因为它违反了上述规则#2,它将继续覆盖用户的焦点选择。


    首先,感谢您的回答! 共有9个答案。 谢谢。

    坏消息:所有的答案都有一些怪癖,或者工作不正确(或者根本就没有)。 我已为每个帖子添加了评论。

    好消息:我找到了一种使其工作的方法。 这个解决方案非常简单,似乎适用于所有场景(鼠标移动,选择文本,选项卡焦点等)

    bool alreadyFocused;
    
    ...
    
    textBox1.GotFocus += textBox1_GotFocus;
    textBox1.MouseUp += textBox1_MouseUp;
    textBox1.Leave += textBox1_Leave;
    
    ...
    
    void textBox1_Leave(object sender, EventArgs e)
    {
        alreadyFocused = false;
    }
    
    
    void textBox1_GotFocus(object sender, EventArgs e)
    {
        // Select all text only if the mouse isn't down.
        // This makes tabbing to the textbox give focus.
        if (MouseButtons == MouseButtons.None)
        {
            this.textBox1.SelectAll();
            alreadyFocused = true;
        }
    }
    
    void textBox1_MouseUp(object sender, MouseEventArgs e)
    {
        // Web browsers like Google Chrome select the text on mouse up.
        // They only do it if the textbox isn't already focused,
        // and if the user hasn't selected all text.
        if (!alreadyFocused && this.textBox1.SelectionLength == 0)
        {
            alreadyFocused = true;
            this.textBox1.SelectAll();
        }
    }
    

    据我所知,这会导致文本框的行为完全像Web浏览器的地址栏。

    希望这有助于下一个试图解决这个看似简单的问题的人。

    再次感谢,伙计们,帮助我走向正确的道路。


    我找到了一个更简单的解决方案。 它包括使用Control.BeginInvoke异步启动SelectAll,以便在Enter和Click事件发生后发生:

    在C#中:

    private void MyTextBox_Enter(object sender, EventArgs e)
    {
        // Kick off SelectAll asyncronously so that it occurs after Click
        BeginInvoke((Action)delegate
        {
            MyTextBox.SelectAll();
        });
    }
    

    在VB.NET中(感谢Krishanu Dey)

    Private Sub MyTextBox_Enter(sender As Object, e As EventArgs) Handles MyTextBox.Enter 
        BeginInvoke(DirectCast(Sub() MyTextBox.SelectAll(), Action)) 
    End Sub
    

    您的解决方案很好,但在某个特定情况下失败。 如果您通过选择文本范围而不是仅单击文本框来为文本框设置焦点,则alreadyFocussed标志不会设置为true,因此当您再次单击文本框时,所有文本都会被选中。

    这是我的解决方案版本。 我也将代码放入继承TextBox的类中,因此很好地隐藏了逻辑。

    public class MyTextBox : System.Windows.Forms.TextBox
    {
        private bool _focused;
    
        protected override void OnEnter(EventArgs e)
        {
            base.OnEnter(e);
            if (MouseButtons == MouseButtons.None)
            {
                SelectAll();
                _focused = true;
            }
        }
    
        protected override void OnLeave(EventArgs e)
        {
            base.OnLeave(e);
            _focused = false;
        }
    
        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            base.OnMouseUp(mevent);
            if (!_focused)
            {
                if (SelectionLength == 0)
                    SelectAll();
                _focused = true;
            }
        }
    }
    
    链接地址: http://www.djcxy.com/p/44921.html

    上一篇: Making a WinForms TextBox behave like your browser's address bar

    下一篇: C pointer to 'SEL' is disallowed with ARC