如何维护资源管理器项目视图中当前可见的项目列表
How to maintain a list of the items currently visible in Explorer's items view
我正在尝试维护一个代表Explorer项目视图中项目的IUIAutomationElement
列表(即向量或集合(。我已经为items视图本身获得了一个IUIAutomationElement
,所以从那里我基本上是在尝试跟踪它的item子项。我还需要访问视图中每个项的索引(通过此处讨论的属性(。
我目前的方法是,每当用户滚动时,例如,我用UIA_ListItemControlTypeId
来FindAll
项目视图的子项。这种方法有效而且非常简单,但我想知道它是否效率太低了。因为在任何卷轴上,无论多小,都要做很多工作。
我的另一个想法是在items视图中为StructureChangedEvent设置一个事件处理程序,它可以在孩子们来来去去时跟踪他们。但在使用AccEvent后,在孩子离开后,被丢弃的孩子的属性似乎不可用,因此我将无法访问该元素(以前的(索引(该属性不适用于虚拟化项目(。所以我不知道从向量中删除什么元素。
那么,还有其他潜在的策略来监视项目视图的子项吗?还是FindAll
是最好的选择,即使它效率低下?
Microsoft UI Automation允许客户端订阅感兴趣的事件。此功能无需持续轮询系统中的UI元素以查看是否有任何信息、结构或状态发生了更改,从而提高了性能
对于这种情况,我们可以通过AddStructureChangedEventHandler
订阅结构更改事件。请参阅下面关于处理结构更改事件的代码示例:
// Defines an event handler for structure-changed events, and
// listens for them on the element specifies by the user.
#include <windows.h>
#include <stdio.h>
#include <UIAutomation.h>
class EventHandler:
public IUIAutomationStructureChangedEventHandler
{
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<IUIAutomationStructureChangedEventHandler*>(this);
else if (riid == __uuidof(IUIAutomationStructureChangedEventHandler))
*ppInterface=static_cast<IUIAutomationStructureChangedEventHandler*>(this);
else
{
*ppInterface = NULL;
return E_NOINTERFACE;
}
this->AddRef();
return S_OK;
}
// IUIAutomationStructureChangedEventHandler methods
HRESULT STDMETHODCALLTYPE HandleStructureChangedEvent(IUIAutomationElement* pSender, StructureChangeType changeType, SAFEARRAY* pRuntimeID) {
_eventCount++;
switch (changeType)
{
case StructureChangeType_ChildAdded:
wprintf(L">> Structure Changed: ChildAdded! (count: %d)n", _eventCount);
break;
case StructureChangeType_ChildRemoved:
wprintf(L">> Structure Changed: ChildRemoved! (count: %d)n", _eventCount);
break;
case StructureChangeType_ChildrenInvalidated:
wprintf(L">> Structure Changed: ChildrenInvalidated! (count: %d)n", _eventCount);
break;
case StructureChangeType_ChildrenBulkAdded:
wprintf(L">> Structure Changed: ChildrenBulkAdded! (count: %d)n", _eventCount);
break;
case StructureChangeType_ChildrenBulkRemoved:
wprintf(L">> Structure Changed: ChildrenBulkRemoved! (count: %d)n", _eventCount);
break;
case StructureChangeType_ChildrenReordered:
wprintf(L">> Structure Changed: ChildrenReordered! (count: %d)n", _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;
}
wprintf(L"-Use the mouse to point to the element you want to listen from.n");
Sleep(3000);
// Make this application dots-per-inch (DPI) aware.
SetProcessDPIAware();
// Get mouse cursor position and get element from point.
POINT pt;
GetPhysicalCursorPos(&pt);
hr = pAutomation->ElementFromPoint(pt, &pTargetElement);
if (FAILED(hr) || pTargetElement == NULL)
{
ret = 1;
goto cleanup;
}
pEHTemp = new EventHandler();
if (pEHTemp == NULL)
{
ret = 1;
goto cleanup;
}
wprintf(L"-Adding Event Handler.n");
hr = pAutomation->AddStructureChangedEventHandler(pTargetElement, TreeScope_Subtree, NULL, (IUIAutomationStructureChangedEventHandler*) pEHTemp);
if (FAILED(hr))
{
ret = 1;
goto cleanup;
}
wprintf(L"-Press any key to remove event handler and exitn");
getchar();
wprintf(L"-Removing Event Handler.n");
hr = pAutomation->RemoveStructureChangedEventHandler(pTargetElement, (IUIAutomationStructureChangedEventHandler*) pEHTemp);
if (FAILED(hr))
{
ret = 1;
goto cleanup;
}
// Release resources and terminate.
cleanup:
if (pEHTemp != NULL)
pEHTemp->Release();
if (pTargetElement != NULL)
pTargetElement->Release();
if (pAutomation != NULL)
pAutomation->Release();
CoUninitialize();
return ret;
}
这是一份关于订阅UI自动化事件的有用文档。
相关文章:
- 从链接列表c++中删除一个项目
- 如何维护资源管理器项目视图中当前可见的项目列表
- 你能检查一下为什么在这个代码中从链接列表中删除项目不起作用吗
- 在给定的项目列表上实现搜索?
- 从文本文件读取,然后将项目存储到列表中
- 在修改项目列表时,请防止可编辑的Qcombobox选择更改
- 发送 QML 项目列表C++类连接到 QML :M16 错误
- 当SLIST_ENTRY不是项目列表的第一个成员时,使用单向链表
- 项目列表中的组合
- C ++ win 32,我想将项目列表添加到组合框中.我该怎么做
- 当试图在C++eclipse工作区中导出一个团队集(5个项目)时,项目列表是空的
- 随机化项目列表并将其输出到文本文件
- Eclipse CDT 自动更新/同步项目列表(以方便"refresh"相关项目集)
- 在每次迭代中以不同顺序循环遍历项目列表
- “添加到项目列表”是灰色的Qt项目管理对话框
- 从 std::vector<std::vector 中删除任意项目列表<T> >
- QT:来自多个旋转框的项目列表
- QComboBox动态项目列表
- QComboBox 不显示其项目列表
- 在浏览项目列表时保存多个项目的数据