UIAutomation: AddAutomationEventHandler () возвращает E_INVALIDARG - PullRequest
1 голос
/ 22 апреля 2019

Вот мой код:

// Defines an event handler for general UI Automation events. It listens for
// tooltip and window creation and destruction events. 
#include <windows.h>
#include <stdio.h>
#include <UIAutomation.h>

class EventHandler :
    public IUIAutomationEventHandler
{
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<IUIAutomationEventHandler*>(this);
        else if (riid == __uuidof(IUIAutomationEventHandler))
            *ppInterface = static_cast<IUIAutomationEventHandler*>(this);
        else
        {
            *ppInterface = NULL;
            return E_NOINTERFACE;
        }
        this->AddRef();
        return S_OK;
    }

    // IUIAutomationEventHandler methods
    HRESULT STDMETHODCALLTYPE HandleAutomationEvent(IUIAutomationElement * pSender, EVENTID eventID)
    {
        _eventCount++;
        switch (eventID)
        {
        case UIA_AutomationFocusChangedEventId:
            wprintf(L">> Event FocusChanged Received! (count: %d)\n", _eventCount);
            break;
        case UIA_ToolTipOpenedEventId:
            wprintf(L">> Event ToolTipOpened Received! (count: %d)\n", _eventCount);
            break;
        case UIA_ToolTipClosedEventId:
            wprintf(L">> Event ToolTipClosed Received! (count: %d)\n", _eventCount);
            break;
        case UIA_Window_WindowOpenedEventId:
            wprintf(L">> Event WindowOpened Received! (count: %d)\n", _eventCount);
            break;
        case UIA_Window_WindowClosedEventId:
            wprintf(L">> Event WindowClosed Received! (count: %d)\n", _eventCount);
            break;
        default:
            wprintf(L">> Event (%d) Received! (count: %d)\n", eventID, _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;
    }
    // Use root element for listening to window and tooltip creation and destruction.
    hr = pAutomation->GetRootElement(&pTargetElement);
    if (FAILED(hr) || pTargetElement == NULL)
    {
        ret = 1;
        goto cleanup;
    }

    pEHTemp = new EventHandler();
    if (pEHTemp == NULL)
    {
        ret = 1;
        goto cleanup;
    }

    wprintf(L"-Adding Event Handlers.\n");
    hr = pAutomation->AddAutomationEventHandler(UIA_ToolTipOpenedEventId, pTargetElement, TreeScope_Subtree, NULL, (IUIAutomationEventHandler*)pEHTemp);
    if (FAILED(hr))
    {
        ret = 1;
        goto cleanup;
    }
    hr = pAutomation->AddAutomationEventHandler(UIA_ToolTipClosedEventId, pTargetElement, TreeScope_Subtree, NULL, (IUIAutomationEventHandler*)pEHTemp);
    if (FAILED(hr))
    {
        ret = 1;
        goto cleanup;
    }
    hr = pAutomation->AddAutomationEventHandler(UIA_Window_WindowOpenedEventId, pTargetElement, TreeScope_Subtree, NULL, (IUIAutomationEventHandler*)pEHTemp);
    if (FAILED(hr))
    {
        ret = 1;
        goto cleanup;
    }
    hr = pAutomation->AddAutomationEventHandler(UIA_Window_WindowClosedEventId, pTargetElement, TreeScope_Subtree, NULL, (IUIAutomationEventHandler*)pEHTemp);
    if (FAILED(hr))
    {
        ret = 1;
        goto cleanup;
    }
    // Error is here. hr returns E_INVALIDARG.
    hr = pAutomation->AddAutomationEventHandler(UIA_AutomationFocusChangedEventId, pTargetElement, TreeScope_Subtree, NULL, (IUIAutomationEventHandler*)pEHTemp);
    if (FAILED(hr))
    {
        ret = 1;
        goto cleanup;
    }

    wprintf(L"-Press any key to remove event handlers and exit\n");
    getchar();

    wprintf(L"-Removing Event Handlers.\n");

cleanup:
    // Remove event handlers, release resources, and terminate
    if (pAutomation != NULL)
    {
        hr = pAutomation->RemoveAllEventHandlers();
        if (FAILED(hr))
            ret = 1;
        pAutomation->Release();
    }

    if (pEHTemp != NULL)
        pEHTemp->Release();

    if (pTargetElement != NULL)
        pTargetElement->Release();

    CoUninitialize();
    return ret;
}

Этот код взят из примеров от Microsoft о реализации классов Event для UIAutomation.

Я немного отредактировал код, чтобы он мог поддерживать события Focus, но мне не удалось инициализировать одну строку кода.

Я не понимаю, почему hr = pAutomation->AddAutomationEventHandler(UIA_AutomationFocusChangedEventId, pTargetElement, TreeScope_Subtree, NULL, (IUIAutomationEventHandler*)pEHTemp) возвращает E_INVALIDARG.

Пробовал читать документы, и я не могу найти причину.

Пожалуйста, помогите.

1 Ответ

1 голос
/ 22 апреля 2019

Существует отдельный обработчик для обработки FocusChanged, AddFocusChangedEventHandler, который следует использовать для изменения фокуса монитора. Поскольку вы пытаетесь отправить указатель на функцию EventHandler для обработки FocusChanged, возникает ошибка во время выполнения.

Чтобы создать этот обработчик, нужен экземпляр класса, который наследуется от IUIAutomationFocusChangedEventHandler.

class FocusChangedEventHandler :
    public IUIAutomationFocusChangedEventHandler
{
private:
    LONG _refCount;

public:
    int _eventCount;

    //Constructor.
    FocusChangedEventHandler() : _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<IUIAutomationFocusChangedEventHandler*>(this);
        else if (riid == __uuidof(IUIAutomationFocusChangedEventHandler))
            *ppInterface = static_cast<IUIAutomationFocusChangedEventHandler*>(this);
        else
        {
            *ppInterface = NULL;
            return E_NOINTERFACE;
        }
        this->AddRef();
        return S_OK;
    }

    // IUIAutomationFocusChangedEventHandler methods.
    HRESULT STDMETHODCALLTYPE HandleFocusChangedEvent(IUIAutomationElement * pSender)
    {
        _eventCount++;
        wprintf(L">> FocusChangedEvent Received! (count: %d)\n", _eventCount);
        return S_OK;
    }
};

В main()

pFHTemp = new FocusChangedEventHandler();
hr = pAutomation->AddFocusChangedEventHandler(NULL, (IUIAutomationFocusChangedEventHandler*)pFHTemp);
if (FAILED(hr))
{
    ret = 1;
    goto cleanup;
}

Фрагменты кода, взятые из Ссылка MSDN

...