winapi - 为什么 UI 自动化条件无法通过 UIA_IsScrollPatternAvailablePropertyId 找到元素?
问题描述
我想在允许滚动的主窗口句柄中找到元素。因此,我不想找到滚动条,然后是滚动条的所有者,我只想返回允许通过 ScrollPattern 滚动的项目,所以我设置了条件,但什么也没找到。如果我搜索滚动条所有者窗口,然后获取 ScrollPattern 它可以工作。为什么我不能只找到具有可用滚动模式的元素?
下面是通用代码:
BOOL CUIAutomateScroller::FindWindow(HWND hwnd, IUIAutomationElement **windowelement)
{
BOOL result=FALSE;
// make sure init completed
if (m_pClientUIA) {
// get window element
HRESULT hr=m_pClientUIA->ElementFromHandle(hwnd, windowelement);
// check result
result=SUCCEEDED(hr);
// output debug info
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("ElementFromHandle error: %d\n"), hr);
}
else {
_ASSERT(*windowelement!=NULL);
}
}
return result;
}
BOOL CUIAutomateScroller::FindContainerWindowElement(const long controltype, IUIAutomationElement **pelement)
{
// Create search condition
VARIANT varprop;
varprop.vt=VT_I4;
varprop.uintVal=controltype;
CComPtr<IUIAutomationCondition> pcondition;
HRESULT hr=m_pClientUIA->CreatePropertyCondition(UIA_ControlTypePropertyId, varprop, &pcondition);
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("CreatePropertyCondition error: %d\n"), hr);
return NULL;
}
// find the control based on condition
CComPtr<IUIAutomationElementArray> pcontrolelementarr;
hr=m_pWindowElement->FindAll(TreeScope_Subtree, pcondition, &pcontrolelementarr);
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("CreatePropertyCondition error: %d\n"), hr);
return NULL;
}
// get number of controls found
int numfound;
pcontrolelementarr->get_Length(&numfound);
CDebugPrint::DebugPrint(_T("Controls Found: %d\n"), numfound);
// process controls found, but really we exit earily if container window found
for (int i=0; i < numfound; i++) {
// get individual control element
CComPtr<IUIAutomationElement> pcontrolelement;
hr=pcontrolelementarr->GetElement(i, &pcontrolelement);
if (FAILED(hr)) {
// skip element unable to be retreived
CDebugPrint::DebugPrint(_T("GetElement error: %d\n"), hr);
continue;
}
// output debug information
CComBSTR name;
hr=pcontrolelement->get_CurrentName(&name);
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("GetCurrentName error: %d\n"), hr);
}
CDebugPrint::DebugPrint(_T("Control Name: %s\n"), name);
name.Empty();
hr=pcontrolelement->get_CurrentClassName(&name);
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("GetCurrentClass error: %d\n"), hr);
}
CDebugPrint::DebugPrint(_T("Class Name: %s\n"), name);
name.Empty();
CComPtr<IUIAutomationTreeWalker> pcontentwalker=NULL;
hr=m_pClientUIA->get_ContentViewWalker(&pcontentwalker);
if (pcontentwalker == NULL) {
return NULL;
}
// Get ancestor element nearest to the scrollbar UI Automation element in the tree view
hr=pcontentwalker->NormalizeElement(pcontrolelement, pelement);
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("NormalizeElement error: %d\n"), hr);
return NULL;
}
// output debug information
hr=(*pelement)->get_CurrentName(&name);
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("get_CurrentName error: %d\n"), hr);
}
CDebugPrint::DebugPrint(_T("Ancestor Name: %s\n"), name);
name.Empty();
return TRUE;
}
return FALSE;
}
这不起作用(它没有找到任何东西):
// get main window
if (FindWindow(hwnd, &m_pWindowElement)) {
HRESULT hr;
VARIANT varprop;
// create condition for elements that have UIA_IsScrollPatternAvailablePropertyId available
CComPtr<IUIAutomationCondition> pscrollpatterncondition;
varprop.vt=VT_BOOL;
varprop.boolVal=TRUE;
hr=m_pClientUIA->CreatePropertyCondition(UIA_IsScrollPatternAvailablePropertyId, varprop, &pscrollpatterncondition);
// check result
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("CreatePropertyCondition for ScrollPattern Error: %d\n"), hr);
}
else {
// find the matching element
CComPtr<IUIAutomationElementArray> pscrollpatternarr;
hr=m_pWindowElement->FindAll(TreeScope_Subtree, pscrollpatterncondition, &pscrollpatternarr);
// check result (normal is success with empty array if not found)
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("FindAll Error: %d\n"), hr);
}
else {
// get number of elements in array
int numfound=0;
pscrollpatternarr->get_Length(&numfound);
// make sure we only get one scrollable area - in the future we could figure out the rect
// **numfound is 0**
这确实有效:
// get main window
if (FindWindow(hwnd, &m_pWindowElement)) {
// get scrollable window element based on scrollbar
if (FindContainerWindowElement(UIA_ScrollBarControlTypeId, &m_pScrollableElement)) {
HRESULT hr;
// get the scroll pattern
hr=m_pScrollableElement->GetCurrentPattern(UIA_ScrollPatternId, (IUnknown**) &m_pScrollPattern);
if (FAILED(hr)) {
CDebugPrint::DebugPrint(_T("GetCurrentPattern for Scroll Pattern Error %d:\n"), hr);
}
else if (m_pScrollPattern!=NULL) {
// **we're good!!**
解决方案
为什么我不能只找到具有可用滚动模式的元素?
正如@HansPassant 指出的那样,使用VARIANT_TRUE
(-1
)而不是TRUE
(1
)。
更正上述错误后,以下代码可用于查找具有IUIAutomationScrollPattern
可用滚动模式 ( ) 和滚动(垂直滚动条)的元素。
VARIANT varprop;
// create condition for elements that have UIA_IsScrollPatternAvailablePropertyId available
CComPtr<IUIAutomationCondition> pscrollpatterncondition;
varprop.vt = VT_BOOL;
varprop.boolVal = VARIANT_TRUE;
hr = m_pClientUIA->CreatePropertyCondition(UIA_IsScrollPatternAvailablePropertyId, varprop, &pscrollpatterncondition);
// check result
if (FAILED(hr)) {
}
else {
// find the matching element
CComPtr<IUIAutomationElementArray> pscrollpatternarr;
hr = m_pWindowElement->FindAll(TreeScope_Subtree, pscrollpatterncondition, &pscrollpatternarr);
// check result (normal is success with empty array if not found)
if (FAILED(hr)) {
}
else {
// get number of elements in array
numfound = 0;
pscrollpatternarr->get_Length(&numfound);
for (int i = 0; i < numfound; i++)
{
IUIAutomationElement *element = NULL;
pscrollpatternarr->GetElement(i, &element);
IUIAutomationScrollPattern *m_pScrollPattern = NULL;
hr = element->GetCurrentPattern(UIA_ScrollPatternId, (IUnknown**)&m_pScrollPattern);
if (FAILED(hr)) {
}
else if (m_pScrollPattern != NULL) {
// Scroll vertical scrollbar
m_pScrollPattern->Scroll(ScrollAmount_NoAmount, ScrollAmount_LargeIncrement);
}
}
}
}
推荐阅读
- android - Android 片段测试错误:Manifest 主要属性的签名文件摘要无效
- python - 如何使用 python 从网页中读取值?
- c - RockPaperScissor 游戏没有得到预期的结果 - C 编程
- python - 从标记之间的长字符串中提取子集字符串
- javascript - 我如何让这个按钮粘在屏幕上
- python - django 从 post 方法传递上下文数据
- tensorflow - 如何在 Tensorflow Keras 中实现多个 CRF 输出?
- github - 从 Azure Pipeline 创建 GitHub PR 评论
- java - 在 Java 中重采样音频
- php - 将允许添加到购物车的产品的最大数量设置为 6 并通知