HRESULT UiTreeWalk::ElementContainingPoint()

in Tools/UIRecorder/UIXPathLib/UiTreeWalk.cpp [351:431]


HRESULT UiTreeWalk::ElementContainingPoint(long left, long top, IUIAutomationElement*pCur, IUIAutomationElement** ppElem)
{
    if (CancelCurrentTask())
    {
        return S_FALSE;
    }

    RECT rect;
    if (SUCCEEDED(pCur->get_CurrentBoundingRectangle(&rect)))
    {
        if (memcmp(&rect, &rectZero, sizeof(RECT)) != 0)
        {
            if (left < rect.left || left > rect.right)
                return S_FALSE;

            if (top < rect.top || top > rect.bottom)
                return S_FALSE;
        }
    }

    CComPtr<IUIAutomationElementArray> spChildren;
    REQUIRE_SUCCESS_HR(pCur->FindAll(TreeScope::TreeScope_Children, m_spFindAllCondition, &spChildren.p));

    if (spChildren != nullptr)
    {
        int count = 0;
        REQUIRE_SUCCESS_HR(spChildren->get_Length(&count));

        for (int i = 0; i < count; i++)
        {
            CComPtr<IUIAutomationElement> spChild;
            REQUIRE_SUCCESS_HR(spChildren->GetElement(i, &spChild.p));
            if (spChild != nullptr && S_FALSE != ElementContainingPoint(left, top, spChild, ppElem))
            {
                return S_OK;
            }
        }
    }

    spChildren.Release();
    REQUIRE_SUCCESS_HR(pCur->FindAll(TreeScope::TreeScope_Subtree, m_spFindAllCondition, &spChildren.p));
    if (spChildren == nullptr)
        return S_FALSE;

    int countAll = 0;
    REQUIRE_SUCCESS_HR(spChildren->get_Length(&countAll));

    double areaMin = 1E12;
    for (int i = 0; i < countAll; i++)
    {
        CComPtr<IUIAutomationElement> spChild;
        REQUIRE_SUCCESS_HR(spChildren->GetElement(i, &spChild.p));
        {
            if (spChild != nullptr && SUCCEEDED(spChild->get_CurrentBoundingRectangle(&rect)))
            {
                if (rect.left <= left && left <= rect.right)
                {
                    if (rect.top <= top && top <= rect.bottom)
                    {
                        double area = ((double)rect.right - (double)rect.left) * ((double)rect.bottom - (double)rect.top);
                        if (area < areaMin)
                        {
                            areaMin = area;
                            *ppElem = spChild;
                        }
                    }
                }
            }
        }
    }

    if (*ppElem != NULL)
    {
        (*ppElem)->AddRef();
        return S_OK;
    }
    else
    {
        return E_FAIL;
    }
}