1

ワードラップとテキストの位置をシミュレートするために C# で文字列幅を取得しようとしています (現在は richTextBox に記述されています)。

richTextBox のサイズは 555x454 px で、等幅フォント Courier New 12pt を使用しています。

TextRenderer.MeasureText()私もGraphics.MeasureString()方法を試しました。

TextRendererGraphics通常は1行に収まるテキストよりも大きな値を返していたため、コードを別の行に折り返す必要があると判断しました。

しかし、Graphics一方で、私のコードは、特定の文字列が元の richTextBox に出力されるよりも短いと判断したため、間違った場所で次の行に折り返されました。

デバッグ中に、計算された幅が異なることがわかりました。これは、等幅フォントを使用しているため、すべての文字の幅が同じである必要があるため、奇妙です。しかし、私はこのようなものを取得しますGraphics.MeasureString()(例: ' ' - 5.33333254、'S' - 15.2239571、'\r' - 5.328125)。

C# で文字列の幅を正確に計算し、ワードラップをシミュレートして、特定のテキスト位置をピクセル単位で決定するにはどうすればよいですか?

等幅フォントを使用すると、文字によって幅が異なるのはなぜですか?

注: 私は個人的なアイ トラッキング プロジェクトに取り組んでおり、実験中に特定のテキストが配置された場所を特定して、ユーザーがどの単語を見ていたかを判断したいと考えています。たとえば。tユーザーがポイント [256,350]px を見ていましたが、この場所でメソッドの呼び出しがあることがわかりましたWriteLine。私のターゲットの視覚的刺激は、インデント、タブ、行末が編集可能なテキスト領域に配置されたソース コードです (将来的には、単純なオンライン ソース コード エディターになる可能性があります)。

これが私のコードです:

    //before method call
    var font = new Font("Courier New", 12, GraphicsUnit.Point);
    var graphics = this.CreateGraphics();
    var wrapped = sourceCode.WordWrap(font, 555, graphics);

    public static List<string> WordWrap(this string sourceCode, Font font, int width, Graphics g)
        {
            var wrappedText = new List<string>(); // output
            var actualLine = new StringBuilder();
            var actualWidth = 0.0f; // temp var for computing actual string length
            var lines = Regex.Split(sourceCode, @"(?<=\r\n)"); // split input to lines and maintain line ending \r\n where they are
            string[] wordsOfLine;

            foreach (var line in lines)
            {
                wordsOfLine = Regex.Split(line, @"( |\t)").Where(s => !s.Equals("")).ToArray(); // split line by tabs and spaces and maintain delimiters separately

                foreach (string word in wordsOfLine)
                {
                    var wordWidth = g.MeasureString(word, font).Width; // compute width of word

                    if (actualWidth + wordWidth > width) // if actual line width is grather than width of text area
                    {
                        wrappedText.Add(actualLine.ToString()); // add line to list
                        actualLine.Clear(); // clear StringBuilder
                        actualWidth = 0; // zero actual line width
                    }

                    actualLine.Append(word); // add word to actual line
                    actualWidth += wordWidth; // add word width to actual line width
                }

                if (actualLine.Length > 0) // if there is something in actual line add it to list
                {
                    wrappedText.Add(actualLine.ToString());
                }
                actualLine.Clear(); // clear vars
                actualWidth = 0;
            }

            return wrappedText;
        }
4

2 に答える 2