How do I implement a TextBox that displays “Type h

2019-01-17 09:43发布

Displaying "Type here to ..." until the user enters text into a TextBox is a well-known usability feature nowadays. How would one implement this feature in C#?

My idea is to override OnTextChanged, but the logic to handle the changes of text from and to "Type here" is a bit tricky...

Displaying "Type here" on initialization and removing it on first input is easy, but I want to display the message every time the entered text becomes empty.

16条回答
Animai°情兽
2楼-- · 2019-01-17 10:20
  [DllImport("user32.dll", CharSet = CharSet.Auto)]
  private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);
  const int EM_SETCUEBANNER = 0x1501; 

  public Form1()
  {
      InitializeComponent();
      SendMessage(textBox1.Handle, EM_SETCUEBANNER, 1, "Username");
      SendMessage(textBox2.Handle, EM_SETCUEBANNER, 1, "Password");
  }
查看更多
男人必须洒脱
3楼-- · 2019-01-17 10:22

Based on answer of Ahmed Soliman Flasha use following class:

public class TextBoxHint : TextBox
{
    string _hint;

    [Localizable(true)]
    public string Hint
    {
        get { return _hint; }
        set { _hint = value; OnHintChanged(); }
    }

    protected virtual void OnHintChanged()
    {
        SendMessage(this.Handle, EM_SETCUEBANNER, 1, _hint);
    }     

    const int EM_SETCUEBANNER = 0x1501;

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);
}
查看更多
做自己的国王
4楼-- · 2019-01-17 10:23

Based on @Pooven's answer (thank you!), I created this class. Works for me.

/// <summary>
/// A textbox that supports a watermak hint.
/// </summary>
public class WatermarkTextBox : TextBox
{
    /// <summary>
    /// The text that will be presented as the watermak hint
    /// </summary>
    private string _watermarkText = "Type here";
    /// <summary>
    /// Gets or Sets the text that will be presented as the watermak hint
    /// </summary>
    public string WatermarkText
    {
        get { return _watermarkText; }
        set { _watermarkText = value; }
    }

    /// <summary>
    /// Whether watermark effect is enabled or not
    /// </summary>
    private bool _watermarkActive = true;
    /// <summary>
    /// Gets or Sets whether watermark effect is enabled or not
    /// </summary>
    public bool WatermarkActive
    {
        get { return _watermarkActive; }
        set { _watermarkActive = value; }
    }

    /// <summary>
    /// Create a new TextBox that supports watermak hint
    /// </summary>
    public WatermarkTextBox()
    {
        this._watermarkActive = true;
        this.Text = _watermarkText;
        this.ForeColor = Color.Gray;

        GotFocus += (source, e) =>
        {
            RemoveWatermak();
        };

        LostFocus += (source, e) =>
        {
            ApplyWatermark();
        };

    }

    /// <summary>
    /// Remove watermark from the textbox
    /// </summary>
    public void RemoveWatermak()
    {
        if (this._watermarkActive)
        {
            this._watermarkActive = false;
            this.Text = "";
            this.ForeColor = Color.Black;
        }
    }

    /// <summary>
    /// Applywatermak immediately
    /// </summary>
    public void ApplyWatermark()
    {
        if (!this._watermarkActive && string.IsNullOrEmpty(this.Text)
            || ForeColor == Color.Gray ) 
        {
            this._watermarkActive = true;
            this.Text = _watermarkText;
            this.ForeColor = Color.Gray;
        }
    }

    /// <summary>
    /// Apply watermak to the textbox. 
    /// </summary>
    /// <param name="newText">Text to apply</param>
    public void ApplyWatermark(string newText)
    {
        WatermarkText = newText;
        ApplyWatermark();
    }

}
查看更多
劫难
5楼-- · 2019-01-17 10:25

Why using OnTextChanged? I would suggest to remove the text "Type here" when the TextBox gets focus. When the control loses focus and no text is entered, you can display the text again.

Same result and no need for tricky logic.

查看更多
Rolldiameter
6楼-- · 2019-01-17 10:26

If you want to avoid control resizing problems and data binding problems and make the code simpler (ok, it is questionable), you can just use a label and toggle it's visibility. Then

    private void FilterComboBox_GotFocus(object sender, EventArgs e)
    {
        FilterWatermarkLabel.Visible = false;
    }

    private void FilterComboBox_LostFocus(object sender, EventArgs e)
    {
        if (!FilterWatermarkLabel.Visible && string.IsNullOrEmpty(FilterComboBox.Text))
        {
            FilterWatermarkLabel.Visible = true;
        }
    }

Another approach for images and also avoiding data binding problems is here https://msdn.microsoft.com/en-us/library/bb613590(v=vs.100).aspx

查看更多
我欲成王,谁敢阻挡
7楼-- · 2019-01-17 10:28

What you're looking for is a texbox with "watermark"

There's a sample implementation for C# here.

Hope it helps

查看更多
登录 后发表回答