MFC 或 WIN32 UI 自动化客户端示例?
MFC or WIN32 UI Automation Client Sample?
我一直在寻找使用 UI MFC(或 Win32)中的自动化作为客户端来滚动另一个应用程序的示例 window。但是我找不到任何样本?
有人知道或可以提供吗?
以下是在记事本上垂直滚动的 Win32 C++ 示例 window: testWindow.txt - Notepad
.
主要步骤:
使用FindWindow
找到目标应用程序的主window句柄。
FindWindow(L"Notepad", L"testWindow.txt - Notepad");
从上面找到 window 句柄获取 IUIAutomationElement
对象。
pClientUIA->ElementFromHandle(targetWindow, &pRootElement);
使用UIA_ScrollBarControlTypeId
and NormalizeElement
找到包含滚动条的window句柄。
发送 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. 。
我一直在寻找使用 UI MFC(或 Win32)中的自动化作为客户端来滚动另一个应用程序的示例 window。但是我找不到任何样本?
有人知道或可以提供吗?
以下是在记事本上垂直滚动的 Win32 C++ 示例 window: testWindow.txt - Notepad
.
主要步骤:
使用
FindWindow
找到目标应用程序的主window句柄。FindWindow(L"Notepad", L"testWindow.txt - Notepad");
从上面找到 window 句柄获取
IUIAutomationElement
对象。pClientUIA->ElementFromHandle(targetWindow, &pRootElement);
使用
UIA_ScrollBarControlTypeId
andNormalizeElement
找到包含滚动条的window句柄。发送
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.