HRESULT UiTreeWalk::PathFromRootToTarget()

in Tools/UIRecorder/UIXPathLib/UiTreeWalk.cpp [433:528]


HRESULT UiTreeWalk::PathFromRootToTarget(long left, long top)
{
    m_pt = { left,top };

    m_hWndTarget = WindowFromPoint(m_pt);

    BOOL bStartFromRoot = TRUE;

    HWND hRoot = GetAncestor(m_hWndTarget, GA_ROOT);
    if (hRoot != NULL)
    {
        WCHAR chClassName[64]{ 0 };
        GetClassName(hRoot, chClassName, ARRAYSIZE(chClassName));
        if (wcslen(chClassName) > 0)
        {
            if (wcsncmp(L"Chrome_WidgetWin", chClassName, 16) == 0
                || wcsncmp(L"MozillaWindowClass", chClassName, 18) == 0)
            {
                // Chrome and Firefox 
                return PathFromTargetToRoot(left, top);
            }

            if (wcsncmp(L"Progman", chClassName, 7) == 0
                || wcsncmp(L"IEFrame", chClassName, 7) == 0
                || wcsncmp(L"SysListView32", chClassName, 13) == 0)
            {
                // desktop icons or IE11
                bStartFromRoot = FALSE;
            }
        }
    }

    CComPtr<IUIAutomationElement> spRoot;
    REQUIRE_SUCCESS_HR(m_spAutomation->GetRootElement(&spRoot.p));

    CComPtr<IUIAutomationElement> spTarget;
    REQUIRE_SUCCESS_HR(m_spAutomation->ElementFromPoint(m_pt, &spTarget.p));

    CComPtr<IUIAutomationElement> spStart;
    if (bStartFromRoot == FALSE)
    {
        // starting from top window is much faster
        REQUIRE_SUCCESS_HR(m_spAutomation->ElementFromHandle(hRoot, &spStart.p));
    }
    else
    {
        REQUIRE_SUCCESS_HR(spRoot.CopyTo(&spStart.p));
    }

    // ElementFromPoint may return RECT {0,0,0,0} like UIs on Edge F12
    if (SUCCEEDED(spTarget->get_CurrentBoundingRectangle(&s_rectTargetElement)))
    {
        if (memcmp(&s_rectTargetElement, &rectZero, sizeof(RECT)) == 0)
        {
            CComPtr<IUIAutomationElement> TempTarget;
            if (FAILED(ElementContainingPoint(left, top, spStart, &TempTarget.p)))
            {
                CComPtr<IUIAutomationElement> spParent;
                m_spTreeWalker->GetParentElement(spTarget, &spParent.p);
                spTarget.Release();
                spTarget = spParent.Detach();
            }
            else
            {
                spTarget.Release();
                spTarget = TempTarget.Detach();
            }
        }
    }

    std::wstring uiPath;
    HRESULT hr = GetChildUiNode(left, top, spStart, spTarget, uiPath);
    if (hr == S_OK)
    {
        AppendUiAttributes(left, top, spStart, 0, uiPath);

        if (bStartFromRoot == FALSE)
        {
            AppendUiAttributes(left, top, spRoot, 0, uiPath);
        }

        swprintf_s(s_chBuffer, BUFFERSIZE, L"%s", uiPath.c_str());

        if (SUCCEEDED(spTarget->get_CurrentBoundingRectangle(&s_rectTargetElement)))
        {
            DrawHighlight();
            m_nHighlightTimer = SetTimer(NULL, 0, 500, NULL);
        }
    }
    else
    {
        PathFromTargetToRoot(left, top);
    }

    return S_OK;
}