效果:
描述:
本来是想用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); } /// <summary> /// 获得当前进程,以便重绘控件 /// </summary> /// <param name="hWnd"></param> /// <returns></returns> [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(); } }
不足之处:
文本没能居中,可以把字体大小往上调让字体充满控件的高度。调整控件的大小之后,需要手动调整字体的大小