
本篇實現了類似于QQ登錄中輸入框的效果,可以自定義邊框效果!
還是先看看最終的效果圖(和QQ登陸中的輸入框效果差不多):
效果說明: 1.實現了水印的效果 2.實現了鼠標移上去的時候周圍產生輝光 3.輸入前端可以設置圖片
整體說明:
前面顯示的那個圖片我采用的是一個picturebox,當然如果你愿意也可以自己畫(后續的“button再探討”中就采用的是自己畫的方式)。圖片后面的輸入文本框采用的是textbox控件,這樣一來就避免了許多繪制textbox的麻煩(我一開始打算自己繪制用戶輸入的字符的,不過發現不理想)。然后邊框和輝光都是畫出來的。
具體實現:
先拋開水印不說。最重要的就是重寫的OnPaint方法,如下:

代碼
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
CalculateSizeAndPosition();
Draw(e.ClipRectangle, e.Graphics);
base.OnPaint(e);
}
可以看出里面調用了兩個方法,做過前面窗體換膚的可能對這個不陌生。就是繪畫之前計算好所有的位置大小信息,然后再調用draw畫出來。那么這次的calculateSizeAndPosition又做了什么呢?2點!1.判斷是否有前端圖片需要顯示,2.判斷是否處于multiline模式。代碼如下:

代碼
private void CalculateSizeAndPosition()
{
if (ForeImage != null)
{
//圖片大小固定為16
pic.Height = pic.Width = 16;
pic.Top = pic.Left = 3;
txt.Width = Width - pic.Width - 12;
txt.Location = new Point(16 + 3 + 3, 6);
}
else
{
pic.Left = -40; //隱藏圖片
txt.Width = Width - 9;
txt.Location = new Point(3, 6);
}
//單行
if (!txt.Multiline)
{
Height = txt.Height + 9;
}
else
{
txt.Height = Height - 9; //如果是多行則設置實際里面的輸入文本框的高度
}
}
當所有的東西都計算好了,我們就可以安心的拿起我們的畫筆竟然繪畫了。先畫什么?再畫什么?請看代碼:

代碼
private void Draw(Rectangle rectangle, Graphics g)
{
#region 畫背景
using (SolidBrush backgroundBrush = new SolidBrush(Color.White))
{
g.FillRectangle(backgroundBrush, 2, 2, this.Width - 5, this.Height -4);
}
#endregion
#region 畫陰影(外邊框)
Color drawShadowColor = _shadowColor;
if (!_isFouse) //判斷是否獲得焦點
{
drawShadowColor = Color.Transparent;
}
using (Pen shadowPen = new Pen(drawShadowColor))
{
if (_radius == 0)
{
g.DrawRectangle(shadowPen, new Rectangle(rectangle.X, rectangle.Y, rectangle.Width - 1, rectangle.Height - 1));
}
else
{
g.DrawPath(shadowPen, DrawHelper.DrawRoundRect(rectangle.X, rectangle.Y, rectangle.Width - 2, rectangle.Height - 1, _radius));
}
}
#endregion
#region 畫邊框
using (Pen borderPen = new Pen(_borderColor))
{
if (_radius == 0)
{
g.DrawRectangle(borderPen, new Rectangle(rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 3, rectangle.Height - 3));
}
else
{
g.DrawPath(borderPen, DrawHelper.DrawRoundRect(rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 3, rectangle.Height - 2, _radius));
}
}
#endregion
}
在這個方法里面主要畫了三個東西,大家看注釋也知道了,分別是:背景,邊框,輝光。要注意的就是這里面的微小距離要設置好,我也改了好幾次才設置正確。在畫邊框和輝光的時候,因為實現了圓角邊框所以要對圓角度進行判斷。
現在繪畫的方法也做好了,接下來就是出發重繪的事件了。不然它也不會自動幫你繪畫啊^_^。顯然當鼠標移上去和移出去的時候需要重新繪畫。那我們就在下面幾個方法中引發重繪事件:

代碼
private void TextBoxEx2_MouseEnter(object sender, EventArgs e)
{
_isFouse = true;
this.Invalidate();
}
private void TextBoxEx2_MouseLeave(object sender, EventArgs e)
{
_isFouse = false;
this.Invalidate();
}
代碼很簡單,不解釋。
基本上面的做好了,大部分就完成了。下面我們完成水印的功能。至此,textbox美化講解完畢,希望對你有幫助
水印我是這樣子實現的:當用戶離開輸入焦點的時候檢測當前用戶有沒有輸入字符,如果沒有輸入則改變輸入框的顏色(灰色),然后看起來就像是水印的感覺啦。我們專門寫了一個函數來設置水印,如下:

代碼
private void SetWaterMark()
{
if (_waterMark != null && (txt.Text == " " || txt.Text == @"" + WaterMark)) //用戶沒有輸入
{
txt.ForeColor = _waterMarkColor;
txt.Text = @"" + WaterMark;
}
else
{
txt.ForeColor = ForeColor;
}
}
然后在什么地方調用呢?剛才上面也已經說了當用戶離開焦點的時候判斷,不過用戶獲得輸入焦點的時候我們還要設置一下,如果當前的文本時水印的話就清空文本等待輸入:
private void Txt_GotFocus(object sender, EventArgs e)
{
if (txt.Text == @"" + WaterMark)
{
//獲得焦點,切換正常文字等待填寫
txt.ForeColor = ForeColor;
txt.Text = " ";
}
}
private void Txt_LostFocus(object sender, EventArgs e)
{
SetWaterMark();
}
這里還有一點需要注意的是,在pageload里面我們也需要調用一下setwatermark方法,不然它一開始是不會顯示滴!

代碼
namespace QLFUI
{
public partial class TextBoxEx : UserControl
{
#region - 變量 -
private Color _borderColor = Color.FromArgb(166, 208, 226);
private Color _shadowColor = Color.FromArgb(175, 212, 228);
private Image _foreImage = null;
private bool _isFouse = false;
private Color _backColor = Color.Transparent;
private string _waterMark = null;
private Color _waterMarkColor = Color.Silver;
private Color _foreColor = Color.Black;
private int _radius = 3;
#endregion
#region - 屬性 -
[Category("QLFUI"), Description("邊框顏色,BorderStyle為FixedSingle有效")]
public Color BorderColor
{
get { return _borderColor; }
set
{
_borderColor = value;
this.Invalidate();
}
}
[Category("QLFUI"), Description("邊框陰影顏色,BorderStyle為FixedSingle有效")]
public Color ShadowColor
{
get { return _shadowColor; }
set
{
_shadowColor = value;
this.Invalidate();
}
}
[Category("QLFUI"), Description("顯示的前端的圖片")]
public Image ForeImage
{
get { return pic.Image; }
set
{
_foreImage = value;
pic.Image = _foreImage;
Invalidate();
}
}
[Category("QLFUI"), Description("文字")]
public string Caption
{
get
{
return txt.Text;
}
set
{
txt.Text = value;
SetWaterMark();
Invalidate();
}
}
[Category("行為"), Description("是否多行顯示")]
public bool Multiline
{
get { return txt.Multiline; }
set
{
txt.Multiline = value;
}
}
[Category("行為"), Description("是否以密碼形式顯示字符")]
public bool UseSystemPasswordChar
{
get { return txt.UseSystemPasswordChar; }
set
{
txt.UseSystemPasswordChar = value;
}
}
[Category("QLFUI"), Description("水印文字")]
public string WaterMark
{
get { return _waterMark; }
set
{
_waterMark = value;
Invalidate();
}
}
[Category("QLFUI"), Description("水印顏色")]
public Color WaterMarkColor
{
get { return _waterMarkColor; }
set
{
_waterMarkColor = value;
Invalidate();
}
}
#region 需要被隱藏的屬性
[Browsable(false)]
public new BorderStyle BorderStyle
{
get { return BorderStyle.None; }
}
[Browsable(false)]
public new Color BackColor
{
get { return base.BackColor; }
set { base.BackColor = value; }
}
[Browsable(false)]
public new Image BackgroundImage
{
get { return null; }
}
[Browsable(false)]
public new ImageLayout BackgroundImageLayout
{
get { return base.BackgroundImageLayout; }
set { base.BackgroundImageLayout = value; }
}
#endregion
[Category("QLFUI"), Description("邊角彎曲的角度(1-10),數值越大越彎曲")]
public int Radius
{
get { return _radius; }
set
{
if (value > 10)
{
value = 10;
}
if (value < 0)
{
value = 0;
}
_radius = value;
this.Invalidate();
}
}
[Browsable(true)]
[Category("外觀"), Description("文本顏色")]
public new Color ForeColor
{
get { return _foreColor; }
set { _foreColor = value; }
}
[Browsable(true)]
[Category("外觀"), Description("鼠標形狀")]
public new Cursor Cursor
{
get { return txt.Cursor; }
set { txt.Cursor = value; }
}
[Category("行為"), Description("自動提示方式")]
public AutoCompleteMode AutoCompleteMode
{
get { return txt.AutoCompleteMode; }
set { txt.AutoCompleteMode = value; }
}
[Category("行為"), Description("自動提示類型")]
public AutoCompleteSource AutoCompleteSource
{
get { return txt.AutoCompleteSource; }
set { txt.AutoCompleteSource = value; }
}
#endregion
#region - 構造函數 -
public TextBoxEx()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
InitializeComponent();
BackColor = Color.Transparent;
//下面的圖片和文本框的大小位置必須設置,否則首次啟動時
//會出現莫名其妙的斷痕
pic.SizeMode = PictureBoxSizeMode.StretchImage;
pic.BorderStyle = BorderStyle.None;
pic.Height = pic.Width = 16;//圖片大小固定為16
pic.Left = -40; //隱藏圖片
txt.Width = Width - 9;
txt.Location = new Point(3, 6);
txt.MouseEnter += new EventHandler(TextBoxEx2_MouseEnter);
txt.MouseLeave += new EventHandler(TextBoxEx2_MouseLeave);
pic.MouseEnter += new EventHandler(TextBoxEx2_MouseEnter);
pic.MouseLeave += new EventHandler(TextBoxEx2_MouseLeave);
txt.LostFocus += new EventHandler(Txt_LostFocus);
txt.GotFocus += new EventHandler(Txt_GotFocus);
pic.BackColor = Color.White; //不設置成白色則邊框會一同加陰影
}
#endregion
#region - 事件 -
private void TextBoxEx_Load(object sender, EventArgs e)
{
SetWaterMark();
}
private void TextBoxEx2_MouseEnter(object sender, EventArgs e)
{
_isFouse = true;
this.Invalidate();
}
private void TextBoxEx2_MouseLeave(object sender, EventArgs e)
{
_isFouse = false;
this.Invalidate();
}
private void Txt_GotFocus(object sender, EventArgs e)
{
if (txt.Text == @"" + WaterMark)
{
//獲得焦點,切換正常文字等待填寫
txt.ForeColor = ForeColor;
txt.Text = " ";
}
}
private void Txt_LostFocus(object sender, EventArgs e)
{
SetWaterMark();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
CalculateSizeAndPosition();
Draw(e.ClipRectangle, e.Graphics);
base.OnPaint(e);
}
#endregion
#region - 幫助方法 -
private void SetWaterMark()
{
if (_waterMark != null && (txt.Text == " " || txt.Text == @"" + WaterMark)) //用戶沒有輸入
{
txt.ForeColor = _waterMarkColor;
txt.Text = @"" + WaterMark;
}
else
{
txt.ForeColor = ForeColor;
}
}
private void CalculateSizeAndPosition()
{
if (ForeImage != null)
{
pic.Top = pic.Left = 3;
txt.Width = Width - pic.Width - 12;
txt.Location = new Point(16 + 3 + 3, 6);
}
else
{
pic.Left = -40; //隱藏圖片
txt.Width = Width - 9;
txt.Location = new Point(3, 6);
}
//單行
if (!txt.Multiline)
{
Height = txt.Height + 9;
}
else
{
txt.Height = Height - 9;
}
}
private void Draw(Rectangle rectangle, Graphics g)
{
#region 畫背景
using (SolidBrush backgroundBrush = new SolidBrush(Color.White))
{
g.FillRectangle(backgroundBrush, 2, 2, this.Width - 5, this.Height -4);
}
#endregion
#region 畫陰影(外邊框)
Color drawShadowColor = _shadowColor;
if (!_isFouse) //判斷是否獲得焦點
{
drawShadowColor = Color.Transparent;
}
using (Pen shadowPen = new Pen(drawShadowColor))
{
if (_radius == 0)
{
g.DrawRectangle(shadowPen, new Rectangle(rectangle.X, rectangle.Y, rectangle.Width - 1, rectangle.Height - 1));
}
else
{
g.DrawPath(shadowPen, DrawHelper.DrawRoundRect(rectangle.X, rectangle.Y, rectangle.Width - 2, rectangle.Height - 1, _radius));
}
}
#endregion
#region 畫邊框
using (Pen borderPen = new Pen(_borderColor))
{
if (_radius == 0)
{
g.DrawRectangle(borderPen, new Rectangle(rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 3, rectangle.Height - 3));
}
else
{
g.DrawPath(borderPen, DrawHelper.DrawRoundRect(rectangle.X + 1, rectangle.Y + 1, rectangle.Width - 3, rectangle.Height - 2, _radius));
}
}
#endregion
}
#endregion
}
}
Demo下載