tags:

views:

144

answers:

2

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?

+2  A: 

The best way is to design a good data structure for storing your text and which also considers hit-testing. One example could be to split the text into blocks (words, lines or paragraphs depending on what you need). Then each such block should have a bounding-box which should be recomputed in any formatting operations. Also consider caret positions in your design.

Once you have such facility it becomes very easy to do hit-testing, just use the bounding boxes. It will also help in subsequent operations like highlighting a particular portion of text.

Sesh
FormattedText already allows me to get boxes for ranges of text, but I need actual selection; so I'd probably need boxes for each char, and that'd quickly get messy. It's a possible solution, but not a very good one...
Eric
There is a fly-weight or some other design pattern that addresses similar problem (bbox for single char). Can you please check the Gamma book on design patterns? its there in it.
Sesh
+1  A: 

Completely agree with Sesh - the easiest way you're going to get away with not re-implementing a whole load of FormattedText functionality is going to be by splitting up the individual items you want to hit-test into their own controls/inlines.

Consider using a TextBlock and adding each word as it's own Inline ( or ), then either bind to the inline's IsMouseDirectlyOver property, our add delegates to the MouseEnter & MouseLeave events.

If you want to do pixel-level hit testing of the actual glyphs (i.e. is the mouse exactly in the dot of this 'i'), then you'll need to use GlyphRuns and do manual hit testing on the glyphs (read: hard work).

Mark