C# Winfrom 自定义控件——带图片的TextBox

效果:

描述:

本来是想用GDI在左边画图片上去的,文本是居中对齐,如果文本是左对齐,文本会把图片遮住控件长这样:
但这样做,输入框在获取焦点时候,会把图片挡住就像这样:
输入完成之后图片就会显示完整。所以我又采用了PictureBox+TextBox组合的方式来完成这种效果。完成这种效果需要完成以下步骤:
0.分别设置PictureBox和TextBox的控件的Anchor和Dock属性,这样在窗体上拉动控件大小的时候,图片框和文本输入框能一起变大;
1.调整TextBox的border为none;
2.调整PictureBox的backColor为White;
3.调整作为控件载体的UserControl的BackColor为White;
4.设置作为控件载体的UserControl的BorderStyle为FixedSingle;因为这里需要重绘UserContorl的边框就需要这样的设置,我这里重绘成了DarkRed颜色。

提醒:

如果你想写一些文本框的事件就要像定义MyTextChanged那样暴露出来。还有就是,这里如果override UserControlde的OnPaint方法我是没能完成控件边框的重绘。
 (我也不清楚什么时候重写WndProc什么时候重写OnPaint。)

代码:

 public partial class MyPicturerTextBox : UserControl
    {
        public MyPicturerTextBox()
        {
            InitializeComponent();
            this.BorderStyle = BorderStyle.FixedSingle;
        }


        private Image userImg;
        [Description("文本框里的图片")]
        public Image UserImg
        {
            get { return userImg; }

            set
            {

                if (value != null)
                {
                    this.Img.Image = value;
                }
                userImg = value;

            }
        }

        private string txt;
        [Description("输入的文本")]
        public string Txt
        {
            get { return txt; }

            set
            {
                if (!string.IsNullOrEmpty(value))
                {
                    this.textBox.Text = value;
                }
                txt = value;
            }
        }
        [Description("TextChanged事件")]
        public event EventHandler MyTextChanged;

        private void textBox_TextChanged(object sender, EventArgs e)
        {
            MyTextChanged?.Invoke(sender, e);
        }
       
        ///  
        /// 获得当前进程,以便重绘控件 
        ///  
        ///  
        ///  
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern IntPtr GetWindowDC(IntPtr hWnd);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);


        protected override void WndProc(ref Message m)
        {

            base.WndProc(ref m);
            if (m.Msg == 0xf || m.Msg == 0x133)
            {
                //拦截系统消息,获得当前控件进程以便重绘。 
                //一些控件(如TextBox、Button等)是由系统进程绘制,重载OnPaint方法将不起作用. 
                //所有这里并没有使用重载OnPaint方法绘制TextBox边框。 
                // 
                //MSDN:重写 OnPaint 将禁止修改所有控件的外观。 
                //那些由 Windows 完成其所有绘图的控件(例如 Textbox)从不调用它们的 OnPaint 方法, 
                //因此将永远不会使用自定义代码。请参见您要修改的特定控件的文档, 
                //查看 OnPaint 方法是否可用。如果某个控件未将 OnPaint 作为成员方法列出, 
                //则您无法通过重写此方法改变其外观。 
                // 
                //MSDN:要了解可用的 Message.Msg、Message.LParam 和 Message.WParam 值, 
                //请参考位于 MSDN Library 中的 Platform SDK 文档参考。可在 Platform SDK(“Core SDK”一节) 
                //下载中包含的 windows.h 头文件中找到实际常数值,该文件也可在 MSDN 上找到。 
                IntPtr hDC = GetWindowDC(m.HWnd);
                if (hDC.ToInt32() == 0)
                {
                    return;
                }

                //只有在边框样式为FixedSingle时自定义边框样式才有效 
                if (this.BorderStyle == BorderStyle.FixedSingle)
                {
                    //边框Width为1个像素 
                    System.Drawing.Pen pen = new Pen(Brushes.DarkRed, 1);

                    //绘制边框 
                    System.Drawing.Graphics g = Graphics.FromHdc(hDC);
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    g.DrawRectangle(pen, 0, 0, this.Width - 1, this.Height - 1);
                    pen.Dispose();
                }
                //返回结果 
                m.Result = IntPtr.Zero;
                //释放 
                ReleaseDC(m.HWnd, hDC);
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            this.Refresh();
        }
    }

不足之处:

文本没能居中,可以把字体大小往上调让字体充满控件的高度。调整控件的大小之后,需要手动调整字体的大小
 

你可能感兴趣的:(C# Winfrom 自定义控件——带图片的TextBox)