WinForms中的水印文本框

任何人都可以指向我一个基本的Windows窗体文本框的一个很好的实现,最初将显示光标进入时消失的水印文本? 我想我可以创build自己的一些创造性的使用进入和离开事件,但我相信有一个完全可用的实现坐在某处。 我看到了WPF的实现,如果有必要,我可以嵌套它,但本地的WinForms TextBox衍生物会更好。

我到目前为止, 还没有尝试过,但没有人看到任何明显的问题?

public class WatermarkTextBox:TextBox { public string WatermarkText { get; set; } public Color WatermarkColor { get; set; } private Color TextColor { get; set; } private bool isInTransition; public WatermarkTextBox() { WatermarkColor = SystemColors.GrayText; } private bool HasText { get { return Text.IsNotNullOrBlankOr(WatermarkText); }} protected override void OnEnter(EventArgs e) { base.OnEnter(e); if (HasText) return; isInTransition = true; ForeColor = TextColor; Text = String.Empty; isInTransition = false; } protected override void OnForeColorChanged(EventArgs e) { base.OnForeColorChanged(e); if (!isInTransition) //the change came from outside TextColor = ForeColor; } protected override void OnLeave(EventArgs e) { base.OnLeave(e); if (HasText) return; isInTransition = true; ForeColor = WatermarkColor; Text = WatermarkText.EmptyIfNull(); isInTransition = false; } } 

编辑:上面将最终与一些finessing工作,但CueProvider工作得更好。 这是我最后的实现:

 public class WatermarkTextBox:TextBox { private string watermarkText; public string WatermarkText { get { return watermarkText; } set { watermarkText = value; if (watermarkText.IsNullOrBlank()) CueProvider.ClearCue(this); else CueProvider.SetCue(this, watermarkText); } } } 

我可以完全集成CueProvider的function,但是这个工作很好。

官方称号是“提示横幅”。 这是另一种方法,只是inheritanceTextBox也可以完成工作。 为您的项目添加一个新类,并粘贴下面显示的代码。 编译。 从工具箱的顶部放下新的控件并设置Cue属性。

您可以在devise器中获得Cue值的实时预览,并将其本地化为表单的Language属性。 非常小的压力,很好的演示Winforms的良好部分。

 using System; using System.ComponentModel; using System.Windows.Forms; using System.Runtime.InteropServices; class CueTextBox : TextBox { [Localizable(true)] public string Cue { get { return mCue; } set { mCue = value; updateCue(); } } private void updateCue() { if (this.IsHandleCreated && mCue != null) { SendMessage(this.Handle, 0x1501, (IntPtr)1, mCue); } } protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); updateCue(); } private string mCue; // PInvoke [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, string lp); } 

我已经更新了上面的@Hans Passant给出的答案,以引入常量,使其与pinvoke.net定义保持一致,并让代码通过FxCopvalidation。

 class CueTextBox : TextBox { private static class NativeMethods { private const uint ECM_FIRST = 0x1500; internal const uint EM_SETCUEBANNER = ECM_FIRST + 1; [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, string lParam); } private string _cue; public string Cue { get { return _cue; } set { _cue = value; UpdateCue(); } } private void UpdateCue() { if (IsHandleCreated && _cue != null) { NativeMethods.SendMessage(Handle, NativeMethods.EM_SETCUEBANNER, (IntPtr)1, _cue); } } protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); UpdateCue(); } } 

编辑:更新PInvoke调用来设置CharSet属性,以确保安全。 欲了解更多信息,请参阅pinvoke.net的SendMessage页面。

 [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam); 

和消息常量:

 private const uint EM_SETCUEBANNER = 0x1501; private const uint CB_SETCUEBANNER = 0x1703; // minimum supported client Windows Vista, minimum supported server Windows Server 2008 

而imho实现它的最好方法是作为扩展方法。
所以对于TextBox控件来说,语法是:

 MyTextBox.CueBanner(false, "Password"); 

从代码:

 public static void CueBanner(this TextBox textbox, bool showcuewhenfocus, string cuetext) { uint BOOL = 0; if (showcuewhenfocus == true) { BOOL = 1; } SendMessage(textbox.Handle, EM_SETCUEBANNER, (IntPtr)BOOL, cuetext); ; } 

这里是一个TextBox的实现,它支持显示提示(或水印或提示):

  • 它还显示MultiLine为true时的提示。
  • 它基于处理WM_PAINT消息并绘制提示。 因此,您可以简单地自定义提示并添加一些属性(如提示颜色),或者可以从右向左绘制或控制何时显示提示。
 using System.Drawing; using System.Windows.Forms; public class ExTextBox : TextBox { string hint; public string Hint { get { return hint; } set { hint = value; this.Invalidate(); } } protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg == 0xf) { if (!this.Focused && string.IsNullOrEmpty(this.Text) && !string.IsNullOrEmpty(this.Hint)) { using (var g = this.CreateGraphics()) { TextRenderer.DrawText(g, this.Hint, this.Font, this.ClientRectangle, SystemColors.GrayText , this.BackColor, TextFormatFlags.Top | TextFormatFlags.Left); } } } } } 
 Private Sub randomSubName() Handles txtWatermark.Click txtWatermark.text = "" End Sub 

使文本框的默认文本,无论你想要的水印,我假设在这个例子中,你的文本框名称txtWatermark

嘿,我是新的。 所以很抱歉,如果我非常糟糕的post…我也不知道这是否工作…