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