Kei*_*thS 53 .net textbox watermark winforms
任何人都可以指向一个基本的Windows窗体TextBox的良好实现,它最初会显示水印文本,当光标进入时它会消失吗?我想我可以通过创造性地使用Enter和Leave事件来创建我自己的东西,但我确信在某个地方有一个完全可用的实现.我看到了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;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:上面最终会有一些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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我可以完全集成CueProvider功能,但这很有效.
Han*_*ant 94
官方用语是"cue banner".这是另一种方法,只需继承TextBox即可完成工作.在项目中添加一个新类并粘贴下面显示的代码.编译.从工具箱顶部删除新控件并设置Cue属性.
您可以在设计器中实时预览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);
}
Run Code Online (Sandbox Code Playgroud)
g t*_*g t 31
我已经更新了@Hans Passant上面给出的答案来引入常量,使其与pinvoke.net定义保持一致,并让代码通过FxCop验证.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:更新PInvoke调用set CharSet属性,以安全方面出错.有关更多信息,请参阅pinvoke.net上的SendMessage页面.
dee*_*gee 14
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
Run Code Online (Sandbox Code Playgroud)
并且消息常量:
private const uint EM_SETCUEBANNER = 0x1501;
private const uint CB_SETCUEBANNER = 0x1703; // minimum supported client Windows Vista, minimum supported server Windows Server 2008
Run Code Online (Sandbox Code Playgroud)
而imho实现它的最佳方式是作为扩展方法.
因此,对于TextBox控件,语法将是:
MyTextBox.CueBanner(false, "Password");
Run Code Online (Sandbox Code Playgroud)
从代码:
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); ;
}
Run Code Online (Sandbox Code Playgroud)
Rez*_*aei 13
这是一个TextBox支持显示提示(或水印或提示)的实现:
MultiLine为真的提示.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);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您使用EM_SETCUEBANNER,那么将有2个问题.文本始终以系统默认颜色显示.另外,文本将不会被显示时TextBox是MultiLine.
使用绘画解决方案,您可以使用您想要的任何颜色显示文本.当控件是多行时,您还可以显示水印:
下载
您可以克隆或下载工作示例:
在 .NET Core 上使用 WinForms:
这在 .NET Core 中得到了极大的简化。您可以通过修改 TextBox 的新 PlaceholderText 属性来直接添加占位符文本。
public virtual string PlaceholderText { get; set; }
Run Code Online (Sandbox Code Playgroud)
请注意,如果您想获得彩色占位符文本,您可能仍然需要编辑前景色。当文本字段为 null 或为空时,PlaceholderText 字段可见。
| 归档时间: |
|
| 查看次数: |
31680 次 |
| 最近记录: |