C# textbox重绘

效果预览

    还是先看看最终的效果图(和QQ登陆中的输入框效果差不多):

查看 TextboxEx效果

 

 

       效果说明: 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方法,不然它一开始是不会显示滴!

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.Data;
using System.Security;
using System.Drawing.Drawing2D;


namespace Cash_Register_System.V1._00
{
    internal class DrawHelper
    {
        public static GraphicsPath DrawRoundRect(int x, int y, int width, int height, int radius)
        {
            GraphicsPath gp = new GraphicsPath();
            gp.AddArc(x, y, radius, radius, 180, 90);
            gp.AddArc(width - radius, y, radius, radius, 270, 90);
            gp.AddArc(width - radius, height - radius, radius, radius, 0, 90);
            gp.AddArc(x, height - radius, radius, radius, 90, 90);
            gp.CloseAllFigures();
            return gp;
        }

        /// <summary>
        /// 绘制圆角矩形
        /// </summary>
        /// <param name="rect">矩形</param>
        /// <param name="radius">弯曲程度(0-10),越大越弯曲</param>
        /// <returns></returns>
        public static GraphicsPath DrawRoundRect(Rectangle rect, int radius)
        {
            int x = rect.X;
            int y = rect.Y;
            int width = rect.Width;
            int height = rect.Height;
            return DrawRoundRect(x, y, width - 2, height - 1, radius);
        }

        /// <summary>
        /// 得到两种颜色的过渡色(1代表开始色,100表示结束色)
        /// </summary>
        /// <param name="c">开始色</param>
        /// <param name="c2">结束色</param>
        /// <param name="value">需要获得的度</param>
        /// <returns></returns>
        public static Color GetIntermediateColor(Color c, Color c2, int value)
        {
            float pc = value * 1.0F / 100;

            int ca = c.A, cr = c.R, cg = c.G, cb = c.B;
            int c2a = c2.A, c2r = c2.R, c2g = c2.G, c2b = c2.B;

            int a = (int)Math.Abs(ca + (ca - c2a) * pc);
            int r = (int)Math.Abs(cr - ((cr - c2r) * pc));
            int g = (int)Math.Abs(cg - ((cg - c2g) * pc));
            int b = (int)Math.Abs(cb - ((cb - c2b) * pc));

            if (a > 255) { a = 255; }
            if (r > 255) { r = 255; }
            if (g > 255) { g = 255; }
            if (b > 255) { b = 255; }

            return (Color.FromArgb(a, r, g, b));
        }

        public static StringFormat StringFormatAlignment(ContentAlignment textalign)
        {
            StringFormat sf = new StringFormat();
            switch (textalign)
            {
                case ContentAlignment.TopLeft:
                case ContentAlignment.TopCenter:
                case ContentAlignment.TopRight:
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.MiddleRight:
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case ContentAlignment.BottomLeft:
                case ContentAlignment.BottomCenter:
                case ContentAlignment.BottomRight:
                    sf.LineAlignment = StringAlignment.Far;
                    break;
            }
            switch (textalign)
            {
                case ContentAlignment.TopLeft:
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.BottomLeft:
                    sf.Alignment = StringAlignment.Near;
                    break;
                case ContentAlignment.TopCenter:
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.BottomCenter:
                    sf.Alignment = StringAlignment.Center;
                    break;
                case ContentAlignment.TopRight:
                case ContentAlignment.MiddleRight:
                case ContentAlignment.BottomRight:
                    sf.Alignment = StringAlignment.Far;
                    break;
            }
            return sf;
        }
    }

    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 pictureBox1.Image; }
            set
            {
                _foreImage = value;
                pictureBox1.Image = _foreImage;
                Invalidate();
            }
        }

        [Category("QLFUI"), Description("文字")]
        public string Caption
        {
            get
            {
                return textBox1.Text;
            }
            set
            {
                textBox1.Text = value;
                SetWaterMark();
                Invalidate();
            }
        }

        [Category("行为"), Description("是否多行显示")]
        public bool Multiline
        {
            get { return textBox1.Multiline; }
            set
            {
                textBox1.Multiline = value;
            }
        }

        [Category("行为"), Description("是否以密码形式显示字符")]
        public bool UseSystemPasswordChar
        {
            get { return textBox1.UseSystemPasswordChar; }
            set
            {
                textBox1.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 textBox1.Cursor; }
            set { textBox1.Cursor = value; }
        }

        [Category("行为"), Description("自动提示方式")]
        public AutoCompleteMode AutoCompleteMode
        {
            get { return textBox1.AutoCompleteMode; }
            set { textBox1.AutoCompleteMode = value; }
        }

        [Category("行为"), Description("自动提示类型")]
        public AutoCompleteSource AutoCompleteSource
        {
            get { return textBox1.AutoCompleteSource; }
            set { textBox1.AutoCompleteSource = value; }
        }

        #endregion

        #region - 构造函数 -

        public TextBoxEx()
        {
            SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
            InitializeComponent();

            BackColor = Color.Transparent;

            //下面的图片和文本框的大小位置必须设置,否则首次启动时
            //会出现莫名其妙的断痕
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            pictureBox1.BorderStyle = BorderStyle.None;
            pictureBox1.Height =pictureBox1.Width = 16;//图片大小固定为16
            pictureBox1.Left = -40;  //隐藏图片
            textBox1.Width = Width - 9;
            textBox1.Location = new Point(3, 6);

            textBox1.MouseEnter += new EventHandler(TextBoxEx2_MouseEnter);
            textBox1.MouseLeave += new EventHandler(TextBoxEx2_MouseLeave);
            textBox1.MouseEnter += new EventHandler(TextBoxEx2_MouseEnter);
            textBox1.MouseLeave += new EventHandler(TextBoxEx2_MouseLeave);
            textBox1.LostFocus += new EventHandler(Txt_LostFocus);
            textBox1.GotFocus += new EventHandler(Txt_GotFocus);
            textBox1.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 (textBox1.Text == @"" + WaterMark)
            {
                //获得焦点,切换正常文字等待填写
                textBox1.ForeColor = ForeColor;
                textBox1.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 && (textBox1.Text == " " || textBox1.Text == @"" + WaterMark))   //用户没有输入
            {
                textBox1.ForeColor = _waterMarkColor;
                textBox1.Text = @"" + WaterMark;
            }
            else
            {
                textBox1.ForeColor = ForeColor;
            }
        }

        private void CalculateSizeAndPosition()
        {
            if (ForeImage != null)
            {
                pictureBox1.Top = pictureBox1.Left = 3;
                textBox1.Width = Width - pictureBox1.Width - 12;
                textBox1.Location = new Point(16 + 3 + 3, 6);
            }
            else
            {
                pictureBox1.Left = -40;  //隐藏图片
                textBox1.Width = Width - 9;
                textBox1.Location = new Point(3, 6);
            }

            //单行
            if (!textBox1.Multiline)
            {
                Height = textBox1.Height + 9;
            }
            else
            {
                textBox1.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
    }
}

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值