/ / Ako môžem získať TextPointer kliknutím myši v dokumente FlowDocument - .net, wpf, flowdocument

Ako môžem získať TextPointer kliknutím myši v FlowDocument - .net, wpf, flowdocument

Chcel by som dostať slovo, na ktoré používateľ klikol, v dokumente FlowDocument.

Momentálne do každého pridávam obsluhu udalostiSpustenie v dokumente a iterácia cez TextPointers v spustení, na ktoré sa kliklo, volanie GetCharacterRect () na každom z nich a kontrola, či obdĺžnik obsahuje bod.

Ak však ku kliknutiu dôjde na konci dlhého spustenia, trvá to> 10 sekúnd.

Existuje nejaká efektívnejšia metóda?

odpovede:

6 pre odpoveď č. 1

Hovorím, že najjednoduchším spôsobom je použiť automatizačné rozhrania:

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);

Používanie ITextProvider vyžaduje odkaz nazhromaždenie UIAutomationProvider. Na toto zhromaždenie sa bežne neodkazuje, takže ho možno budete musieť pridať. Na použitie niektorých svojich metód bude tiež potrebné použiť UIAutomationTypes.

Upozorňujeme, že existuje veľa možností na vytvorenie vášho automatizovaného partnerského programu v závislosti od toho, ako prezentujete 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);

aktualizovať

Skúšal som to a funguje to dobre, aj keď prevod z ITextRangeProvider na TextPointer sa ukázal ako ťažší, ako som čakal.

Algoritmus som zabalil do metódy rozšírenia ScreenPointToTextPointer pre ľahké použitie. Tu je príklad toho, ako je možné moju metódu rozšírenia použiť na tučné zvýraznenie celého textu pred ukazovateľom myši a za neho zvýraznenie celého textu:

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);
}

Tu je kód pre metódu rozšírenia:

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;
}

}

Všimnite si tiež použitie PointToScreen v príklade metódy MouseMove na získanie bodu obrazovky na prechod do metódy rozšírenia.


1 pre odpoveď č. 2

Ak je FlowDocument RichTextBox, môžete použiť GetPositionFromPoint () metóda na získanie TextPointera.


0 pre odpoveď č. 3

Udalosti kliknutia myšou sú prebublávané navrch,namiesto toho môžete jednoducho pripojiť PreviewMouseLeftButtonUp vo svojom dokumente a sledovať odosielateľa / pôvodný zdroj udalosti, dostanete Run, ktorý vám poslal udalosť.

Potom môžete RangeFromPoint a môžete použiť,

PointToScreen, ktorý prevedie váš miestny bod myši na globálny bod.