这些天项目中需要用到自动适应文本大小的文本框控件。
本以为Graphics.MeasureString可以获得文字的范围,但是怎么弄
也和textbox的大小不一致,尤其是行数多了的时候。
网上估计有些兄弟也有这方面的问题。
后来通过看Textbox的源码,发现用TextRenderer.MeasureText可以完美获得和TextBox一样的大小。故实现了以下控件。
有兴趣看代码的,代码copy如下:
2007 9 30 使用的时候发现了bug:键盘输入时,并不能保持中心点不变,原因:每次变化去求前一次的保持的位置,长久下来累计误差比较大,因为中间除2了,可能会舍入。修改为保存好不变的位置
修改后代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Runtime.InteropServices;
using System.Drawing;
namespace Hob.Toolbox.Controls
{
///
/// 锁定的位置
///
public enum LockPosition
{
LockTopLeft,
LockTopHCenter,
LockTopRight,
LockVCenterRight,
LockBottomRight,
LockBottomHCenter,
LockBottomLeft,
LockVCenterLeft,
LockVCenterHCenter
}
///
/// 自动适应文本大小的文本框控件
/// 继承自TextBox
/// 2007 9 30 bug:键盘输入时,并不能保持中心点不变,原因:每次变化去求前一次的
/// 保持的位置,长久下来累计误差比较大,因为中间除2了,可能会舍入。修改为保存好不变的位置
///
public class AutoSizeTextBox : TextBox
{
public AutoSizeTextBox()
{
//默认多行
base.Multiline = true;
base.WordWrap = false;
base.TextAlign = HorizontalAlignment.Center;
base.BorderStyle = BorderStyle.FixedSingle;
{
///
/// 锁定的位置
///
public enum LockPosition
{
LockTopLeft,
LockTopHCenter,
LockTopRight,
LockVCenterRight,
LockBottomRight,
LockBottomHCenter,
LockBottomLeft,
LockVCenterLeft,
LockVCenterHCenter
}
///
/// 自动适应文本大小的文本框控件
/// 继承自TextBox
/// 2007 9 30 bug:键盘输入时,并不能保持中心点不变,原因:每次变化去求前一次的
/// 保持的位置,长久下来累计误差比较大,因为中间除2了,可能会舍入。修改为保存好不变的位置
///
public class AutoSizeTextBox : TextBox
{
public AutoSizeTextBox()
{
//默认多行
base.Multiline = true;
base.WordWrap = false;
base.TextAlign = HorizontalAlignment.Center;
base.BorderStyle = BorderStyle.FixedSingle;
m_LockPosition = LockPosition.LockTopLeft;
m_FrameColor = Color.Gray;
m_unchangleLocationInit = false;
}
m_FrameColor = Color.Gray;
m_unchangleLocationInit = false;
}
///
/// 不变化的位置坐标
///
private Point m_unchangeLocation;
bool m_unchangleLocationInit;//是否已经初始化m_unchangeLocation
/// 不变化的位置坐标
///
private Point m_unchangeLocation;
bool m_unchangleLocationInit;//是否已经初始化m_unchangeLocation
///
/// 调整大小
///
private void AdjustSize()
{
//调整大小
ClientSize = GetRightClientSize();
/// 调整大小
///
private void AdjustSize()
{
//调整大小
ClientSize = GetRightClientSize();
if (m_unchangleLocationInit)
{
switch (m_LockPosition)//保持位置
{
case LockPosition.LockTopLeft:
Location = m_unchangeLocation;
break;
case LockPosition.LockTopHCenter:
Location = new Point(m_unchangeLocation.X - Size.Width / 2, m_unchangeLocation.Y);
break;
case LockPosition.LockTopRight:
Location = new Point(m_unchangeLocation.X - Size.Width, m_unchangeLocation.Y);
break;
case LockPosition.LockVCenterRight:
Location = new Point(m_unchangeLocation.X - Size.Width, m_unchangeLocation.Y - Size.Height / 2);
break;
case LockPosition.LockBottomRight:
Location = new Point(m_unchangeLocation.X - Size.Width, m_unchangeLocation.Y - Size.Height);
break;
case LockPosition.LockBottomHCenter:
Location = new Point(m_unchangeLocation.X - Size.Width / 2, m_unchangeLocation.Y - Size.Height);
break;
case LockPosition.LockBottomLeft:
Location = new Point(m_unchangeLocation.X, m_unchangeLocation.Y - Size.Height);
break;
case LockPosition.LockVCenterLeft:
Location = new Point(m_unchangeLocation.X, m_unchangeLocation.Y - Size.Height / 2);
break;
case LockPosition.LockVCenterHCenter:
Location = new Point(m_unchangeLocation.X - Size.Width / 2, m_unchangeLocation.Y - Size.Height / 2);
break;
}
}
InvalidateFrame();
}
{
switch (m_LockPosition)//保持位置
{
case LockPosition.LockTopLeft:
Location = m_unchangeLocation;
break;
case LockPosition.LockTopHCenter:
Location = new Point(m_unchangeLocation.X - Size.Width / 2, m_unchangeLocation.Y);
break;
case LockPosition.LockTopRight:
Location = new Point(m_unchangeLocation.X - Size.Width, m_unchangeLocation.Y);
break;
case LockPosition.LockVCenterRight:
Location = new Point(m_unchangeLocation.X - Size.Width, m_unchangeLocation.Y - Size.Height / 2);
break;
case LockPosition.LockBottomRight:
Location = new Point(m_unchangeLocation.X - Size.Width, m_unchangeLocation.Y - Size.Height);
break;
case LockPosition.LockBottomHCenter:
Location = new Point(m_unchangeLocation.X - Size.Width / 2, m_unchangeLocation.Y - Size.Height);
break;
case LockPosition.LockBottomLeft:
Location = new Point(m_unchangeLocation.X, m_unchangeLocation.Y - Size.Height);
break;
case LockPosition.LockVCenterLeft:
Location = new Point(m_unchangeLocation.X, m_unchangeLocation.Y - Size.Height / 2);
break;
case LockPosition.LockVCenterHCenter:
Location = new Point(m_unchangeLocation.X - Size.Width / 2, m_unchangeLocation.Y - Size.Height / 2);
break;
}
}
InvalidateFrame();
}
///
/// 重绘边框
///
private void InvalidateFrame()
{
if (BorderStyle == BorderStyle.Fixed3D)
SetWindowPos(Handle, (IntPtr)0, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
/// 重绘边框
///
private void InvalidateFrame()
{
if (BorderStyle == BorderStyle.Fixed3D)
SetWindowPos(Handle, (IntPtr)0, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
///
/// 得到合适的客户区大小
///
///
private Size GetRightClientSize()
{
Size size = GetRightTextSize();
int borderwidth = GetBorderWidth();
size.Width += borderwidth * 2;
size.Height += borderwidth * 2;
return size;
}
/// 得到合适的客户区大小
///
///
private Size GetRightClientSize()
{
Size size = GetRightTextSize();
int borderwidth = GetBorderWidth();
size.Width += borderwidth * 2;
size.Height += borderwidth * 2;
return size;
}
private Size GetRightSize()
{
Size size = GetRightClientSize();
int borderwidth = GetBorderWidth();
size.Width += borderwidth * 2;
size.Height += borderwidth * 2;
return size;
}
{
Size size = GetRightClientSize();
int borderwidth = GetBorderWidth();
size.Width += borderwidth * 2;
size.Height += borderwidth * 2;
return size;
}
///
/// 当文本改变时
///
///
protected override void OnTextChanged(EventArgs e)
{
//call base
base.OnTextChanged(e);
//set auto size
AdjustSize();
}
/// 当文本改变时
///
///
protected override void OnTextChanged(EventArgs e)
{
//call base
base.OnTextChanged(e);
//set auto size
AdjustSize();
}
///
/// 字体变化
///
///
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
AdjustSize();
}
/// 字体变化
///
///
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
AdjustSize();
}
///
/// 得到合适的尺寸
///
///
private Size GetRightTextSize()
{
String str = Text;
int len = str.Length;
if (len<2) str = "tt";//至少两个宽度
int count = Lines.Length;
if (count >= 1)
if (Lines[count - 1] == "")
str += "tt";
Size size = TextRenderer.MeasureText(str, Font);
return size;
}
/// 得到合适的尺寸
///
///
private Size GetRightTextSize()
{
String str = Text;
int len = str.Length;
if (len<2) str = "tt";//至少两个宽度
int count = Lines.Length;
if (count >= 1)
if (Lines[count - 1] == "")
str += "tt";
Size size = TextRenderer.MeasureText(str, Font);
return size;
}
//border改变
protected override void OnBorderStyleChanged(EventArgs e)
{
base.OnBorderStyleChanged(e);
AdjustSize();
}
protected override void OnBorderStyleChanged(EventArgs e)
{
base.OnBorderStyleChanged(e);
AdjustSize();
}
///
/// 得到边框宽度
///
///
private int GetBorderWidth()
{
if (BorderStyle == BorderStyle.Fixed3D)
return 2;
else if (BorderStyle == BorderStyle.FixedSingle)
return 1;
else //none
return 0;
}
/// 得到边框宽度
///
///
private int GetBorderWidth()
{
if (BorderStyle == BorderStyle.Fixed3D)
return 2;
else if (BorderStyle == BorderStyle.FixedSingle)
return 1;
else //none
return 0;
}
//隐藏Multiline
[Browsable(false)]
public override bool Multiline
{
get
{
return base.Multiline;
}
set
{
base.Multiline = value;
}
}
[Browsable(false)]
public override bool Multiline
{
get
{
return base.Multiline;
}
set
{
base.Multiline = value;
}
}
//隐藏WordWrap
[Browsable(false)]
public new bool WordWrap
{
get
{
return base.WordWrap;
}
set
{
base.WordWrap = value;
}
}
[Browsable(false)]
public new bool WordWrap
{
get
{
return base.WordWrap;
}
set
{
base.WordWrap = value;
}
}
[DefaultValue(HorizontalAlignment.Center)]//默认值设为Center,并且构造函数为center
public new HorizontalAlignment TextAlign
{
get
{
return base.TextAlign;
}
set
{
base.TextAlign = value;
}
}
public new HorizontalAlignment TextAlign
{
get
{
return base.TextAlign;
}
set
{
base.TextAlign = value;
}
}
[DefaultValue(BorderStyle.FixedSingle)]
public new BorderStyle BorderStyle
{
get
{
return base.BorderStyle;
}
set
{
base.BorderStyle = value;
}
}
public new BorderStyle BorderStyle
{
get
{
return base.BorderStyle;
}
set
{
base.BorderStyle = value;
}
}
private Color m_FrameColor;
[Category("Appearance"), Description("边框的颜色"), DefaultValue(typeof(Color), "Gray")]
public Color FrameColor
{
get
{
return m_FrameColor;
}
set
{
m_FrameColor = value;
InvalidateFrame();
}
}
[Category("Appearance"), Description("边框的颜色"), DefaultValue(typeof(Color), "Gray")]
public Color FrameColor
{
get
{
return m_FrameColor;
}
set
{
m_FrameColor = value;
InvalidateFrame();
}
}
#region winodws api
private const uint WM_NCPAINT = 0x0085;
private const uint WM_PAINT = 0x000F;
[DllImport("user32")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("user32")]
private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOMOVE = 0x0002;
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOREDRAW = 0x0008;
private const int SWP_NOACTIVATE = 0x0010;
private const int SWP_FRAMECHANGED = 0x0020; /* The frame changed: send WM_NCCALCSIZE */
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
#endregion
private const uint WM_NCPAINT = 0x0085;
private const uint WM_PAINT = 0x000F;
[DllImport("user32")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("user32")]
private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOMOVE = 0x0002;
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOREDRAW = 0x0008;
private const int SWP_NOACTIVATE = 0x0010;
private const int SWP_FRAMECHANGED = 0x0020; /* The frame changed: send WM_NCCALCSIZE */
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
#endregion
///
/// 重载wndproc
///
///
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT)
DrawFixedSingle();
if (m.Msg == WM_NCPAINT)
DrawFixed3D();
}
/// 重载wndproc
///
///
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT)
DrawFixedSingle();
if (m.Msg == WM_NCPAINT)
DrawFixed3D();
}
///
/// 绘制非客户区边框
///
private void DrawFixed3D()
{
if (BorderStyle == BorderStyle.Fixed3D)
{
Pen pen = new Pen(this.m_FrameColor);
IntPtr windc = GetWindowDC(Handle);
Graphics borderG = Graphics.FromHdc(windc);
borderG.DrawRectangle(pen, 0, 0, Size.Width - 1, Size.Height - 1);
ReleaseDC(Handle, windc);
borderG.Dispose();
pen.Dispose();
}
}
/// 绘制非客户区边框
///
private void DrawFixed3D()
{
if (BorderStyle == BorderStyle.Fixed3D)
{
Pen pen = new Pen(this.m_FrameColor);
IntPtr windc = GetWindowDC(Handle);
Graphics borderG = Graphics.FromHdc(windc);
borderG.DrawRectangle(pen, 0, 0, Size.Width - 1, Size.Height - 1);
ReleaseDC(Handle, windc);
borderG.Dispose();
pen.Dispose();
}
}
///
/// 绘制客户区边框
///
private void DrawFixedSingle()
{
if (BorderStyle == BorderStyle.FixedSingle)
{
Pen pen = new Pen(this.m_FrameColor);
Graphics dc = Graphics.FromHwnd(Handle);
dc.DrawRectangle(pen, 0, 0, Size.Width - 1, Size.Height - 1);
dc.Dispose();
pen.Dispose();
}
}
/// 绘制客户区边框
///
private void DrawFixedSingle()
{
if (BorderStyle == BorderStyle.FixedSingle)
{
Pen pen = new Pen(this.m_FrameColor);
Graphics dc = Graphics.FromHwnd(Handle);
dc.DrawRectangle(pen, 0, 0, Size.Width - 1, Size.Height - 1);
dc.Dispose();
pen.Dispose();
}
}
//锁定的不变位置
private LockPosition m_LockPosition;
[Category("Layout"), Description("锁定的不变位置"), DefaultValue(LockPosition.LockTopLeft)]
public LockPosition TextLockPosition//修改名字为TextLockPosition,使得InitializeComponent在text改变后加载TextLockPosition属性
{
get
{
return m_LockPosition;
}
set
{
m_LockPosition = value;
UpdateunchangeLocation();
}
}
private LockPosition m_LockPosition;
[Category("Layout"), Description("锁定的不变位置"), DefaultValue(LockPosition.LockTopLeft)]
public LockPosition TextLockPosition//修改名字为TextLockPosition,使得InitializeComponent在text改变后加载TextLockPosition属性
{
get
{
return m_LockPosition;
}
set
{
m_LockPosition = value;
UpdateunchangeLocation();
}
}
private void UpdateunchangeLocation()
{
//求不变的位置坐标
switch (m_LockPosition)//求保持的位置
{
case LockPosition.LockTopLeft:
m_unchangeLocation = Location;
break;
case LockPosition.LockTopHCenter:
m_unchangeLocation = new Point(Location.X + Size.Width / 2, Location.Y);
break;
case LockPosition.LockTopRight:
m_unchangeLocation = new Point(Location.X + Size.Width, Location.Y);
break;
case LockPosition.LockVCenterRight:
m_unchangeLocation = new Point(Location.X + Size.Width, Location.Y + Size.Height / 2);
break;
case LockPosition.LockBottomRight:
m_unchangeLocation = new Point(Location.X + Size.Width, Location.Y + Size.Height);
break;
case LockPosition.LockBottomHCenter:
m_unchangeLocation = new Point(Location.X + Size.Width / 2, Location.Y + Size.Height);
break;
case LockPosition.LockBottomLeft:
m_unchangeLocation = new Point(Location.X, Location.Y + Size.Height);
break;
case LockPosition.LockVCenterLeft:
m_unchangeLocation = new Point(Location.X, Location.Y + Size.Height / 2);
break;
case LockPosition.LockVCenterHCenter:
m_unchangeLocation = new Point(Location.X + Size.Width / 2, Location.Y + Size.Height / 2);
break;
}
m_unchangleLocationInit = true;
}
{
//求不变的位置坐标
switch (m_LockPosition)//求保持的位置
{
case LockPosition.LockTopLeft:
m_unchangeLocation = Location;
break;
case LockPosition.LockTopHCenter:
m_unchangeLocation = new Point(Location.X + Size.Width / 2, Location.Y);
break;
case LockPosition.LockTopRight:
m_unchangeLocation = new Point(Location.X + Size.Width, Location.Y);
break;
case LockPosition.LockVCenterRight:
m_unchangeLocation = new Point(Location.X + Size.Width, Location.Y + Size.Height / 2);
break;
case LockPosition.LockBottomRight:
m_unchangeLocation = new Point(Location.X + Size.Width, Location.Y + Size.Height);
break;
case LockPosition.LockBottomHCenter:
m_unchangeLocation = new Point(Location.X + Size.Width / 2, Location.Y + Size.Height);
break;
case LockPosition.LockBottomLeft:
m_unchangeLocation = new Point(Location.X, Location.Y + Size.Height);
break;
case LockPosition.LockVCenterLeft:
m_unchangeLocation = new Point(Location.X, Location.Y + Size.Height / 2);
break;
case LockPosition.LockVCenterHCenter:
m_unchangeLocation = new Point(Location.X + Size.Width / 2, Location.Y + Size.Height / 2);
break;
}
m_unchangleLocationInit = true;
}
//重载禁止调整高度
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
{
Size size = GetRightSize();
if (width != size.Width && ((specified & BoundsSpecified.Width) == BoundsSpecified.Width))
width = size.Width;
if (height != size.Height && ((specified & BoundsSpecified.Height) == BoundsSpecified.Height))
height = size.Height;
//call base
base.SetBoundsCore(x, y, width, height, specified);
}
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
{
Size size = GetRightSize();
if (width != size.Width && ((specified & BoundsSpecified.Width) == BoundsSpecified.Width))
width = size.Width;
if (height != size.Height && ((specified & BoundsSpecified.Height) == BoundsSpecified.Height))
height = size.Height;
//call base
base.SetBoundsCore(x, y, width, height, specified);
}
///
/// 覆盖Location
///
public new Point Location
{
get
{
return base.Location;
}
set
{
base.Location = value;
UpdateunchangeLocation();
}
}
}
}
/// 覆盖Location
///
public new Point Location
{
get
{
return base.Location;
}
set
{
base.Location = value;
UpdateunchangeLocation();
}
}
}
}
有兴趣下载的: