拡張可能なWinForms TextBox
-
05-07-2019 - |
質問
テキストを1行で入力するための高さから開始するWindowsフォームアプリケーションでテキストボックスを作成しました。しかし、ユーザーがコントロール内にラップされたテキストを入力した場合、テキストボックスの高さを自動的に増加させたいと思います。
現在、このテキストボックスには、multilineプロパティとwordwrapプロパティがtrueに設定されています。 TextChangedイベントを使用して、テキストがラップされたタイミングを判別しようとしましたが、これに役立つプロパティが見つかりません。 Linesプロパティは、折り返されたテキストに関するヘルプを提供しません。ユーザーがEnterキーを押して新しい行を開始したテキストのみ。
テキストがテキストボックスの幅を超えて折り返すたびにテキストボックスの高さを拡大するにはどうすればよいですか?
解決
他の人が投稿したのと同じ種類のアイデア、これをtextChangedイベントに入れます:
Dim s As SizeF = TextRenderer.MeasureText(txt.Text, txt.Font, txt.ClientRectangle.Size, TextFormatFlags.WordBreak)
txt.Height = CInt(s.Height)
何らかの最小高さを必要とし、場合によってはパディングを指定する必要がありますが、これは機能します。
他のヒント
代わりにRichTextBoxを使用したい場合(これは、私の経験では、気まぐれなコントロールの一種です)、ResortTextイベントを使用して、新しい必要なサイズを指定できます:
private void HandleContentsResized(object sender, ContentsResizedEvenetArgs e)
{
int newheight = e.NewRectangle.Height;
}
別のプロジェクトのラベルコントロール用にこれを書きました。私はどこかと思うコードプロジェクトからコードを取得しました。テキストボックスへの変更は、ベースの変更と同じくらい簡単です。
public class GrowLabel : Label
{
private bool _growing;
//public bool GrowFontSize { get; set; }
public GrowLabel()
{
AutoSize = false;
//GrowFontSize = false;
}
public override sealed bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = value; }
}
private void ResizeLabel()
{
if (_growing) return;
try
{
_growing = true;
var sz = new Size(Width, Int32.MaxValue);
sz = TextRenderer.MeasureText(Text, Font, sz, TextFormatFlags.WordBreak);
Height = sz.Height;
}
finally
{
_growing = false;
}
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
ResizeLabel();
}
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
ResizeLabel();
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
ResizeLabel();
}
}
AdamSaneの投稿は役に立ちましたが、テキストボックスは拡大しませんでした。いくつか変更を加えたいと思います。私のMODは以下です:
class GrowTextBox : TextBox
{
private double m_growIndex = 0.0;
private Timer m_timer;
public GrowTextBox()
{
AutoSize = false;
this.Height = 20;
// Without the timer, I got a lot of AccessViolationException in the System.Windows.Forms.dll.
m_timer = new Timer();
m_timer.Interval = 1;
m_timer.Enabled = false;
m_timer.Tick += new EventHandler(m_timer_Tick);
this.KeyDown += new KeyEventHandler(GrowTextBox_KeyDown);
}
void GrowTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
{
this.SelectAll();
}
}
void m_timer_Tick(object sender, EventArgs e)
{
var sz = new Size(Width, Int32.MaxValue);
sz = TextRenderer.MeasureText(Text, Font, sz, TextFormatFlags.TextBoxControl);
m_growIndex = (double)(sz.Width / (double)Width);
if (m_growIndex > 0)
Multiline = true;
else
Multiline = false;
int tempHeight = (int)(20 * m_growIndex);
if (tempHeight <= 20)
Height = 20;
else
Height = tempHeight;
m_timer.Enabled = false;
}
public override sealed bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = value; }
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
m_timer.Enabled = true;
}
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
m_timer.Enabled = true;
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
m_timer.Enabled = true;
}
}
次のコードを使用していますが、10行目までは成功し、1文字減りますが、これはうまくいきます。 -7や-12のような乱数については聞かないでください。それらはパディングと関係があります
private void txbDescription_TextChanged(object sender, EventArgs e)
{
SizeF s = TextRenderer.MeasureText(txbDescription.Text, txbDescription.Font, txbDescription.ClientRectangle.Size, TextFormatFlags.TextBoxControl);
int lines = (int)Math.Ceiling((decimal)Convert.ToInt32(s.Width - 7) / ((decimal)txbDescription.Width - 12));
if (lines == 0)
{
txbDescription.Height = 20;
}
else
{
txbDescription.Height = 20 + (lines - 1) * 13;
}
}
残念ながら、詳細を提供することはできませんが、おそらくカスタム実装を行う必要があります。
新しいテキストボックスタイプ-ExpandableTextBox-を派生させた後、手動で実装する必要があります。
これは、あなたが探しているものにも関連があるようです: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/11dfb280-b113-4ddf-ad59-788f78d2995a