Microsoft UI Automation allows clients to subscribe to events of interest. This capability improves performance by eliminating the need to continually poll the UI elements in the system to see if any information, structure, or state has changed.
For this scenario, we can subscribe Structure change event via AddStructureChangedEventHandler
. Please refer to the code sample below about handling Structure-Changed events:
// Defines an event handler for structure-changed events, and
// listens for them on the element specifies by the user.
#include <windows.h>
#include <stdio.h>
#include <UIAutomation.h>
class EventHandler:
public IUIAutomationStructureChangedEventHandler
{
private:
LONG _refCount;
public:
int _eventCount;
// Constructor.
EventHandler(): _refCount(1), _eventCount(0)
{
}
// IUnknown methods.
ULONG STDMETHODCALLTYPE AddRef()
{
ULONG ret = InterlockedIncrement(&_refCount);
return ret;
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG ret = InterlockedDecrement(&_refCount);
if (ret == 0)
{
delete this;
return 0;
}
return ret;
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppInterface)
{
if (riid == __uuidof(IUnknown))
*ppInterface=static_cast<IUIAutomationStructureChangedEventHandler*>(this);
else if (riid == __uuidof(IUIAutomationStructureChangedEventHandler))
*ppInterface=static_cast<IUIAutomationStructureChangedEventHandler*>(this);
else
{
*ppInterface = NULL;
return E_NOINTERFACE;
}
this->AddRef();
return S_OK;
}
// IUIAutomationStructureChangedEventHandler methods
HRESULT STDMETHODCALLTYPE HandleStructureChangedEvent(IUIAutomationElement* pSender, StructureChangeType changeType, SAFEARRAY* pRuntimeID) {
_eventCount++;
switch (changeType)
{
case StructureChangeType_ChildAdded:
wprintf(L">> Structure Changed: ChildAdded! (count: %d)\n", _eventCount);
break;
case StructureChangeType_ChildRemoved:
wprintf(L">> Structure Changed: ChildRemoved! (count: %d)\n", _eventCount);
break;
case StructureChangeType_ChildrenInvalidated:
wprintf(L">> Structure Changed: ChildrenInvalidated! (count: %d)\n", _eventCount);
break;
case StructureChangeType_ChildrenBulkAdded:
wprintf(L">> Structure Changed: ChildrenBulkAdded! (count: %d)\n", _eventCount);
break;
case StructureChangeType_ChildrenBulkRemoved:
wprintf(L">> Structure Changed: ChildrenBulkRemoved! (count: %d)\n", _eventCount);
break;
case StructureChangeType_ChildrenReordered:
wprintf(L">> Structure Changed: ChildrenReordered! (count: %d)\n", _eventCount);
break;
}
return S_OK;
}
};
int main(int argc, char* argv[])
{
HRESULT hr;
int ret = 0;
IUIAutomationElement* pTargetElement = NULL;
EventHandler* pEHTemp = NULL;
CoInitializeEx(NULL,COINIT_MULTITHREADED);
IUIAutomation* pAutomation=NULL;
hr = CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation), (void**)&pAutomation);
if (FAILED(hr) || pAutomation == NULL)
{
ret = 1;
goto cleanup;
}
wprintf(L"-Use the mouse to point to the element you want to listen from.\n");
Sleep(3000);
// Make this application dots-per-inch (DPI) aware.
SetProcessDPIAware();
// Get mouse cursor position and get element from point.
POINT pt;
GetPhysicalCursorPos(&pt);
hr = pAutomation->ElementFromPoint(pt, &pTargetElement);
if (FAILED(hr) || pTargetElement == NULL)
{
ret = 1;
goto cleanup;
}
pEHTemp = new EventHandler();
if (pEHTemp == NULL)
{
ret = 1;
goto cleanup;
}
wprintf(L"-Adding Event Handler.\n");
hr = pAutomation->AddStructureChangedEventHandler(pTargetElement, TreeScope_Subtree, NULL, (IUIAutomationStructureChangedEventHandler*) pEHTemp);
if (FAILED(hr))
{
ret = 1;
goto cleanup;
}
wprintf(L"-Press any key to remove event handler and exit\n");
getchar();
wprintf(L"-Removing Event Handler.\n");
hr = pAutomation->RemoveStructureChangedEventHandler(pTargetElement, (IUIAutomationStructureChangedEventHandler*) pEHTemp);
if (FAILED(hr))
{
ret = 1;
goto cleanup;
}
// Release resources and terminate.
cleanup:
if (pEHTemp != NULL)
pEHTemp->Release();
if (pTargetElement != NULL)
pTargetElement->Release();
if (pAutomation != NULL)
pAutomation->Release();
CoUninitialize();
return ret;
}
Here is an helpful document about Subscribing to UI Automation Events.