当C#WinForms文本框获得焦点时,我希望它的行为类似于浏览器的地址栏.
要查看我的意思,请单击您的Web浏览器的地址栏.您会注意到以下行为:
如果文本框之前没有聚焦,则单击文本框应选择所有文本.
鼠标按下并在文本框中拖动应该只选择我用鼠标突出显示的文本.
如果文本框已经聚焦,则单击不会选择所有文本.
以编程方式或通过键盘选项卡聚焦文本框应选择所有文本.
我想在WinForms中做到这一点.
最快的枪声:请在回答之前阅读以下内容!多谢你们.:-)
在.Enter或.GotFocus事件期间调用.SelectAll()将不起作用,因为如果用户单击文本框,则插入符号将被放置在他单击的位置,从而取消选择所有文本.
在.Click事件期间调用.SelectAll()将不起作用,因为用户将无法使用鼠标选择任何文本; .SelectAll()调用将继续覆盖用户的文本选择.
在焦点/输入事件输入上调用BeginInvoke((Action)textbox.SelectAll)不起作用,因为它违反了上面的规则#2,它将继续覆盖用户对焦点的选择.
Judah Gabrie.. 107
首先,谢谢你的回答!共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浏览器的地址栏完全相同.
希望这有助于下一个试图解决这个看似简单的问题的人.
再次感谢,伙计们,所有的答案都帮助我走上了正确的道路.
首先,谢谢你的回答!共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浏览器的地址栏完全相同.
希望这有助于下一个试图解决这个看似简单的问题的人.
再次感谢,伙计们,所有的答案都帮助我走上了正确的道路.
我找到了一个更简单的解决方案.它涉及使用异步启动SelectAll,Control.BeginInvoke
以便在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
您的解决方案很好,但在一个特定情况下失败.如果通过选择文本范围而不是单击来给TextBox焦点,则alreadyFocussed标志不会设置为true,因此当您再次单击TextBox时,将选中所有文本.
这是我的解决方案版本.我还将代码放入一个继承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; } } }
这有点笨拙,但在你的点击事件中,请使用SendKeys.Send( "{HOME}+{END}" );
.