1

I'm rendering text using FormattedText, but there does appear to be any way to perform per-char hit testing on the rendered output. It's read-only, so I basically only need selection, no editing.

I'd use RichTextBox or similar, but I need to output text based on control codes embed in the text itself, so they don't always nest, which makes building the right Inline elements very complex. I'm also a bit worried about performance with that solution; I have a large number of lines, and new lines are appended often.

I've looked at GlyphRun, it appears I could get hit-testing from it or a related class, but I'd be reimplementing a lot of functionality, and it seems like there should be a simpler way...

Does anyone know of a good way to implement this?

4

4 に答える 4

4

FormattedText オブジェクトから各文字のジオメトリを取得し、各文字の境界を使用してヒット テストを行うことができます。

var geometry = (GeometryGroup)((GeometryGroup)text.BuildGeometry(new Point(0, 0))).Children[0];
foreach (var c in geometry.Children)
{
  if (c.Bounds.Contains(point))
    return index;
  index++;
}

OnRender では、書式設定されたテキストの代わりにこれらのジオメトリ オブジェクトをレンダリングできます。

于 2011-07-27T05:31:27.393 に答える
3

最良の方法は、テキストを格納するための優れたデータ構造を設計し、ヒット テストも考慮に入れることです。一例として、テキストをブロック (必要に応じて単語、行、または段落) に分割することが考えられます。次に、そのような各ブロックには、フォーマット操作で再計算する必要がある境界ボックスが必要です。また、設計におけるキャレットの位置も考慮してください。

このような機能があれば、ヒット テストを非常に簡単に実行できます。バウンディング ボックスを使用するだけです。また、テキストの特定の部分を強調表示するなど、その後の操作にも役立ちます。

于 2009-02-12T04:44:50.573 に答える
1

私はパーティーに非常に遅れています.パーティーが終わっておらず、実際のキャラクタージオメトリが必要ない場合は、次のような便利なものを見つけました:

 for (int i = 0; i < FormattedText.Text.Length; i++)
 {
            characterHighlightGeometry = FormattedText.BuildHighlightGeometry(new Point(), i, 1);
            CharacterHighlightGeometries.Children.Add(characterHighlightGeometry);
 }

BuildGeometry() には、キャラクターの実際のパス ジオメトリのみが含まれます。BuildHighlightGeometry() は、スペースを含むすべての文字の外側の境界を生成するため、スペースへのインデックスは次の方法で見つけることができます。

 foreach (var c in CharacterHighlightGeometries.Children)
        {
            if (c.Bounds.Contains(centerpoint))
            {
                q = c;
                cpos = index;
                break;
            }
            index++;
        }

お役に立てれば。

于 2015-01-16T19:58:20.573 に答える
1

Sesh に完全に同意します。FormattedText 機能の負荷全体を再実装せずに済む最も簡単な方法は、ヒット テストする個々の項目を独自のコントロール/インラインに分割することです。

TextBlock を使用し、各単語を独自の Inline ( または ) として追加することを検討してから、インラインの IsMouseDirectlyOver プロパティにバインドし、MouseEnter & MouseLeave イベントにデリゲートを追加します。

実際のグリフのピクセル レベルのヒット テストを実行する場合 (つまり、マウスがこの 'i' のドットに正確にある場合)、GlyphRuns を使用して、グリフで手動のヒット テストを実行する必要があります (読み取り: ハード仕事)。

于 2009-02-12T08:15:38.100 に答える