问题
I have been looking for a sample of using UI Automation in MFC (or Win32) as a client to scroll another applications window. But I can't find any samples?
Does anyone know of one or can provide one?
回答1:
The following is a Win32 C++ example of scrolling vertically on a notepad window: testWindow.txt - Notepad
.
Main steps:
Find the main window handle of target application using FindWindow.
FindWindow(L"Notepad", L"testWindow.txt - Notepad");
Get IUIAutomationElement object from above found window handle.
pClientUIA->ElementFromHandle(targetWindow, &pRootElement);
Find the handle of the window which containing the scrollbar using UIA_ScrollBarControlTypeId and NormalizeElement.
Send WM_VSCROLL message to the window containing the scrollbar.
PostMessage(foundHwnd, WM_VSCROLL, SB_LINEUP, 0);
This is the complete code you can refer to:
#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);
}
--------------------------------------------------------------
UPDATE:
Another method is using IUIAutomationScrollPattern::Scroll(). More direct and simple. Similar thread.
来源:https://stackoverflow.com/questions/62143582/mfc-or-win32-ui-automation-client-sample