我想弄清楚是否可能,以及是否有人知道如何做这个Cue Banner(Watermark) textbox的多行版本。我得到了这个工作正常的单行版本,但对于我的项目,我真的需要一个多行,在加载时框中会有一段文字,当用户点击文本消失时,只要他们在框中输入内容它保持不变但是如果它们删除了它们放在文本框中的任何内容,我的段落就会回来。我希望这是有道理的。
感谢您的回复。
答案 0 :(得分:1)
我搜索了一下,找到了一个适用于多线和单线文本框的更好的解决方案:
// Thank you author of http://nate.deepcreek.org.au/svn/tools/ComskipToCuttermaran/trunk/CSharpControls/GlassTextBox.cs
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class CueTextBox : TextBox
{
#region Fields
private Bitmap _bitmap;
private bool _paintedFirstTime = false;
const int WM_PAINT = 0x000F;
const int WM_PRINT = 0x0317;
const int PRF_CLIENT = 0x00000004;
const int PRF_ERASEBKGND = 0x00000008;
private string _cue;
#endregion
#region Properties
public string Cue
{
get { return _cue; }
set {
_cue = value;
Invalidate(true);
}
}
public new BorderStyle BorderStyle
{
get { return base.BorderStyle; }
set {
if (_paintedFirstTime)
SetStyle(ControlStyles.UserPaint, false);
base.BorderStyle = value;
if (_paintedFirstTime)
SetStyle(ControlStyles.UserPaint, true);
}
}
public override bool Multiline
{
get { return base.Multiline; }
set {
if (_paintedFirstTime)
SetStyle(ControlStyles.UserPaint, false);
base.Multiline = value;
if (_paintedFirstTime)
SetStyle(ControlStyles.UserPaint, true);
}
}
#endregion
#region Constructor
public CueTextBox()
: base()
{
SetStyle(ControlStyles.UserPaint, false);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
}
#endregion
#region Functions
[DllImport("USER32.DLL", EntryPoint = "SendMessage")]
public static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);
protected override void Dispose(bool disposing)
{
if (_bitmap != null)
_bitmap.Dispose();
base.Dispose(disposing);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_PAINT)
{
_paintedFirstTime = true;
CaptureBitmap();
SetStyle(ControlStyles.UserPaint, true);
base.WndProc(ref m);
SetStyle(ControlStyles.UserPaint, false);
return;
}
base.WndProc(ref m);
}
private void CaptureBitmap()
{
if (_bitmap != null)
_bitmap.Dispose();
_bitmap = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, PixelFormat.Format32bppArgb);
using (var graphics = Graphics.FromImage(_bitmap))
{
int lParam = PRF_CLIENT | PRF_ERASEBKGND;
System.IntPtr hdc = graphics.GetHdc();
SendMessage(this.Handle, WM_PRINT, hdc, new IntPtr(lParam));
graphics.ReleaseHdc(hdc);
}
}
protected override void OnPaint(PaintEventArgs e)
{
SetStyle(ControlStyles.UserPaint, true);
if (_bitmap == null)
e.Graphics.FillRectangle(Brushes.CornflowerBlue, ClientRectangle);
else
e.Graphics.DrawImageUnscaled(_bitmap, 0, 0);
if (_cue != null && Text.Length == 0)
e.Graphics.DrawString(_cue, Font, Brushes.Gray, -1f, 1f);
SetStyle(ControlStyles.UserPaint, false);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
Invalidate();
}
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
Invalidate();
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
Invalidate();
}
protected override void OnFontChanged(EventArgs e)
{
if (_paintedFirstTime)
SetStyle(ControlStyles.UserPaint, false);
base.OnFontChanged(e);
if (_paintedFirstTime)
SetStyle(ControlStyles.UserPaint, true);
}
#endregion
}
基本上我使用了GlassTextBox的代码并在OnPaint函数中添加了几行以便能够绘制提示。
答案 1 :(得分:0)
好吧,最后在网上搜索后,我找到了一个“有点”的解决方案(至少对我的项目来说)This class allows the watermark in multiline虽然实际上要使文字排序,你必须进入设计器类并添加{ {1}}让它转到新的一行。但这确实有效!