Newer
Older
JumpListUtil / ShortcutUtil / WatermarkTextBox.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ShortcutUtil
{
	// https://www.codeproject.com/Articles/27849/WaterMark-TextBox-For-Desktop-Applications-Using-C

	class WatermarkTextBox : TextBox
	{
		private Font mOldFont = null;
		private Boolean mWaterMarkTextEnabled = 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();
			WaterMarkToggle(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((mWaterMarkTextEnabled ? 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.WaterMarkToggle);
				this.LostFocus += new System.EventHandler(this.WaterMarkToggle);
				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 WaterMarkToggle(object sender, EventArgs args)
		{
			if (this.Text.Length <= 0)
				EnableWaterMark();
			else
				DisableWaterMark();
		}

		private void EnableWaterMark()
		{
			//Save current font until returning the UserPaint style to false (NOTE:
			//It is a try and error advice)
			mOldFont = new System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style,
			   Font.Unit);
			//Enable OnPaint event handler
			this.SetStyle(ControlStyles.UserPaint, true);
			this.mWaterMarkTextEnabled = true;
			//Triger OnPaint immediatly
			Refresh();
		}

		private void DisableWaterMark()
		{
			//Disbale OnPaint event handler
			this.mWaterMarkTextEnabled = false;
			this.SetStyle(ControlStyles.UserPaint, false);
			//Return back oldFont if existed
			if (mOldFont != null)
				this.Font = new System.Drawing.Font(mOldFont.FontFamily, mOldFont.Size,
					mOldFont.Style, mOldFont.Unit);
		}

		private void WaterMark_FontChanged(object sender, EventArgs args)
		{
			if (mWaterMarkTextEnabled)
			{
				mOldFont = new System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style,
					Font.Unit);
				Refresh();
			}
		}
	}
}