自动适应文本内容的文本框控件(winform)
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://happyoldbear.blog.51cto.com/231048/44258 |
这些天项目中需要用到自动适应文本大小的文本框控件。
本以为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; 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; m_LockPosition = LockPosition.LockTopLeft;
m_FrameColor = Color.Gray; m_unchangleLocationInit = false; } /// <summary>
/// 不变化的位置坐标 /// </summary> private Point m_unchangeLocation; bool m_unchangleLocationInit;//是否已经初始化m_unchangeLocation /// <summary>
/// 调整大小 /// </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(); } /// <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>
/// 得到合适的客户区大小 /// </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; } /// <summary>
/// 当文本改变时 /// </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>
/// 得到合适的尺寸 /// </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(); } /// <summary>
/// 得到边框宽度 /// </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; } } //隐藏WordWrap
[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; } } [DefaultValue(BorderStyle.FixedSingle)]
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(); } } #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 /// <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(); } /// <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>
/// 绘制客户区边框 /// </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 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; } //重载禁止调整高度
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(); } } } } 有兴趣下载的:
本文出自 “欢乐老熊” 博客,请务必保留此出处http://happyoldbear.blog.51cto.com/231048/44258 本文出自 51CTO.COM技术博客 |
附件下载:
源代码
源代码


lijun4183
博客统计信息
热门文章
最新评论
友情链接
