问题描述
该代码适用于 Word 和 Outlook,但不适用于 PowerPoint,因为只有文本框的第一个字符或第一个单词被选中.这是一个错误吗?有什么解决方法吗?在 PowerPoint 2013 中的简单 PowerPoint 幻灯片上试试这个.
私有静态异步任务getText(双x,双y){字符串结果 = 空;尝试{var location = new System.Windows.Point(x, y);AutomationElement 元素 = AutomationElement.FromPoint(location);对象模式对象;if (element.TryGetCurrentPattern(TextPattern.Pattern, out patternObj)){var textPattern = (TextPattern)patternObj;var range = textPattern.RangeFromPoint(location);range.ExpandToEnclosureUnit(TextUnit.Word);范围.选择();var text = range.GetText(-1).TrimEnd('
');返回 text.Trim();}别的{返回未找到文本";}}捕获(异常前){返回前消息;}}
从截图上看不出来,但是鼠标在第一"而不是卡住",但是不管鼠标放在哪里,总是卡住.也许这已在 PowerPoint 2016 中修复?
当我查看范围的边界框时,它始终是整个元素,而不是选定的单词.这可能是 RangeToPoint 不起作用的部分原因.
原文发表于
此行为可能是由于 PowerPoint 2013 中的限制所致,我希望您无法使用 UIA 解决此问题.当您调用 RangeFromPoint() 时,UIA 提供程序点击鼠标下方(即实现 IUIAutomationTextPattern::RangeFromPoint() 的那个)意味着返回鼠标光标所在的退化(即空)范围.然后UIA客户端可以扩大返回的范围,得到周围的字符、单词、行或段落.
但是,正如您所指出的,PowerPoint 2013 并没有这样做.我刚刚编写了下面的测试代码(使用由 tlbimp.exe 生成的本机 Windows UIA API 的托管包装器),发现 PowerPoint 显然为光标下方的整个文本框返回了一个 TextRange.当我运行代码时,我发现我确实在 WordPad、Word 2013 和 PowerPoint OnLine 中的光标下方得到了预期的单词,但在 PowerPoint 2013 中没有.当我运行作为 Inspect SDK 一部分的文本资源管理器工具时,我得到了相同的结果工具.下图显示了文本资源管理器报告从 PowerPoint 2013 返回的文本是文本框中的整个文本,当鼠标悬停在这些单词之一上时.
(为了让下面的测试代码完全工作,我应该添加它,我认为当前的显示缩放设置需要为 100%.我没有添加代码来说明其他一些缩放处于活动状态.)
>我不知道 PowerPoint 2016 是否已修复此问题,我会尝试调查并通知您.
谢谢,
伙计
private void buttonGetTheText_Click(object sender, EventArgs e){labelText.Text = "未找到文本.";IUIAutomation uiAutomation = new CUIAutomation8();点 ptCursor = Cursor.Position;标记点 pt;pt.x = ptCursor.X;pt.y = ptCursor.Y;//缓存通过下方元素可用的文本模式//鼠标光标,(如果元素支持文本模式,)//为了避免另一个跨进程调用以获取模式.int patternIdText = 10014;//UIA_TextPatternIdIUIAutomationCacheRequest cacheRequestTextPattern =uiAutomation.CreateCacheRequest();cacheRequestTextPattern.AddPattern(patternIdText);//现在获取鼠标下方的元素.IUIAutomationElement 元素 =uiAutomation.ElementFromPointBuildCache(pt, cacheRequestTextPattern);//元素是否支持文本模式?IUIAutomationTextPattern textPattern =element.GetCachedPattern(patternIdText);如果(文本模式!= null){//现在获取鼠标所在的退化 TextRange.IUIAutomationTextRange range = textPattern.RangeFromPoint(pt);如果(范围!= null){//扩大范围以包括周围的单词//鼠标所在的点.range.ExpandToEnclosureUnit(TextUnit.TextUnit_Word);//在测试应用程序中显示单词.labelText.Text = "文本为:"" + range.GetText(256) + """;}}}
The code works for Word and Outlook but fails with PowerPoint in that only the first character or first word of the textbox ever gets selected. Is this a bug? Is there any workaround? Try this on a simple PowerPoint slide in PowerPoint 2013.
private static async Task<string> getText(double x, double y)
{
string result = null;
try
{
var location = new System.Windows.Point(x, y);
AutomationElement element = AutomationElement.FromPoint(location);
object patternObj;
if (element.TryGetCurrentPattern(TextPattern.Pattern, out patternObj))
{
var textPattern = (TextPattern)patternObj;
var range = textPattern.RangeFromPoint(location);
range.ExpandToEnclosingUnit(TextUnit.Word);
range.Select();
var text = range.GetText(-1).TrimEnd('
');
return text.Trim();
}
else
{
return "no text found";
}
}
catch (Exception ex)
{
return ex.Message;
}
}
You cannot see it from the screenshot, but the mouse is on "first" not "stuck", but regardless of where the mouse is placed, it always is stuck. Maybe this is fixed in PowerPoint 2016?
When I look at the bounding box for the range it is always the whole element, rather than the selected word. That could be part of the problem of why RangeToPoint is not working.
Original posted in MSDN but no response...
Update. If I use
text = printRange(range, text);
while (range.Move(TextUnit.Word, 1) > 0)
{
text += Environment.NewLine;
text = printRange(range, text);
}
I get
This behavior is probably due to a limitation in PowerPoint 2013, and I expect you can't work around it using UIA. When you call RangeFromPoint(), the UIA provider hit beneath the mouse, (ie the one that's implementing IUIAutomationTextPattern::RangeFromPoint(),) is meant to return a degenerative (ie empty) range where the mouse cursor is. Then the UIA client can expand the returned range to get the surrounding character, word, line or paragraph.
However, as you point out, PowerPoint 2013 isn't doing that. I've just written the test code below, (using a managed wrapper for the native Windows UIA API generated by tlbimp.exe,) and found that PowerPoint apparently returns a TextRange for the entire text box beneath the cursor. When I ran the code, I found that I did get the expected word beneath the cursor in WordPad, Word 2013 and PowerPoint OnLine, but not PowerPoint 2013. I got the same results when I ran the Text Explorer tool that's part of the Inspect SDK tool. The image below shows Text Explorer reporting that the text returned from PowerPoint 2013 is the entire text in the a text box, when the mouse is hovering over one of those words.
(I should add that for the test code below to work at all, I think the current display scaling setting needs to be at 100%. I've not added code to account for some other scaling being active.)
I don't know if this is fixed in PowerPoint 2016, I'll try to look into that and let you know.
Thanks,
Guy
private void buttonGetTheText_Click(object sender, EventArgs e)
{
labelText.Text = "No text found.";
IUIAutomation uiAutomation = new CUIAutomation8();
Point ptCursor = Cursor.Position;
tagPOINT pt;
pt.x = ptCursor.X;
pt.y = ptCursor.Y;
// Cache the Text pattern that's available through the element beneath
// the mouse cursor, (if the Text pattern's supported by the element,) in
// order to avoid another cross-process call to get the pattern later.
int patternIdText = 10014; // UIA_TextPatternId
IUIAutomationCacheRequest cacheRequestTextPattern =
uiAutomation.CreateCacheRequest();
cacheRequestTextPattern.AddPattern(patternIdText);
// Now get the element beneath the mouse.
IUIAutomationElement element =
uiAutomation.ElementFromPointBuildCache(pt, cacheRequestTextPattern);
// Does the element support the Text pattern?
IUIAutomationTextPattern textPattern =
element.GetCachedPattern(patternIdText);
if (textPattern != null)
{
// Now get the degenerative TextRange where the mouse is.
IUIAutomationTextRange range = textPattern.RangeFromPoint(pt);
if (range != null)
{
// Expand the range to include the word surrounding
// the point where the mouse is.
range.ExpandToEnclosingUnit(TextUnit.TextUnit_Word);
// Show the word in the test app.
labelText.Text = "Text is: "" + range.GetText(256) + """;
}
}
}
这篇关于当我尝试使用 PowerPoint 2013 的 UI 自动化时,我只能在使用 RangeFromPoint 时获取第一个字符/单词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!