質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

4726閲覧

C# Labelの行数を取得したいです。

.......

総合スコア23

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2021/11/06 04:09

編集2021/11/07 08:08

タイトルの通りWinForms用のLabelの行数を取得したいです。
行数を取得し、
Label1行の高さ×行数で無限に高さを設定したいです。
一応、"\r\n"の数を調べればわかることですが、自動改行をtrueにしてるので分かりません。labelの高さを取得して、それを割るなどして改行した数を取得しようとしましたが、正確ではないので没になりました。

サンプルコード

C#

1Label label = new Label(); 2label.AutoSize = false; //<-falseにする事で自動折り返しにしている。 3label.Width = 400; 4label.Text = “aaaaaaaaaaaaaaaaaaa”; 5 6//heightはLabelの1行の高さです。ここでは既に代入してることにしています。 7int lines = label.PreferredHeight / height;//<-ここでlabelの高さのズレであまりが出てしまいます。一回ぐらいならいいのですが、繰り返すと値にズレが生じてしまいます。

このズレを生じさせないか、他の案があれば、解決できます。

開発環境

Visual Studios 2019
Framework.NET 4.7
windows10 Home

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/11/06 04:26

何の Label ですか? WinForms 用、WPF 用、ASP.NET Web Forms 用といろいろあるのですよ。
.......

2021/11/06 04:30

WinForms用です。
退会済みユーザー

退会済みユーザー

2021/11/06 04:33

質問欄に追記してください。ここは「質問への追記・修正の依頼」の場所ですので。 それから、自分で実装したサンプルコードを書くなどして、どこまで自分で実装していて、どこに躓いていて、何か分かれば解決するかをもう少し具体的に書けないでしょうか?
.......

2021/11/06 04:37

質問欄にはとっくに追加しています。
退会済みユーザー

退会済みユーザー

2021/11/06 08:42 編集

無理っぽいですね。 行数を取得して何がしたいのかそもそものやりたいことを書いた方が良いと思います。違った観点での提案が出てくるかもしれません。一般的によくある話なら、長い WinForms アプリの歴史の中で先人が解決策を見つけているという例は多々あって、ここにも答えを持っている人はいるだろうし、ググれば見つかることも多いはず。
退会済みユーザー

退会済みユーザー

2021/11/07 00:25

欧文の word wrap、日本語の禁則処理は Label.Text で表示される文字にも適用されるようですので、やっぱり無理では? (不可能とは言いませんが)
guest

回答1

0

ベストアンサー

作ってみました。(いろいろ改善の余地はありそうですが)
UseCompatibleTextRendering = true のときは大丈夫なのですが、
false のときは、テキストをラベルに代入して描画しないと
TextRenderer.MeasureText が正しい値を返さないようです。

C#

1using System; 2using System.Drawing; 3using System.Reflection; 4using System.Text; 5using System.Windows.Forms; 6 7static class UTL 8{ 9 // テキストをラベルに表示したときの行数を取得する 10 public static int GetLines(Label label, string text) 11 { 12 // UseCompatibleTextRendering = false のときは、代入しないと正しい値が求まらない 13 label.Text = text; 14 // テキストをラベルに表示したときの高さを取得 15 int textHeight = UTL.GetTextHeight(label, text); 16 17 int lines = 1; // 1行から開始(ここは工夫が必要かも) 18 while (true) 19 { 20 // n行の高さを求める 21 int linesHeight = UTL.GetTextHeight(label, lines); 22 // n行の高さがテキストの高さ以上になったら終了 23 if (linesHeight >= textHeight) 24 { 25 return lines; 26 } 27 lines++; 28 } 29 } 30 31 private static int GetTextHeight(Label label, string text) 32 { 33 Rectangle face = DeflateRect(label.ClientRectangle, label.Padding); 34 using (var g = label.CreateGraphics()) 35 { 36 if (label.UseCompatibleTextRendering) 37 { 38 using (StringFormat stringFormat = CreateStringFormat(label)) 39 { 40 SizeF size = g.MeasureString(text, label.Font, face.Width, stringFormat); 41 return (int)size.Height; 42 } 43 } 44 else 45 { 46 TextFormatFlags flags = CreateTextFormatFlags(label); 47 Size size = TextRenderer.MeasureText(g, text, label.Font, new Size(face.Width, int.MaxValue), flags); 48 return size.Height; 49 } 50 } 51 } 52 53 private static Rectangle DeflateRect(Rectangle rect, Padding padding) 54 { 55 rect.X += padding.Left; 56 rect.Y += padding.Top; 57 rect.Width -= padding.Horizontal; 58 rect.Height -= padding.Vertical; 59 return rect; 60 } 61 62 private static int GetTextHeight(Label label, int lines) 63 { 64 var sb = new StringBuilder(); 65 for (int i = 1; i <= lines; i++) 66 { 67 sb.AppendLine(); 68 } 69 return GetTextHeight(label, sb.ToString()); 70 } 71 72 // ロジックを転記するのが面倒なのでリフレクションで呼び出す。 73 74 private static StringFormat CreateStringFormat(Label label) 75 { 76 Type type = typeof(Label); 77 MethodInfo mi = type.GetMethod( 78 "CreateStringFormat", 79 BindingFlags.Instance | BindingFlags.NonPublic, 80 null, 81 new Type[0], 82 new ParameterModifier[0]); 83 return (StringFormat)mi.Invoke(label, null); 84 } 85 86 private static TextFormatFlags CreateTextFormatFlags(Label label) 87 { 88 Type type = typeof(Label); 89 MethodInfo mi = type.GetMethod( 90 "CreateTextFormatFlags", 91 BindingFlags.Instance | BindingFlags.NonPublic, 92 null, 93 new Type[0], 94 new ParameterModifier[0]); 95 return (TextFormatFlags)mi.Invoke(label, null); 96 } 97}

#使い方
デザイン

C#

1 using System; 2 using System.Windows.Forms; 3 4 public partial class Form1 : Form 5 { 6 public Form1() 7 { 8 InitializeComponent(); 9 } 10 11 private void checkBox1_CheckedChanged(object sender, EventArgs e) 12 { 13 label1.UseCompatibleTextRendering = ((CheckBox)sender).Checked; 14 textBox1_TextChanged(textBox1, EventArgs.Empty); 15 } 16 17 private void textBox1_TextChanged(object sender, EventArgs e) 18 { 19 int lines = UTL.GetLines(label1, ((TextBox)sender).Text); 20 label2.Text = string.Format("{0}行です。", lines); 21 } 22 }

投稿2021/11/07 05:59

KOZ6.0

総合スコア2707

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

.......

2021/11/07 07:56

回答ありがとうございます。 試したところ、正確でとても使いやすかったです。 ですが、本当に申し訳ないのですが、 SurferOnWwwさんが仰っていた、 "行数を取得して何がしたいのかそもそものやりたいことを書いた方が良いと思います。違った観点での提案が出てくるかもしれません。"を見て、 私は文字列の行数を取得して、Labelの1行の高さ×行数として、textboxのように自動改行+無限にLabelの高さを無限に設定しようと思っており、違う観点から見て AutoSizeをfalseにしていたのをAutoSizeをtrueにし、Labelの長さが一定を超えると改行するという案を思いつき、今までコードを書いており、今さっき完成しました。 public partial class Form1 : Form { Label label = new Label(); Label label2 = new Label(); int Count; int lines = 1; int height; public Form1() { label.Location = new Point(0, 0); label.AutoSize = true; label2.Location = new Point(0, 300); label2.AutoSize = true; this.Controls.Add(label); this.Controls.Add(label2); this.KeyPress += new KeyPressEventHandler(KeyPressEventHandler); } void KeyPressEventHandler(object sender, KeyPressEventArgs e) { if (Count == 0) {         //labelの未尾に入力した文字を代入 label.Text += e.KeyChar; //labelの長さが一定を超えると{}を実行 if (label.PreferredWidth >= Screen.PrimaryScreen.Bounds.Width - 20) { Count = 1; //labelの高さをheightに代入 height = label.PreferredHeight; } } if (Count == 1) { label2.Text += e.KeyChar; if (label2.PreferredWidth >= Screen.PrimaryScreen.Bounds.Width - 20) { lines++;            //label.Textに改行 + label2の文字列を代入 label.Text += "\r\n" + label2.Text; //label2のlocationの高さをLabelの1行の高さ×行数 label2.Location = new Point(0, height * lines); //label2の文字列をリセット label2.Text = ""; } } } } これは、label2の長さが一定を超えると、labelに改行+label2の文字列を代入し、lines(行数)を1プラスし label2のLocationにheight×linesとやっております。これでtextboxのように自動で改行+高さ無限にできます。コードの長さなどの理由でこのコードを使うことにします。 お時間を無駄にさせてしまい申し訳ございません。ですが、いつか役に立つ時が来るかもしれないので、 その時は喜んで、使わせてもらいます。
.......

2021/11/20 01:42

private void textBox1_TextChanged(object sender, EventArgs e) { height = TextBox(textBox1, height); label1.Text = height.ToString() + "行です"; } public static int TextBox(TextBox textbox, int height) { Size size = TextRenderer.MeasureText(textbox.Text, textbox.Font); if(size.Width >= textbox.Width*height) { textbox.Height = textbox.Height + 12; height++; } return height; } 少し改善しました。こちらの方が使いやすいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問