I would say that the easiest way is to use automation interfaces:
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
FlowDocument flowDocument = ...;
Point point = ...;
var peer = new DocumentAutomationPeer(flowDocument);
var textProvider = (ITextProvider)peer.GetPattern(PatternInterface.Text);
var rangeProvider = textProvider.RangeFromPoint(point);
ITextProvider UIAutomationProvider. , . UIAutomationTypes .
, , FlowDocument:
var peer = new DocumentAutomationPeer(flowDocument);
var peer = new DocumentAutomationPeer(textBlock);
var peer = new DocumentAutomationPeer(flowDocumentScrollViewer);
var peer = new TextBoxAutomationPeer(textBox);
var peer = new RichTextBoxAutomationPeer(richTextBox);
, , ITextRangeProvider TextPointer , .
ScreenPointToTextPointer . , :
private void Window_MouseMove(object sender, MouseEventArgs e)
{
var document = this.Viewer.Document;
var screenPoint = PointToScreen(e.GetPosition(this));
TextPointer pointer = document.ScreenPointToTextPointer(screenPoint);
new TextRange(document.ContentStart, pointer).ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
new TextRange(pointer, document.ContentEnd).ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Normal);
}
:
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Automation.Text;
public static class DocumentExtensions
{
public static TextPointer ScreenPointToTextPointer(this FlowDocument document, Point screenPoint)
{
var peer = new DocumentAutomationPeer(document);
var textProvider = (ITextProvider)peer.GetPattern(PatternInterface.Text);
var rangeProvider = textProvider.RangeFromPoint(screenPoint);
rangeProvider.MoveEndpointByUnit(TextPatternRangeEndpoint.Start, TextUnit.Document, 1);
int charsBeforePoint = rangeProvider.GetText(int.MaxValue).Length;
var pointer = document.ContentStart.GetPositionAtOffset(charsBeforePoint);
for(int i=0; i<10; i++)
{
int error = charsBeforePoint - new TextRange(document.ContentStart, pointer).Text.Length;
if(error==0) break;
pointer = pointer.GetPositionAtOffset(error);
}
return pointer;
}
}
PointToScreen MouseMove, .