当我尝试使用UI Automation的UI自动化时,我只能在使用RangeFromPoint

时间:2015-09-12 15:21:37

标签: c# automation powerpoint ui-automation

该代码适用于Word和Outlook但由于PowerPoint失败,因为只有文本框的第一个字符或第一个字被选中。这是一个错误吗?有没有解决方法?在PowerPoint 2013中的简单PowerPoint幻灯片上试试这个。

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

您无法从屏幕截图中看到它,但鼠标已开启&#34;首先&#34;不是&#34;卡住&#34;,但无论鼠标放在哪里,它总是卡住。也许这已在PowerPoint 2016中修复了?

enter image description here

当我查看范围的边界框时,它始终是整个元素,而不是选定的单词。这可能是RangeToPoint无法正常工作的问题的一部分。

原帖张贴于MSDN但未回复......

更新。如果我使用

text = printRange(range, text);
while (range.Move(TextUnit.Word, 1) > 0)
{
    text += Environment.NewLine;
    text = printRange(range, text);
}

我得到了

enter image description here

2 个答案:

答案 0 :(得分:3)

此行为可能是由于PowerPoint 2013中的限制,我希望您无法使用UIA解决此问题。当您调用RangeFromPoint()时,UIA提供程序命中鼠标(即实现IUIAutomationTextPattern :: RangeFromPoint()的那个)意味着返回鼠标光标所在的退化(即空)范围。然后UIA客户端可以扩展返回的范围以获取周围的字符,单词,行或段落。

但是,正如您所指出的,PowerPoint 2013并没有这样做。我刚刚编写了下面的测试代码,(使用tlbimp.exe生成的本机Windows UIA API的托管包装器),发现PowerPoint显然返回了光标下方整个文本框的TextRange。当我运行代码时,我发现我确实在写字板,Word 2013和PowerPoint OnLine中获得了光标下的预期字,但没有获得PowerPoint 2013.当我运行Text Explorer工具时,我得到了相同的结果Inspect SDK工具。下图显示了文本资源管理器报告,当鼠标悬停在其中一个单词上时,从PowerPoint 2013返回的文本是文本框中的整个文本。

(我应该在下面的测试代码中添加它,我认为当前的显示缩放设置需要达到100%。我没有添加代码来解释其他一些活动的扩展。)

我不知道这是否已在PowerPoint 2016中修复,我会尝试调查并告知您。

谢谢,

enter image description here

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) + "\"";
        }
    }
}

答案 1 :(得分:0)

我只能建议Python代码获取幻灯片的标题文本(例如)。对不起,我没时间在C#上重写它。您可以使用PowerPoint.Application COM对象和MSDN example of Power Point automation

from __future__ import print_function
import win32com.client as com
pp = com.Dispatch('PowerPoint.Application')
print(pp.Presentations[0].Slides[8].Shapes[0].TextFrame.TextRange.Text)