winforms 为什么在显示窗体时文本框中的文本突出显示(选中)?

vi4fp9gy  于 2023-02-24  发布在  其他
关注(0)|答案(7)|浏览(160)

我在C#中有一个包含TextBox的表单,我将其设置为字符串,如下所示:

textBox.Text = str;

当窗体显示时,为什么文本框中的文本显示为高亮显示/选中?

ddhy6vgd

ddhy6vgd1#

文本框的TabIndex为0,TabStop设置为true。这意味着显示窗体时将为控件提供焦点。
您可以为另一个控件指定0 TabIndex(如果有),并为文本框指定一个不同的制表符索引(〉0),或者将文本框的TabStop设置为false以阻止这种情况发生。

6mzjoqzu

6mzjoqzu2#

Windows窗体中TextBox的默认行为是,如果文本框通过Tab键第一次获得焦点,则突出显示所有文本,但如果文本框被单击,则不会突出显示所有文本。我们可以通过查看TextBoxOnGotFocus()重写在Reflector中看到这一点:

protected override void OnGotFocus(EventArgs e)
{
    base.OnGotFocus(e);
    if (!this.selectionSet)
    {
        this.selectionSet = true;
        if ((this.SelectionLength == 0) && (Control.MouseButtons == MouseButtons.None))
        {
            base.SelectAll();
        }
    }
}

正是if语句导致了我们不喜欢的行为,而且,雪上加霜的是,每当文本被重新赋值时,Text属性的setter就会盲目地重置selectionSet变量:

public override string Text
{
    get
    {
        return base.Text;
    }
    set
    {
        base.Text = value;
        this.selectionSet = false;
    }
}

因此,如果你有一个TextBox并按Tab键进入它,那么所有的文本都会被选中;如果你点击它,高亮显示会被移除,如果你重新按Tab键进入它,你的插入符号位置(和选择长度为零)会被保留;但是如果我们以编程方式设置new Text,并再次按Tab键进入TextBox,那么所有的文本都会再次被选中。
如果你和我一样,觉得这种行为令人讨厌且前后矛盾,那么有两种方法可以绕过这个问题。
第一种方法,也可能是最简单的方法,就是通过调用表单Load()上的DeselectAll(),在Text发生变化时触发selectionSet的设置:

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    this.textBox2.SelectionStart = this.textBox2.Text.Length;
    this.textBox2.DeselectAll();
}

DeselectAll()只是将SelectionLength设置为0。实际上是SelectionStart翻转了TextBoxselectionSet变量。在上面的例子中,调用DeselectAll()是不必要的,因为我们将开始设置为文本的结尾。但是如果我们将它设置为任何其他位置,比如文本的开始,那么调用它是一个好主意。)
更持久的方法是通过继承创建我们自己的具有所需行为的TextBox:

public class NonSelectingTextBox : TextBox
{
    // Base class has a selectionSet property, but its private.
    // We need to shadow with our own variable. If true, this means
    // "don't mess with the selection, the user did it."
    private bool selectionSet;

    protected override void OnGotFocus(EventArgs e)
    {
        bool needToDeselect = false;

        // We don't want to avoid calling the base implementation
        // completely. We mirror the logic that we are trying to avoid;
        // if the base implementation will select all of the text, we
        // set a boolean.
        if (!this.selectionSet)
        {
            this.selectionSet = true;

            if ((this.SelectionLength == 0) && 
                (Control.MouseButtons == MouseButtons.None))
            {
                needToDeselect = true;
            }
        }

        // Call the base implementation
        base.OnGotFocus(e);

        // Did we notice that the text was selected automatically? Let's
        // de-select it and put the caret at the end.
        if (needToDeselect)
        {
            this.SelectionStart = this.Text.Length;
            this.DeselectAll();
        }
    }

    public override string Text
    {
        get
        {
            return base.Text;
        }
        set
        {
            base.Text = value;

            // Update our copy of the variable since the
            // base implementation will have flipped its back.
            this.selectionSet = false;
        }
    }
}

你可能不想调用base.OnGotFocus(),但是那样我们就会失去Control基类中有用的功能;你可能不想去搞那些毫无意义的selectionSet,而只是每次在OnGotFocus()中取消选择文本,但是如果用户跳离字段并返回,我们就会失去用户的高亮显示。
丑陋?你猜对了。但事实就是如此。

goucqfw6

goucqfw63#

这个问题的答案帮助了我很多类似的问题,但简单的答案只是暗示了很多其他复杂的建议。只需设置文本后将SelectionStart设置为0。问题解决了!
示例:

yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
nnt7mjpx

nnt7mjpx4#

您还可以通过打开以下窗口来选择窗体控件的Tab键顺序:
查看-〉Tab键顺序

  • 请注意,只有在打开窗体设计视图的情况下,此选项才在“视图”中可用。*

选择“Tab键顺序”打开表单视图,允许您通过单击控件选择所需的Tab键顺序。

kyxcudwk

kyxcudwk5#

在VS 2013中,要取消突出显示文本字段,请尝试使用以下命令init:

myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);

并添加方法:

public void myTextBox_GotFocus(object sender, EventArgs e)
{
    myTextBox.SelectionLength=0;
}
bcs8qyzn

bcs8qyzn6#

我还没有在C#上测试过这个问题,但是我在使用C++ WIN32对话框时遇到了同样的问题。看起来你可以通过从OnInitDialog()WM_INITDIALOG返回FALSE来改变这个行为。希望这能有所帮助。

8ehkhllq

8ehkhllq7#

以下是对我有效的方法

public void SetNotes(string notes)
    {
        notesTextBox.Text = notes;

        notesTextBox.Select();
        notesTextBox.SelectionLength = 0;
        notesTextBox.SelectionStart = notes.Length;//place cursor at end of text
    }

相关问题