IAccessible ( 二 )

下来会分享如何获取子控件的IAccessible接口,在这个之前先讲点其它的东西:

获取控件如果使用Findwindow(FindwindowEx)我们需要知道的控件的ClassName和CaptionName,这两个信息可以通过Spy++等工具获取,但我们在测试工具中会常见到Role等很多属性,先看这些信息是从什么地方来的,在microsoft的站点上下载Inspect32.exe运行后如:

Inspect

 

上面告诉了我们一个控件的详细信息,现在我们只关心classname, role, name。

下面开始实现获取子控件IAccessible接口的代码,先看函数定义:

BOOL Find (
	IAccessible* paccParent, 
	LPSTR szName, 
	LPSTR szRole, 
	LPSTR szClass, 
	IAccessible** paccChild, 
	VARIANT* pvarChild)
第一个就是父窗体的IAcessible接口,依次分别为:name, role, classname, 子控件接口,类似于ID的东西(后面再解释) >看实现:
BOOL Find (
	IAccessible* paccParent, 
	LPSTR szName, 
	LPSTR szRole, 
	LPSTR szClass, 
	IAccessible** paccChild, 
	VARIANT* pvarChild)
{

	HRESULT hr;
	long numChildren;
	unsigned long numFetched;
	VARIANT varChild;
	int indexCount;
	IAccessible* pCAcc = NULL;
	IEnumVARIANT* pEnum = NULL;
	IDispatch* pDisp = NULL;
	BOOL found = false;
	char szObjName[MAX_PATH], szObjRole[MAX_PATH], szObjClass[MAX_PATH], szObjState[MAX_PATH];

	//Get the IEnumVARIANT interface
	hr = paccParent -> QueryInterface(IID_IEnumVARIANT, (PVOID*) & pEnum);

	if(pEnum)
		pEnum -> Reset();

	// Get child count
	paccParent -> get_accChildCount(&numChildren);

	for(indexCount = 1; indexCount <= numChildren && !found; indexCount++)
	{
		pCAcc = NULL;

		// Get next child
		if (pEnum)
			hr = pEnum -> Next(1, &varChild, &numFetched);	
		else
		{
			varChild.vt = VT_I4;
			varChild.lVal = indexCount;
		}

		// Get IDispatch interface for the child
		if (varChild.vt == VT_I4)
		{
			pDisp = NULL;
			hr = paccParent -> get_accChild(varChild, &pDisp);
		}
		else
			pDisp = varChild.pdispVal;

		// Get IAccessible interface for the child
		if (pDisp)
		{
			hr = pDisp->QueryInterface(IID_IAccessible, (void**)&pCAcc);
			hr = pDisp->Release();
		}

		// Get information about the child
		if(pCAcc)
		{
			VariantInit(&varChild);
			varChild.vt = VT_I4;
			varChild.lVal = CHILDID_SELF;

			*paccChild = pCAcc;
		}
		else
			*paccChild = paccParent;

		// Skip invisible and unavailable objects and their children
		GetObjectState(*paccChild, &varChild, szObjState, sizeof(szObjState));
		if(NULL != strstr(szObjState, "unavailable"))
		{
			if(pCAcc)
				pCAcc->Release();
			continue;
		}

		GetObjectName(*paccChild, &varChild, szObjName, sizeof(szObjName));
		GetObjectRole(*paccChild, &varChild, szObjRole, sizeof(szObjRole));
		GetObjectClass(*paccChild, szObjClass, sizeof(szObjClass));

		if ((!szName || !strcmp(szName, szObjName)) && (!szRole || !strcmp(szRole, szObjRole)) && (!szClass || !strcmp(szClass, szObjClass)))
		{
			found = true;
			*pvarChild = varChild;
			break;

		}
		if(!found && pCAcc)
		{
			// Go deeper
			found = Find(pCAcc, szName, szRole, szClass, paccChild, pvarChild);
			if(*paccChild != pCAcc)
				pCAcc->Release();
		}
	}

	// Clean up
	if(pEnum)
		pEnum -> Release();

	return found;
}
看获取控件状态的函数:
UINT GetObjectState(IAccessible* pacc, VARIANT* pvarChild, LPSTR lpszState, UINT cchState)
{
	HRESULT hr;
	VARIANT varRetVal;

	*lpszState = 0;

	VariantInit(&varRetVal);

	hr = pacc->get_accState(*pvarChild, &varRetVal);

	if (!SUCCEEDED(hr))
		return(0);

	DWORD dwStateBit;
	int cChars = 0;
	if (varRetVal.vt == VT_I4)
	{
		// Convert state flags to comma separated list.
		for (dwStateBit = STATE_SYSTEM_UNAVAILABLE; dwStateBit < STATE_SYSTEM_ALERT_HIGH; dwStateBit <<= 1)
		{
			if (varRetVal.lVal & dwStateBit)
			{
				cChars += GetStateTextA(dwStateBit, lpszState + cChars, cchState - cChars);
				*(lpszState + cChars++) = ',';
			}
		}
		if(cChars > 1)
			*(lpszState + cChars - 1) = '\0';
	}
	else if (varRetVal.vt == VT_BSTR)
	{
		WideCharToMultiByte(CP_ACP, 0, varRetVal.bstrVal, -1, lpszState,
			cchState, NULL, NULL);
	}

	VariantClear(&varRetVal);

	return(lstrlenA(lpszState));
}


用来获取一个控件是否可用。 下来看一个例子: 

HWND hwnd = ::FindWindowW( NULL,L"Run");

	IAccessible *paccMainWindow = NULL;
	AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**)&paccMainWindow);

	long count = 0;
	paccMainWindow->get_accChildCount(&count);

	IAccessible*	paccControl = NULL;
	VARIANT			varControl;

	if (Find(paccMainWindow, "Open:", "editable text", "Edit", &paccControl, &varControl))
	{
		paccControl->put_accValue(varControl, CComBSTR("123"));
	}
	
运行结果:

123Text

 


作者:GangWang
出处:http://www.cnblogs.com/GnagWang/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 
原文地址:https://www.cnblogs.com/GnagWang/p/1716449.html