Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I implement a TextBox that displays "Type here"?

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.

like image 644
mafu Avatar asked Mar 21 '10 12:03

mafu


People also ask

How do I set text to TextBox?

Step 1: Create a windows form. Step 2: Drag the TextBox control from the ToolBox and Drop it on the windows form. You can place TextBox anywhere on the windows form according to your need. Step 3: After drag and drop you will go to the properties of the TextBox control to set the Text property of the TextBox.

How do I use text boxes in Visual Studio?

To add a button and a text box Verify that the document is open in the Visual Studio designer. From the Common Controls tab of the Toolbox, drag a TextBox control to the document. In Word, controls are dropped in-line with text by default.


3 Answers

Something that has worked for me:

this.waterMarkActive = true; this.textBox.ForeColor = Color.Gray; this.textBox.Text = "Type here";  this.textBox.GotFocus += (source, e) =>   {     if (this.waterMarkActive)     {       this.waterMarkActive = false;       this.textBox.Text = "";       this.textBox.ForeColor = Color.Black;     }   };  this.textBox.LostFocus += (source, e) =>   {     if (!this.waterMarkActive && string.IsNullOrEmpty(this.textBox.Text))     {       this.waterMarkActive = true;       this.textBox.Text = "Type here";       this.textBox.ForeColor = Color.Gray;     }   }; 

Where bool waterMarkActive is a class member variable and textBox is the TextBox. This probably should be encapsulated though :) There might be some issues with this approach, but I'm not currently aware of any.

I recently discovered that Windows support water marks in text boxes; they are called cue banners (see here). It's very easy to implement:

// Within your class or scoped in a more appropriate location: [DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);  // In your constructor or somewhere more suitable: SendMessage(textBox.Handle, 0x1501, 1, "Please type here."); 

Where textBox is an instance of TextBox, 0x1501 is the code for the windows message EM_SETCUEBANNER, the wParam may either be TRUE (non-zero) or FALSE (zero), and lParam is the water mark you'd like to display. wParam indicates when the cue banner should be displayed; if set to TRUE then the cue banner will be displayed even when the control has focus.

like image 67
Pooven Avatar answered Sep 24 '22 17:09

Pooven


What you're looking for is a TextBox with a "watermark".

There's a sample implementation for C# here, all credits to Wael Alghool.

The relevant part of his code is:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing;  namespace wmgCMS {     class WaterMarkTextBox : TextBox     {         private Font oldFont = null;         private Boolean waterMarkTextEnabled = false;          #region Attributes              private Color _waterMarkColor = Color.Gray;             public Color WaterMarkColor             {                 get { return _waterMarkColor; }                 set { _waterMarkColor = value; Invalidate();/*thanks to Bernhard Elbl                                                               for Invalidate()*/ }             }              private string _waterMarkText = "Water Mark";             public string WaterMarkText             {                 get { return _waterMarkText; }                 set { _waterMarkText = value; Invalidate(); }             }         #endregion          //Default constructor         public WaterMarkTextBox()         {             JoinEvents(true);         }          //Override OnCreateControl ... thanks to  "lpgray .. codeproject guy"         protected override void OnCreateControl()          {              base.OnCreateControl();             WaterMark_Toggel(null, null);          }          //Override OnPaint         protected override void OnPaint(PaintEventArgs args)         {             // Use the same font that was defined in base class             System.Drawing.Font drawFont = new System.Drawing.Font(Font.FontFamily,                 Font.Size, Font.Style, Font.Unit);             //Create new brush with gray color or              SolidBrush drawBrush = new SolidBrush(WaterMarkColor);//use Water mark color             //Draw Text or WaterMark             args.Graphics.DrawString((waterMarkTextEnabled ? WaterMarkText : Text),                 drawFont, drawBrush, new PointF(0.0F, 0.0F));             base.OnPaint(args);         }          private void JoinEvents(Boolean join)         {             if (join)             {                 this.TextChanged += new System.EventHandler(this.WaterMark_Toggel);                 this.LostFocus += new System.EventHandler(this.WaterMark_Toggel);                 this.FontChanged += new System.EventHandler(this.WaterMark_FontChanged);                 //No one of the above events will start immeddiatlly                  //TextBox control still in constructing, so,                 //Font object (for example) couldn't be catched from within                 //WaterMark_Toggle                 //So, call WaterMark_Toggel through OnCreateControl after TextBox                 //is totally created                 //No doupt, it will be only one time call                  //Old solution uses Timer.Tick event to check Create property             }         }          private void WaterMark_Toggel(object sender, EventArgs args )         {             if (this.Text.Length <= 0)                 EnableWaterMark();             else                 DisbaleWaterMark();         }          private void EnableWaterMark()         {             //Save current font until returning the UserPaint style to false (NOTE:             //It is a try and error advice)             oldFont = new System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style,                Font.Unit);             //Enable OnPaint event handler             this.SetStyle(ControlStyles.UserPaint, true);             this.waterMarkTextEnabled = true;             //Triger OnPaint immediatly             Refresh();         }          private void DisbaleWaterMark()         {             //Disbale OnPaint event handler             this.waterMarkTextEnabled = false;             this.SetStyle(ControlStyles.UserPaint, false);             //Return back oldFont if existed             if(oldFont != null)                 this.Font = new System.Drawing.Font(oldFont.FontFamily, oldFont.Size,                     oldFont.Style, oldFont.Unit);         }          private void WaterMark_FontChanged(object sender, EventArgs args)         {             if (waterMarkTextEnabled)             {                 oldFont = new System.Drawing.Font(Font.FontFamily,Font.Size,Font.Style,                     Font.Unit);                 Refresh();             }         }     } } 
like image 32
Marcos Placona Avatar answered Sep 20 '22 17:09

Marcos Placona


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();
    }

}
like image 42
Joel Avatar answered Sep 23 '22 17:09

Joel