MFC 或 WIN32 UI 自动化客户端示例?

MFC or WIN32 UI Automation Client Sample?

我一直在寻找使用 UI MFC(或 Win32)中的自动化作为客户端来滚动另一个应用程序的示例 window。但是我找不到任何样本?

有人知道或可以提供吗?

以下是在记事本上垂直滚动的 Win32 C++ 示例 window: testWindow.txt - Notepad.

主要步骤:

  1. 使用FindWindow找到目标应用程序的主window句柄。

    FindWindow(L"Notepad", L"testWindow.txt - Notepad");

  2. 从上面找到 window 句柄获取 IUIAutomationElement 对象。

    pClientUIA->ElementFromHandle(targetWindow, &pRootElement);

  3. 使用UIA_ScrollBarControlTypeId and NormalizeElement找到包含滚动条的window句柄。

  4. 发送 WM_VSCROLL 消息到包含滚动条的 window。

    PostMessage(foundHwnd, WM_VSCROLL, SB_LINEUP, 0);

这是您可以参考的完整代码:

#include <windows.h>
#include <uiautomation.h>

IUIAutomation *pClientUIA;
IUIAutomationElement *pRootElement;

HWND FindScrollbarContainerWindow(const long controlType)
{
    HRESULT hr;
    BSTR name;
    IUIAutomationCondition *pCondition;
    VARIANT varProp;
    varProp.vt = VT_I4;
    varProp.uintVal = controlType;
    hr = pClientUIA->CreatePropertyCondition(UIA_ControlTypePropertyId, varProp, &pCondition);
    if (S_OK != hr)
    {
        printf("CreatePropertyCondition error: %d\n", hr);
    }

    IUIAutomationElementArray *pElementFound;
    hr = pRootElement->FindAll(TreeScope_Subtree, pCondition, &pElementFound);
    if (S_OK != hr)
    {
        printf("CreatePropertyCondition error: %d\n", hr);
    }
    int eleCount;
    pElementFound->get_Length(&eleCount);
    if (eleCount == 0)
        return NULL;

    for (int i = 0; i <= eleCount; i++)
    {
        IUIAutomationElement *pElement;
        hr = pElementFound->GetElement(i, &pElement);
        if (S_OK != hr)
        {
            printf("CreatePropertyCondition error: %d\n", hr);
        }
        hr = pElement->get_CurrentName(&name);
        if (S_OK != hr)
        {
            printf("CreatePropertyCondition error: %d\n", hr);
        }
        wprintf(L"Control Name: %s\n", name);

        hr = pElement->get_CurrentClassName(&name);
        if (S_OK != hr)
        {
            printf("CreatePropertyCondition error: %d\n", hr);
        }
        wprintf(L"Class Name: %s\n", name);

        IUIAutomationTreeWalker* pContentWalker = NULL;

        hr = pClientUIA->get_ContentViewWalker(&pContentWalker);
        if (pContentWalker == NULL)
            return NULL;

        // Get ancestor element nearest to the scrollbar UI Automation element in the tree view
        IUIAutomationElement *ncestorElement;
        hr = pContentWalker->NormalizeElement(pElement, &ncestorElement);

        hr = ncestorElement->get_CurrentName(&name);
        wprintf(name);

        // Get window handle of ancestor element
        UIA_HWND controlContainerHwnd = NULL;
        hr = ncestorElement->get_CurrentNativeWindowHandle(&controlContainerHwnd);
        printf("");

        if (controlContainerHwnd)
        {
            return (HWND)controlContainerHwnd;
        }
    }

    return NULL;
}

int main()
{
    // Find target window
    HWND targetWindow = FindWindow(L"Notepad", L"testWindow.txt - Notepad");
    if (NULL == targetWindow)
    {
        printf("FindWindow fails with error: %d\n", GetLastError());
        return FALSE;
    }

    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    if (S_OK != hr)
    {
        printf("CoInitializeEx error: %d\n", hr);
        return 1;
    }

    hr = CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, IID_IUIAutomation, reinterpret_cast<void**>(&pClientUIA));
    if (S_OK != hr)
    {
        printf("CoCreateInstance error: %d\n", hr);
        return 1;
    }

    hr = pClientUIA->ElementFromHandle(targetWindow, &pRootElement);
    if (S_OK != hr)
    {
        printf("ElementFromHandle error: %d\n", hr);
        return 1;
    }

    // Find scroll bar and its containing window
    HWND foundHwnd = FindScrollbarContainerWindow(UIA_ScrollBarControlTypeId);
    if (NULL == foundHwnd)
        return 1;

    // Vertical scroll bar
    // Line up - Like click top arrow button to scroll up one line
    PostMessage(foundHwnd, WM_VSCROLL, SB_LINEUP, 0);
    Sleep(1000);

    // Line down
    PostMessage(foundHwnd, WM_VSCROLL, SB_LINEDOWN, 0);
    Sleep(1000);

    // Page up
    PostMessage(foundHwnd, WM_VSCROLL, SB_PAGEUP, 0);
    Sleep(1000);

    // Page down
    PostMessage(foundHwnd, WM_VSCROLL, SB_LINEDOWN, 0);
    Sleep(1000);
}

---------------------------------------- ----------------------

更新:

另一种方法是使用 IUIAutomationScrollPattern::Scroll(). More direct and simple.