ycl*_*ine 4 .net wpf flowdocument
我想得到一个用户在FlowDocument中点击的单词.
我目前正在为文档中的每个Run添加一个事件处理程序,并在单击的Run中迭代TextPointers,在每个Run上调用GetCharacterRect()并检查矩形是否包含该点.
但是,当在长时间运行结束时发生咔嗒声时,这需要> 10秒.
有没有更有效的方法?
我想说最简单的方法是使用Automation接口:
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);
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
更新
我试过这个并且效果很好,虽然从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);
}
Run Code Online (Sandbox Code Playgroud)
以下是扩展方法的代码:
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Automation.Text;
public static class DocumentExtensions
{
// Point is specified relative to the given visual
public static TextPointer ScreenPointToTextPointer(this FlowDocument document, Point screenPoint)
{
// Get text before point using automation
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;
// Find the pointer that corresponds to the TextPointer
var pointer = document.ContentStart.GetPositionAtOffset(charsBeforePoint);
// Adjust for difference between "text offset" and actual number of characters before pointer
for(int i=0; i<10; i++) // Limit to 10 adjustments
{
int error = charsBeforePoint - new TextRange(document.ContentStart, pointer).Text.Length;
if(error==0) break;
pointer = pointer.GetPositionAtOffset(error);
}
return pointer;
}
}
Run Code Online (Sandbox Code Playgroud)
另请注意,在示例MouseMove方法中使用PointToScreen来获取要传递到扩展方法的屏幕点.
| 归档时间: |
|
| 查看次数: |
2065 次 |
| 最近记录: |