4

Is it possible to create a textbox in Visual Studio like this:

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
gjjansen97
  • 99
  • 1
  • 3
  • 9

2 Answers2

17

Actually. A better solution will be simply use the Paint event of the text box to draw the string.

Here's the code:

class CueTextBox : TextBox
{
    public event EventHandler CueTextChanged;
    private string _cueText;

    public string CueText
    {
        get { return _cueText; }
        set
        {
            value = value ?? string.Empty;
            if (value != _cueText)
            {
                _cueText = value;
                OnCueTextChanged(EventArgs.Empty);
            }
        }
    }

    public CueTextBox()
        : base()
    {
        _cueText = string.Empty;
    }

    protected virtual void OnCueTextChanged(EventArgs e)
    {
        this.Invalidate(true);
        if (this.CueTextChanged != null)
            this.CueTextChanged(this, e);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        if (string.IsNullOrEmpty(this.Text.Trim()) && !string.IsNullOrEmpty(this.CueText) && !this.Focused)
        {
            Point startingPoint = new Point(0, 0);
            StringFormat format = new StringFormat();
            Font font = new Font(this.Font.FontFamily.Name, this.Font.Size, FontStyle.Italic);
            if (this.RightToLeft == RightToLeft.Yes)
            {
                format.LineAlignment = StringAlignment.Far;
                format.FormatFlags = StringFormatFlags.DirectionRightToLeft;
            }
            e.Graphics.DrawString(CueText, font, Brushes.Gray, this.ClientRectangle, format);
        }
    }

    const int WM_PAINT = 0x000F;
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == WM_PAINT)
        {
            this.OnPaint(new PaintEventArgs(Graphics.FromHwnd(m.HWnd), this.ClientRectangle));
        }
    }
}

Now, all you need is the set the 'CueText' property to the initial value you want and you're done!

Nissim
  • 6,395
  • 5
  • 49
  • 74
  • 1
    Good tip but little complex for the newbie :) – DayTimeCoder Feb 13 '12 at 20:46
  • 1
    This way you don't modify the 'Text' property of the textbox, which could lead to unexpected results. On my solution the text is only painted over the textbox area, and you can use the Text property without any worries – Nissim Jun 26 '12 at 08:27
  • 1
    I personally like your solution :) – DayTimeCoder Jun 26 '12 at 09:19
  • 2
    I like your method, although you should always call the `Dispose` method to release the Graphics and related resources created by the `FromHwnd` method. So I suggest the code `using (Graphics g = Graphics.FromHwnd(m.HWnd)) { this.OnPaint(new PaintEventArgs(g, this.ClientRectangle)); }` – Ricardo González Apr 26 '18 at 12:18
3

You would just need to handle three TextBox events, in the Designer set the text of the TextBox to "username" and make it Font Italics then set TextBox BackColor to LightYellow,the rest is handled by Event handlers...

     private void textBox1_TextChanged(object sender, EventArgs e)
    {
        if (textBox1.Text == "")
            ChangeTextBoxtoWatermark();
    }

    private void textBox1_MouseEnter(object sender, EventArgs e)
    {
        if (textBox1.Text == "username")
        {
            textBox1.Text = "";
            textBox1.Font = new Font(this.Font, FontStyle.Regular);
            textBox1.BackColor = Color.White;
        }
    }

    private void textBox1_MouseLeave(object sender, EventArgs e)
    {
        if (textBox1.Text == "")
            ChangeTextBoxtoWatermark();
    }

    private void ChangeTextBoxtoWatermark()
    {
        textBox1.Font = new Font(this.Font, FontStyle.Italic);
        textBox1.BackColor = Color.LightYellow;
        textBox1.Text = "username";
    }

I have checked it and it works fine :)

DayTimeCoder
  • 4,294
  • 5
  • 38
  • 61