這些天項目中需要用到自動適應文本大小的文本框控件。
本以爲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
{
/// <summary>
/// 鎖定的位置
/// </summary>
public enum LockPosition
{
LockTopLeft,
LockTopHCenter,
LockTopRight,
LockVCenterRight,
LockBottomRight,
LockBottomHCenter,
LockBottomLeft,
LockVCenterLeft,
LockVCenterHCenter
}
/// <summary>
/// 自動適應文本大小的文本框控件
/// 繼承自TextBox
/// 2007 9 30 bug:鍵盤輸入時,並不能保持中心點不變,原因:每次變化去求前一次的
/// 保持的位置,長久下來累計誤差比較大,因爲中間除2了,可能會舍入。修改爲保存好不變的位置
/// </summary>
public class AutoSizeTextBox : TextBox
{
public AutoSizeTextBox()
{
//默認多行
base.Multiline = true;
base.WordWrap = false;
base.TextAlign = HorizontalAlignment.Center;
base.BorderStyle = BorderStyle.FixedSingle;
{
/// <summary>
/// 鎖定的位置
/// </summary>
public enum LockPosition
{
LockTopLeft,
LockTopHCenter,
LockTopRight,
LockVCenterRight,
LockBottomRight,
LockBottomHCenter,
LockBottomLeft,
LockVCenterLeft,
LockVCenterHCenter
}
/// <summary>
/// 自動適應文本大小的文本框控件
/// 繼承自TextBox
/// 2007 9 30 bug:鍵盤輸入時,並不能保持中心點不變,原因:每次變化去求前一次的
/// 保持的位置,長久下來累計誤差比較大,因爲中間除2了,可能會舍入。修改爲保存好不變的位置
/// </summary>
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;
}
/// <summary>
/// 不變化的位置座標
/// </summary>
private Point m_unchangeLocation;
bool m_unchangleLocationInit;//是否已經初始化m_unchangeLocation
/// 不變化的位置座標
/// </summary>
private Point m_unchangeLocation;
bool m_unchangleLocationInit;//是否已經初始化m_unchangeLocation
/// <summary>
/// 調整大小
/// </summary>
private void AdjustSize()
{
//調整大小
ClientSize = GetRightClientSize();
/// 調整大小
/// </summary>
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();
}
/// <summary>
/// 重繪邊框
/// </summary>
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);
}
/// 重繪邊框
/// </summary>
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);
}
/// <summary>
/// 得到合適的客戶區大小
/// </summary>
/// <returns></returns>
private Size GetRightClientSize()
{
Size size = GetRightTextSize();
int borderwidth = GetBorderWidth();
size.Width += borderwidth * 2;
size.Height += borderwidth * 2;
return size;
}
/// 得到合適的客戶區大小
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 當文本改變時
/// </summary>
/// <param name="e"></param>
protected override void OnTextChanged(EventArgs e)
{
//call base
base.OnTextChanged(e);
//set auto size
AdjustSize();
}
/// 當文本改變時
/// </summary>
/// <param name="e"></param>
protected override void OnTextChanged(EventArgs e)
{
//call base
base.OnTextChanged(e);
//set auto size
AdjustSize();
}
/// <summary>
/// 字體變化
/// </summary>
/// <param name="e"></param>
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
AdjustSize();
}
/// 字體變化
/// </summary>
/// <param name="e"></param>
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
AdjustSize();
}
/// <summary>
/// 得到合適的尺寸
/// </summary>
/// <returns></returns>
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;
}
/// 得到合適的尺寸
/// </summary>
/// <returns></returns>
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();
}
/// <summary>
/// 得到邊框寬度
/// </summary>
/// <returns></returns>
private int GetBorderWidth()
{
if (BorderStyle == BorderStyle.Fixed3D)
return 2;
else if (BorderStyle == BorderStyle.FixedSingle)
return 1;
else //none
return 0;
}
/// 得到邊框寬度
/// </summary>
/// <returns></returns>
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
/// <summary>
/// 重載wndproc
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT)
DrawFixedSingle();
if (m.Msg == WM_NCPAINT)
DrawFixed3D();
}
/// 重載wndproc
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT)
DrawFixedSingle();
if (m.Msg == WM_NCPAINT)
DrawFixed3D();
}
/// <summary>
/// 繪製非客戶區邊框
/// </summary>
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();
}
}
/// 繪製非客戶區邊框
/// </summary>
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();
}
}
/// <summary>
/// 繪製客戶區邊框
/// </summary>
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();
}
}
/// 繪製客戶區邊框
/// </summary>
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);
}
/// <summary>
/// 覆蓋Location
/// </summary>
public new Point Location
{
get
{
return base.Location;
}
set
{
base.Location = value;
UpdateunchangeLocation();
}
}
}
}
/// 覆蓋Location
/// </summary>
public new Point Location
{
get
{
return base.Location;
}
set
{
base.Location = value;
UpdateunchangeLocation();
}
}
}
}
有興趣下載的: