带大家一步步熟悉C#.重绘.美化控件.重绘TextBox(一)

首先C# 中TextBox控件属于系统控件,若是只继承TextBox 。然后重写Paint事件是不会产生任何效果的。这种控件。重绘需要拦截消息。然后重绘。

带大家一步步熟悉C#.重绘.美化控件.重绘TextBox(一)

重写WndProc

首先重写WndProc 。并截获消息。

窗体重绘主要是这两个消息。判定消息 m.Msg==以下两个消息时候,执行重绘需要的代码

public const int WM_PAINT = 0x000F; //要求一个窗口重画自己

public const int WM_NCPAINT = 0x0085; //程序发送此消息给某个窗口当它(窗口)的框架必须被绘制时;

带大家一步步熟悉C#.重绘.美化控件.重绘TextBox(一)

重写事件

此位置主要用到两个调用系统Dll文件,方法如下

带大家一步步熟悉C#.重绘.美化控件.重绘TextBox(一)

[DllImport("user32.dll")]

public static extern IntPtr GetWindowDC(IntPtr hWnd);

带大家一步步熟悉C#.重绘.美化控件.重绘TextBox(一)

[DllImport("user32.dll")]

public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);

            if (m.Msg == 0xf || m.Msg == 0x133)
            {
 IntPtr hDC = WinApi.WindowsAPI.GetWindowDC(m.HWnd);
                if (hDC.ToInt32() == 0)
                {
                    return;
                }

 //只有在边框样式为FixedSingle时自定义边框样式才有效
                using (Graphics g = Graphics.FromHdc(hDC))
                {
                    g.SetGDIHigh();
                    if (this.BorderStyle == BorderStyle.FixedSingle)
                    {
                        //边框Width为1个像素
                        using (Pen pen = new Pen(this.borderColor, 1))
                        {
                            if (this.hotTrack)
                            {
                                if (this.Focused)
                                {
                                    pen.Color = this.hotColor;
                                }
                                else
                                {
                                    if (this.isMouseOver)
                                    {
                                        pen.Color = this.hotColor;
                                    }
                                    else
                                    {
                                        pen.Color = this.borderColor;
                                    }
                                }
                            }
                            g.DrawRectangle(pen, 0, 0, this.Width - 1, this.Height - 1);
                        }
                    }
										//当文本为空,提示文本不为空,水印TextBox
                    if (this.Text == "" && this.WateText != "")
                    {
                        using (Brush b = new SolidBrush(Color.FromArgb(153, 153, 153)))
                        {
                            g.DrawString(WateText, this.Font, b, new Rectangle(0, 0, Width, this.Height), ControlHelper.StringConters);
                        }
                    }
                }
 //返回结果
 m.Result = IntPtr.Zero;
 ////释放
 WinApi.WindowsAPI.ReleaseDC(m.HWnd, hDC);
            }

以上代码主要实现其功能。

        #region 公有属性


        [Category("Wen"), Description("当文本类容为空的时候提示内容"), DefaultValue(null)]
        public string WateText { get => wateText; set { wateText = value; this.Invalidate(); } }

        /// <summary>
        /// 是否启用热点效果
        /// </summary>
        [Category("行为"),
            Description("获得或设置一个值,指示当鼠标经过控件时控件边框是否发生变化。只在控件的BorderStyle为FixedSingle时有效"),
            DefaultValue(true)]
        public bool HotTrack
        {
            get => this.hotTrack;
            set
            {
                this.hotTrack = value;
 //在该值发生变化时重绘控件,下同
 //在设计模式下,更改该属性时,如果不调用该语句,
 //则不能立即看到设计试图中该控件相应的变化
 this.Invalidate();
            }
        }

        /// <summary>
        /// 热点时边框颜色
        /// </summary>
        [Category("外观"),
            Description("获得或设置当鼠标经过控件时控件的边框颜色。只在控件的BorderStyle为FixedSingle时有效"),
            DefaultValue(typeof(Color), "#335EA8")]
        public Color HotColor { get => this.hotColor; set { this.hotColor = value; this.Invalidate(); } }

        /// <summary>
        /// 边框颜色
        /// </summary>
        [Category("外观"), Description("获得或设置控件的边框颜色"), DefaultValue(typeof(Color), "#A7A6AA")]
        public Color BorderColor { get => this.borderColor; set { this.borderColor = value; this.Invalidate(); } }


        #endregion
        #region 私有属性

        /// <summary>
        /// 是否启用热点效果
        /// </summary>
        private bool hotTrack = true;

 /// <summary>
 /// 边框颜色
 /// </summary>
 private Color borderColor = Color.FromArgb(0xA7, 0xA6, 0xAA);

 /// <summary>
 /// 热点边框颜色
 /// </summary>
 private Color hotColor = Color.FromArgb(0x33, 0x5E, 0xA8);

 /// <summary>
 /// 是否鼠标MouseOver状态
 /// </summary>
 private bool isMouseOver = false;
        private string wateText;

        #endregion
        #region 重写是鼠标事件

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            isMouseOver = false;
        }
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            isMouseOver = true;
        }

        #endregion
        #region 重写属性

        public new bool ReadOnly
        {
            get => base.ReadOnly;
            set
            {
                base.ReadOnly = value;
                if (value)
                { 
                this.BackColor = Color.FromArgb(100, 100, 100);
                }
                else
                    this.BackColor = Color.FromArgb(37, 37, 37);
                this.Invalidate();
            }
        }

        #endregion
        //构造函数 主要是颜色改变,做一套酷黑色控件,可以自主美化
				public WenTextBox() : base()
        {
            this.BackColor = Color.FromArgb(37, 37, 38);
            this.ForeColor = Color.White;
            this.BorderStyle = BorderStyle.FixedSingle;
        }

当然我们还可以添加公有属性,提供在设计的时候直接修改属性,

添加鼠标事件,在鼠标移动到控件内改变外框外观。是得控件更加美观。

到这里一个简单的TextBox控件美化完成

接下来看看效果

带大家一步步熟悉C#.重绘.美化控件.重绘TextBox(一)

带大家一步步熟悉C#.重绘.美化控件.重绘TextBox(一)

带大家一步步熟悉C#.重绘.美化控件.重绘TextBox(一)