我需要在WebBrowser控件中找出所选文本的位置。我可以通过
获得IHTMLTxtRange IHTMLDocument2 htmlDocument = BookReaderWeb.Document as IHTMLDocument2;
IMarkupServices ms = (IMarkupServices) htmlDocument;
IHTMLSelectionObject selection = htmlDocument.selection;
if (selection == null) return;
IHTMLTxtRange range = selection.createRange() as IHTMLTxtRange;
但我不知道如何获得相对于全文(不是html)的范围位置。 感谢。
更新
正如Noseratio建议的那样,我实现了以下代码:
IHTMLDocument2 htmlDocument = BookReaderWeb.Document as IHTMLDocument2;
var str = htmlDocument.body.outerText;
IMarkupServices ms = (IMarkupServices) htmlDocument;
IHTMLSelectionObject selection = htmlDocument.selection;
if (selection == null) return;
IHTMLTxtRange range = selection.createRange() as IHTMLTxtRange;
dynamic body = htmlDocument.body;
var bodyRange = body.createTextRange();
bodyRange.moveToElementText(body);
var bodyText = bodyRange.text;
var counter = 0;
while (bodyRange.compareEndPoints("StartToStart", range) != 0)
{
bodyRange.moveStart("character", 1);
++counter;
}
MessageBox.Show(str.Substring(counter, 20));
但它没有给出正确的结果。这个位置是向前放错的几个字符然后它应该是。它只发生在大型html文件上,它适用于较小的文件。看起来dom api将某种标签解释为字符可能..?
答案 0 :(得分:3)
一种愚蠢的方法(为简单起见使用JavaScript表示法):
document.body
创建文字范围:var bodyRange = document.body.createTextRange(); bodyRange.moveToElementText(document.body);
bodyRange.text
对应全文。bodyRange.moveStart("character", 1)
一次向前移动一个字符,并将其开头与您选择的范围比较为bodyRange.compareEndPoints("StartToStart", range
。当它们匹配时,您已在全文中找到了开头的位置。bodyRange.collapse(true)
,这会将范围的结束移动到范围的开始。bodyRange.moveEnd("character", 1)
一次向前移动一个字符,并将其开头与您选择的范围开始比较bodyRange.compareEndPoints("EndToEnd", range
)。当它们匹配时,您已在全文中找到了结尾的位置。您可以通过为moveStart
/ moveEnd
一次移动一个单词或一个句子来改进此算法,然后一次精确匹配一个字符。
此外,还有一种更好的方法,它使用standard DOM Range and Selection API。我描述了它here。
已更新,请尝试对您的代码进行以下更新(未经测试):
var tempRange = bodyRange.duplicate();
while (bodyRange.compareEndPoints("StartToStart", range) != 0)
{
bodyRange.moveStart("character", 1);
tempRange.setEndPoint("EndToStart", bodyRange);
//tempRange.EndToStart(bodyRange);
if (String.Compare(tempRange.text, ((String)bodyText).Substring(counter)) != 0)
++counter;
}
MessageBox.Show(str.Substring(counter, 20));