TextBox 中的真实提示 Visual Studio C#

Real Hint in TextBox Visual Studio C#

我目前正在使用 C# 在 Visual Studio 上制作 Windows 表单应用程序,我正在尝试找到一种方法来获得真正的 提示 .

我在网上找到了很多关于如何在那里预设一些文本的答案,一些示例甚至显示了如何将文本变灰以看起来像占位符,但这不是我要找的。

我想要一个灰色的文本,您无需退格即可在其中键入内容。所以我希望它表现得像一个 HTML 占位符 就像堆栈溢出上的 "Search Q&A" 搜索栏。

有没有简单的方法可以做到这一点,比如在 Visual Studio 上的设计器中配置文本框的 属性?

您是否尝试过在文本框上重叠标签?

在文本框按键事件中,您可以检查 textbox.text 的长度并设置标签。

关于按键事件..

MyLabel.Visible = String.IsNullOrEmpty(MyTextBox.Text);

当然,您可能希望设置标签的默认文本并将其变灰。

问题在于您的表单是否可以调整大小。

您想要实现的不是 windows 表单的原生内容。

这个呢

    private bool hasTextBeenTyped;

    private void Form1_Load(object sender, EventArgs e)
    {
        this.ActiveControl = label1;
        textBox1.ForeColor = Color.LightGray;
    }

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        hasTextBeenTyped = !String.IsNullOrEmpty(textBox1.Text);

        if (hasTextBeenTyped)
        {
            textBox1.ForeColor = Color.Black;
        }
    }

    private void textBox1_Click(object sender, EventArgs e)
    {
        if (!hasTextBeenTyped)
        {
            textBox1.Text = "";
        }
    }

    private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        hasTextBeenTyped = true;
    }

this.ActiveControl = label1;最初只是为了将焦点从文本框上移开。如果其他东西已经做了,不用担心那一行。

请看一下我的ControlHintManager class, ControlHintInfo type and ControlHintType枚举。它们是用 Vb.Net 编写的,但您可以通过分析源代码获得想法,或编译库以在您的 C# 项目中使用它,而无需任何更多努力。

我的解决方案比您提到的 Whosebugs 提示具有更好的行为,考虑到当控件离开焦点时,如果字符串为空,则应恢复提示文本。

用法非常友好:

ControlHintInfo hint1 = 
    new ControlHintInfo("I'm a hint text.", font (or nul), Color.Gray, 
                        ControlHintType.Persistent);

ControlHintManager.SetHint(TextBox1, hint1);

要自己实现,一种方法是使用 EM_SETCUEBANNER 消息调用 Win32 SendMessage 函数,但是,这会产生过于基本的提示,行为不佳,不推荐,

因此,实现此目的的正确方法是自己控制编辑控件文本,处理 Control.HandleCreatedControl.EnterControl.LeaveControl.MouseDown , Control.KeyDownControl.Disposed 事件(如您在我的链接源代码中所见)。

只需使用一个对象来跟踪控件的状态(前景色、文本和可选的字体),然后适当地使用提到的事件处理程序来设置或恢复文本和颜色。

这是链接 url 最重要代码的在线 C# 翻译,如果这有助于您更好地理解它:

private static void Control_HandleCreated(object sender, EventArgs e) {

    InstanceControlHintFields();

    Control ctrl = (Control)sender;
    ControlHintInfo hintInfo = controlHintsB(ctrl);

    SetProperties(ctrl, hintInfo);
}

private static void Control_Enter(object sender, EventArgs e) {

    InstanceControlHintFields();

    Control ctrl = (Control)sender;
    string ctrlText = ctrl.Text;
    ControlHintInfo ctrlDefaults = controlHintsDefaults(ctrl);
    ControlHintInfo hintInfo = controlHintsB(ctrl);

    switch (hintInfo.HintType) {

        case ControlHintType.Normal:
            if ((ctrlText.Equals(hintInfo.Text, StringComparison.OrdinalIgnoreCase))) {
                RestoreProperties(ctrl, ctrlDefaults);
            }

            break;
    }
}

private static void Control_Leave(object sender, EventArgs e) {

    InstanceControlHintFields();

    Control ctrl = (Control)sender;
    string ctrlText = ctrl.Text;
    ControlHintInfo ctrlDefaults = controlHintsDefaults(ctrl);
    ControlHintInfo hintInfo = controlHintsB(ctrl);

    switch (hintInfo.HintType) {

        case ControlHintType.Normal:
            if ((ctrlText.Equals(hintInfo.Text, StringComparison.OrdinalIgnoreCase))) {
                RestoreProperties(ctrl, ctrlDefaults);

            } else if (string.IsNullOrEmpty(ctrlText)) {
                SetProperties(ctrl, hintInfo);

            }

            break;
        case ControlHintType.Persistent:
            if (string.IsNullOrEmpty(ctrlText)) {
                SetProperties(ctrl, hintInfo);
            }

            break;
    }
}

private static void Control_MouseDown(object sender, MouseEventArgs e) {

    InstanceControlHintFields();

    Control ctrl = (Control)sender;
    string ctrlText = ctrl.Text;
    ControlHintInfo hintInfo = controlHintsB(ctrl);

    switch (hintInfo.HintType) {

        case ControlHintType.Persistent:


            if ((ctrlText.Equals(hintInfo.Text, StringComparison.OrdinalIgnoreCase))) {
                // Get the 'Select' control's method (if exist).
                MethodInfo method = sender.GetType.GetMethod("Select", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, {
                    typeof(int),
                    typeof(int)
                }, null);

                if ((method != null)) {
                    // Select the zero length.
                    method.Invoke(ctrl, new object[] {
                        0,
                        0
                    });
                }

            }

            break;
    }
}

private static void Control_KeyDown(object sender, KeyEventArgs e) {

    Control ctrl = (Control)sender;
    string ctrlText = ctrl.Text;
    ControlHintInfo ctrlDefaults = controlHintsDefaults(ctrl);
    ControlHintInfo hintInfo = controlHintsB(ctrl);

    switch (hintInfo.HintType) {

        case ControlHintType.Persistent:
            if ((ctrlText.Equals(hintInfo.Text, StringComparison.OrdinalIgnoreCase))) {
                RestoreProperties(ctrl, ctrlDefaults);

            } else if (string.IsNullOrEmpty(ctrlText)) {
                RestoreProperties(ctrl, ctrlDefaults, skipProperties: { "Text" });

            }

            break;
        case ControlHintType.Normal:
            if (string.IsNullOrEmpty(ctrlText)) {
                RestoreProperties(ctrl, ctrlDefaults);
            }

            break;
    }
}

private static void Control_Disposed(object sender, EventArgs e) {
    RemoveHint((Control)sender);
}

PS:基于Reflection,支持更多种类的控件。

这可能是最丑陋的代码,但我认为您可以改进它。

下面的 class 只是标准 TextBox

的扩展
 class PHTextBox : System.Windows.Forms.TextBox
    {
        System.Drawing.Color DefaultColor; 
        public string PlaceHolderText {get;set;}
        public PHTextBox(string placeholdertext)
        {
            // get default color of text
           DefaultColor = this.ForeColor;
            // Add event handler for when the control gets focus
            this.GotFocus += (object sender, EventArgs e) => 
            {
                this.Text = String.Empty;
                this.ForeColor = DefaultColor;
            };

            // add event handling when focus is lost
            this.LostFocus += (Object sender, EventArgs e) => {
                if (String.IsNullOrEmpty(this.Text) || this.Text == PlaceHolderText)
                {
                    this.ForeColor = System.Drawing.Color.Gray;
                    this.Text = PlaceHolderText;
                }
                else
                {
                    this.ForeColor = DefaultColor;
                }
            };



            if (!string.IsNullOrEmpty(placeholdertext))
            {
                // change style   
                this.ForeColor = System.Drawing.Color.Gray;
                // Add text
                PlaceHolderText = placeholdertext;
                this.Text = placeholdertext;
            }



        }


    }

Copy/paste 到名为 PHTextBox.cs.

的新 cs 文件

请您的图形设计师添加一个文本框。 转到设计器并更改文本框的 instition 行,如下所示:

现在编译,但在此之前,请确保文本框不是第一个获得焦点的元素。为此添加按钮。

我知道这是一个老问题;但是我正在寻找一种方法,我发现我的答案是最佳答案 TextBox 中显示提示文本:

1) 创建一个 class .cs 文件例如调用 MyExtensions.cs 具有 命名空间 例如调用 'Extensions'.

2)TextBox中创建一个名为Init(string prompt)[=的方法53=] 获取要在 TextBox.

中显示的提示文本

3)废话不多说了,把MyExtensions.cs剩下的代码给大家(完整代码):

MyExtensions.cs

using System.Drawing;
using System.Windows.Forms;

namespace Extensions
{
   public static class MyExtensions
{

    public static void Init(this TextBox textBox, string prompt)
    {
        textBox.Text = prompt;
        bool wma = true;
        textBox.ForeColor = Color.Gray;
        textBox.GotFocus += (source, ex) =>
        {
            if (((TextBox)source).ForeColor == Color.Black)
                return;
            if (wma)
            {
                wma = false;
                textBox.Text = "";
                textBox.ForeColor = Color.Black;
            }
        };

        textBox.LostFocus += (source, ex) =>
        {
            TextBox t = ((TextBox)source);
            if (t.Text.Length == 0)
            {
                t.Text = prompt;
                t.ForeColor = Color.Gray;
                return;
            }
            if (!wma && string.IsNullOrEmpty(textBox.Text))
            {
                wma = true;
                textBox.Text = prompt;
                textBox.ForeColor = Color.Gray;
            }
        };
        textBox.TextChanged += (source, ex) =>
        {
            if (((TextBox)source).Text.Length > 0)
            {
                textBox.ForeColor = Color.Black;
            }
        };
    }

}
}

现在假设您有三个 TextBoxtbUsernametbPasswordtbConfirm:

在您的 Form_Load(object sender, EventArgs e) 方法中初始化您的三个 TextBox,使其具有适当的 Prompt Text Messages:

using Extensions;

namespace MyApp{

         public partial class Form1 : Form{

                private void Form1_Load(object sender, 
                                        EventArgs e){

                    tbUsername.Init("Type a username");
                    tbPassword.Init("Type a password");
                    tbConfirm.Init("Confirm your password");
                }
        }
}

尽情享受吧! :)