代码想要实现的功能是:

实现原理:
一、继承TextBox类,重写TextBox的三个事件(OnHandleCreated,OnTextChanged,OnGotFocus)
二、 不能直接在TextBoxChange中增加判断,容易频繁GDI绘图
三、 使用Timer进行延时GDI+,避免频繁绘图
代码实现:
先添加一个用户控件

将新建的UserControl继承TextBox
public partial class UserControl1 : TextBox
生成一个方法,实现当文本改变或焦点改变时判断文本长度,当Text.Length=0时,用GDI在TextBox上绘制显示需要的文本
int i = 0; private void ReDraw(TextBox textBox)
{
Graphics g;
g = Graphics.FromHwnd(textBox.Handle);
if (textBox.Text.Length <= 0)
{
Font font = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style);//设置字体,大小,粗细
Brush sbrush = new SolidBrush(Color.Gray);//设置颜色
g.DrawString("请输入文本......", font, sbrush, 1, 1);
g.Save();
i = 0;
}
else
{
if (i == 0)
{
g.Clear(textBox.BackColor);
Font font = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style);//设置字体,大小,粗细
Brush sbrush = new SolidBrush(this.ForeColor);//设置颜色
g.DrawString(Text, font, sbrush, 0, 0);
g.Save();
i++;
}
}
}
之后我发现在触发OnTextChanged时直接在文本上面绘图,会导致界面无法更新到我需要显示的页面。
原因可能为触发OnTextChanged时,系统默认的GDI的绘图速度慢于我写的这个方法。
所以增加一个Timer,在文字发生改变时实现GDI延时绘图
public UserControl1()
{
InitializeComponent();
timer = new Timer();
timer.Interval = 30;
timer.Tick += Timer_Tick;
timer.Enabled = false;
}
private void Timer_Tick(object sender, EventArgs e)
{
ReDraw(this);
timer.Enabled = false;
}
最后将OnHandleCreated,OnTextChanged,OnGotFocus三个事件重写
OnHandleCreated实现文本框加载时,默认显示提示文本。
OnTextChanged实现文字改变时,判断是否显示提示文本。
OnGotFocus当TextBox窗体失去焦点后重新获得焦点时,显示提示文本。
protected override void OnHandleCreated(EventArgs e)
{
ReDraw(this);
base.OnHandleCreated(e);
}
protected override void OnTextChanged(EventArgs e)
{
ReDraw(this);
base.OnTextChanged(e);
}
protected override void OnGotFocus(EventArgs e)
{
ReDraw(this);
base.OnGotFocus(e);
}
该代码还有优化的空间,应该可以用其他的办法替代延时的方法。想到再补充。。
所有代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TextBoxControler
{
public partial class UserControl1 : TextBox
{
private Timer timer;
public UserControl1()
{
InitializeComponent();
timer = new Timer();
timer.Interval = 30;
timer.Tick += Timer_Tick;
timer.Enabled = false;
}
private void Timer_Tick(object sender, EventArgs e)
{
ReDraw(this);
timer.Enabled = false;
}
protected override void OnHandleCreated(EventArgs e)
{
ReDraw(this);
base.OnHandleCreated(e);
}
protected override void OnTextChanged(EventArgs e)
{
ReDraw(this);
base.OnTextChanged(e);
}
protected override void OnGotFocus(EventArgs e)
{
ReDraw(this);
base.OnGotFocus(e);
}
int i = 0;
private void ReDraw(TextBox textBox)
{
Graphics g;
g = Graphics.FromHwnd(textBox.Handle);
if (textBox.Text.Length <= 0)
{
Font font = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style);//设置字体,大小,粗细
Brush sbrush = new SolidBrush(Color.Gray);//设置颜色
g.DrawString("请输入文本......", font, sbrush, 1, 1);
g.Save();
i = 0;
}
else
{
if (i == 0)
{
g.Clear(textBox.BackColor);
Font font = new Font(this.Font.FontFamily, this.Font.Size, this.Font.Style);//设置字体,大小,粗细
Brush sbrush = new SolidBrush(this.ForeColor);//设置颜色
g.DrawString(Text, font, sbrush, 0, 0);
g.Save();
i++;
}
}
}
}
}
本文介绍如何在C#的WinForm应用中,通过继承TextBox并利用GDI+绘制,实现在文本框内容为空时显示提示文本。文章讨论了避免频繁绘图的方法,即使用Timer进行延时GDI+绘制,并详细解释了OnHandleCreated、OnTextChanged和OnGotFocus三个关键事件的重写逻辑。虽然目前采用延时方法,但作者认为存在优化空间,期待后续改进。
1456

被折叠的 条评论
为什么被折叠?



