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('\r');
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
I can suggest only Python code getting caption text of the slide (for example). Sorry, I have no time to re-write it on C#. You can play with the
PowerPoint.Application
COM object and MSDN example of Power Point automation.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