Whats the best practice or options to speed up the search when you are iterating the entire control list of a window?
I have tried creating a property condition to find only the items that are not empty as:
pAutomation->CreatePropertyCondition(UIA_NamePropertyId, CComVariant(L""), &pNameNotEmptyCondition);
but it didnt make any different on the time when compared to not using it.
I’m interested on just the name property, there’s something else i could try instead of caching, to increase the search speed?
#include <windows.h>
#include <UIAutomation.h>
#include <atlbase.h>
#include <string>
#include <set>
#include <functional>
#include <iostream>
inline void uiaElements2(CComPtr<IUIAutomation> pAutomation, CComPtr<IUIAutomationElement> pRootElement, std::set<std::wstring>& elementsList, int parsedCount = 0)
{
// Create a condition for non-empty names
CComPtr<IUIAutomationCondition> pNameNotEmptyCondition;
pAutomation->CreatePropertyCondition(UIA_NamePropertyId, CComVariant(L""), &pNameNotEmptyCondition);
CComPtr<IUIAutomationCondition> pNameNotEmptyNotCondition;
pAutomation->CreateNotCondition(pNameNotEmptyCondition, &pNameNotEmptyNotCondition);
std::function<void(CComPtr<IUIAutomationElement>)> processElement = [&](CComPtr<IUIAutomationElement> pCurrentElement)
{
parsedCount++;
if (parsedCount > 2000)
return;
BSTR bstrName;
if (SUCCEEDED(pCurrentElement->get_CurrentName(&bstrName)) && bstrName)
{
elementsList.insert(bstrName);
SysFreeString(bstrName);
}
CComPtr<IUIAutomationElementArray> pChildren;
pCurrentElement->FindAll(TreeScope_Children, pNameNotEmptyNotCondition, &pChildren);
if (!pChildren)
return;
int childCount;
pChildren->get_Length(&childCount);
for (int i = 0; i < childCount; i++)
{
CComPtr<IUIAutomationElement> pChild;
pChildren->GetElement(i, &pChild);
if (pChild)
processElement(pChild);
}
};
// Start processing from the root element
processElement(pRootElement);
}
inline void uiaElements(CComPtr<IUIAutomation> pAutomation, CComPtr<IUIAutomationElement> pRootElement, std::set<std::wstring>& elementsList, int parsedCount = 0)
{
CComPtr<IUIAutomationCondition> pTrueCondition;
pAutomation->CreateTrueCondition(&pTrueCondition);
std::function<void(CComPtr<IUIAutomationElement>)> processElement = [&](CComPtr<IUIAutomationElement> pCurrentElement)
{
parsedCount++;
if (parsedCount > 2000)
return;
BSTR bstrName;
if (SUCCEEDED(pCurrentElement->get_CurrentName(&bstrName)) && bstrName)
{
elementsList.insert(bstrName);
SysFreeString(bstrName);
}
CComPtr<IUIAutomationElementArray> pChildren;
pCurrentElement->FindAll(TreeScope_Children, pTrueCondition, &pChildren);
if (!pChildren)
return;
int childCount;
pChildren->get_Length(&childCount);
for (int i = 0; i < childCount; i++)
{
CComPtr<IUIAutomationElement> pChild;
pChildren->GetElement(i, &pChild);
if (pChild)
processElement(pChild);
}
};
// Start processing from the root element
processElement(pRootElement);
}
int main()
{
HRESULT hr = CoInitialize(NULL);
HWND hwnd = FindWindow(NULL, ...);
CComPtr<IUIAutomation> pAutomation;
CComPtr<IUIAutomationElement> pRootElement;
std::set<std::wstring> elementList;
std::set<std::wstring> elementList2;
if (SUCCEEDED(CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, IID_IUIAutomation, (void**)&pAutomation)))
{
for (int i = 0; i < 2; i++)
{
HRESULT hr = pAutomation->ElementFromHandle(hwnd, &pRootElement);
if (SUCCEEDED(hr) && pRootElement)
{
uiaElements(pAutomation, pRootElement, elementList);
uiaElements2(pAutomation, pRootElement, elementList2);
break;
}
else
std::wcout << L"Failed: " << hr << std::endl;
}
}
else
std::cout << "CoCreateInstance failed" << std::endl;
return 0;
}
3