16,472
社区成员
发帖
与我相关
我的任务
分享
//相关头文件 Add 1210
#include <winuser.h>
#include <oleacc.h>
#pragma comment(lib,"oleacc.lib")
//全局变量 Add 1210
HWND hWndMainWindow;
IAccessible *paccMainWindow = NULL;
HRESULT hr;
IAccessible* paccControl = NULL;//输入框的 IAccessible 接口
VARIANT varControl; //子ID
/////////////////////////////////////////
BOOL CmsAccTestDlg::OnInitDialog()
{
CoInitialize(NULL);//初始化com Add1210
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
//根据name,role,classname属性找控件
BOOL FindChild (IAccessible* paccParent, //传入火狐浏览器主窗体句柄
LPSTR szName, //传入子控件Name值
LPSTR szRole, //传入子控件Role值
LPSTR szClass,//传入子控件Class值
IAccessible** paccChild, //传出参数
VARIANT* pvarChild) //传出参数
{
HRESULT hr;
long numChildren; //子控件数量
unsigned long numFetched;
VARIANT varChild;
int index; //索引
//定义指针
IAccessible* pCAcc = NULL;
IEnumVARIANT* pEnum = NULL;
IDispatch* pDisp = NULL;
BOOL found = false; //是否找到需要的子控件
//得到父亲支持的IEnumVARIANT接口
hr = paccParent->QueryInterface(IID_IEnumVARIANT, (PVOID*) & pEnum);
if(pEnum)
pEnum->Reset(); //该行代码,不知道起什么作用???
//取得父亲拥有的可访问的子的数目
paccParent->get_accChildCount(&numChildren);
//搜索并比较每一个子ID,找到名字、角色、类与输入相一致的。
for(index = 1; index <= numChildren && !found; index++)
{
pCAcc = NULL; //临时变量
// 如果支持IEnumVARIANT接口,得到下一个子ID
//以及其对应的 IDispatch 接口
if (pEnum)
hr = pEnum->Next(1, &varChild, &numFetched);
else
{
//如果一个父亲不支持IEnumVARIANT接口,子ID就是它的序号
varChild.vt = VT_I4;
varChild.lVal = index;
}
// 找到此子ID对应的 IDispatch 接口
if (varChild.vt == VT_I4)
{
//通过子ID序号得到对应的 IDispatch 接口
pDisp = NULL; //初始化
hr = paccParent->get_accChild(varChild, &pDisp); //子IDispatch 接口
}
else
//如果父支持IEnumVARIANT接口可以直接得到子IDispatch 接口
pDisp = varChild.pdispVal; //子IDispatch 接口
// 通过 IDispatch 接口得到子的 IAccessible 接口 pCAcc
if (pDisp)
{
hr = pDisp->QueryInterface(IID_IAccessible, (void**)&pCAcc); //pCAcc
hr = pDisp->Release(); //返回S_FALSE
}
// Get information about the child
if(pCAcc)
{
//如果子支持IAccessible 接口,那么子ID就是CHILDID_SELF
VariantInit(&varChild); //初始化变量
varChild.vt = VT_I4;
varChild.lVal = CHILDID_SELF;
*paccChild = pCAcc; //给返回的变量赋值
}
else
//如果子不支持IAccessible 接口
*paccChild = paccParent;
if (*paccChild == NULL)
{
return FALSE;
}
//获取子类控件的name,role,classname属性
HRESULT hrGetName;
BSTR bstrName;
//获取Name属性值,一直返回S_OK
//varChild (I4=0)
//bstrName第一次地址有值,后面几次都是0,但是该指针指向的内容都为空
/**********************************************************/
hrGetName = (*paccChild)->get_accName(varChild, &bstrName);
/**********************************************************/
CString showMsg = COLE2CT(bstrName); //将BSTR转换为CString
//CString showMsg;
//showMsg.Format("%S",bstrName);
AfxMessageBox(showMsg); //显示获取的Name值
SysFreeString(bstrName);//释放资源
if (!SUCCEEDED(hrGetName))
return 0;
//如果这些参数与输入相符或输入为NULL
showMsg.TrimLeft();
showMsg.TrimRight();
//找到Name值为"搜索书签和历史"的控件
if (showMsg.Find(L"搜索书签和历史") >-1)
{
found = true;
*pvarChild = varChild; //给返回的变量赋值
break; //返回true
}
//递归调用
if(!found && pCAcc)
{
//以这次得到的子接口为父递归调用
found = FindChild(pCAcc,
szName,
szRole,
szClass,
paccChild,
pvarChild);
if(*paccChild != pCAcc)
pCAcc->Release();
}
} //End for
// Clean up
if(pEnum)
pEnum->Release();
return found;
}
//测试查找火狐浏览器输入地址的文本框
void CmsAccTestDlg::OnBnClickedButton1()
{
//得到打开的 "火狐浏览器" 窗口的句柄
if(!(hWndMainWindow = FindWindow(L"MozillaUIWindowClass", NULL)->GetSafeHwnd()))
{
MessageBox(L"没有发现窗口");
}
else
{
//获取接口指针
if(S_OK == (hr = AccessibleObjectFromWindow(hWndMainWindow,OBJID_CLIENT, IID_IAccessible,(void**)&paccMainWindow)))
{
MessageBox(L"成功获取接口指针");
//……我们可以通过这个指针paccMainWindow进行操作
//在火狐浏览器地址栏输入:www.hao123.com
//传入参数:火狐浏览器窗体句柄,要搜索的子控件Name、Role、ClassName属性值
//传出参数:paccControl,varControl
if(1 == FindChild (paccMainWindow, "搜索书签和历史", "可编辑文字", "MozillaWindowClass",&paccControl,&varControl))
{
//在这里修改文本编辑框的值
hr = paccControl->put_accValue(varControl,CComBSTR("www.hao123.com"));
paccControl->Release();
VariantClear(&varControl);
}
paccMainWindow->Release();
}
}
}
//下面的代码实现普通IE浏览器中网址检查功能。。。
// URLChekcDlg.cpp : implementation file
//功能介绍
//定时检查用户输入的URL
//如果是不良网址则自动关闭,否则不关闭
//访问记录存储到本地数据库中
//不良网址维护在本地数据库中
//火狐浏览器和Google浏览器, 暂时未解决
//系统API相关头文件
#include <string.h>
#include <fstream.h>
#include <stdlib.h>
#include <Tlhelp32.h>
#include "Shlwapi.h"
#include <Vector>
#pragma comment(lib,"shlwapi.lib")
#pragma comment(lib,"oleacc.lib")
HWND arrIEHwnd[100]; //存储所有打开的页面的进程句柄
int countIEHwd; //已经存储的句柄的个数
BOOL isURLExist; //判断URL是否在容器中
HWND h_Wnd;
HWND hwdesk;
int mi;
//数据库操作相关变量
CString m_databaseStatue;
_ConnectionPtr pConn;
_RecordsetPtr pPtr; //创建智能指针对象
//数据库操作相关函数
BOOL ConnectDB();
int ExecuteSQL(CString sqlcom);
void InsertURL(CString strurl,CString strRs);
//存储数据库中已维护的不良网址
std::vector<CString> m_vecStr;
std::vector<CString>::iterator Iter;
//存储从开机到现在用户已经访问的网址
std::vector<CString> m_vecStrUrl;
std::vector<CString>::iterator IterUrl;
//定义系统回调函数
BOOL CALLBACK EnumIEProc(HWND,LPARAM);
BOOL CALLBACK EnumChildProc2(HWND,LPARAM);
BOOL CALLBACK EnumWindowsProcClose(HWND hwnd, LPARAM lParam);
//获取本地数据库中的不良网址
BOOL GetbadUrl();
//关闭指定的页面
void CloseBrower(HWND hChild);
//关闭指定的进程(暂时未使用)
DWORD KillProcByName(LPCTSTR strname);
BEGIN_MESSAGE_MAP(CURLChekcDlg, CDialog)
//{{AFX_MSG_MAP(CURLChekcDlg)
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CURLChekcDlg::OnInitDialog()
{
CoInitialize(NULL);//初始化com
//数据库连接字符串
m_databaseStatue = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=checkurl.mdb;Mode=Share Deny None;User ID=Admin;Jet OLEDB:Database Password=;";
GetbadUrl(); //查询数据库中的不良网址
SetTimer(1000,125,NULL); //启动定时器
return TRUE; // return TRUE unless you set the focus to a control
}
//定时器
void CURLChekcDlg::OnTimer(UINT nIDEvent)
{
hwdesk=CWnd::GetDesktopWindow()->GetSafeHwnd();
countIEHwd=0;
//枚举已经打开的Web页面,并且把页面进程的句柄保存到数组中
EnumChildWindows(hwdesk,&EnumIEProc,0);
for(mi=0; mi<countIEHwd; ++mi)
{
//查找指定页面中的URL编辑框
//关闭不良网页并且记录到本地数据库中
EnumChildWindows(arrIEHwnd[mi],&EnumChildProc2,NULL);
}
CDialog::OnTimer(nIDEvent);
}
//连接本地Access数据库
BOOL ConnectDB()
{
pConn.CreateInstance("ADODB.Connection");
HRESULT res;
try
{
res= pConn->Open((_bstr_t)m_databaseStatue,"","",0);
}
catch (_com_error &er)
{
CString errStr;
errStr.Format("数据库连接失败:%s",er.ErrorMessage());
return FALSE;
}
return TRUE;
}
//对本地Access数据库, 执行增删改操作
int ExecuteSQL(CString sqlcom)
{
if(!ConnectDB())
return -1;
_variant_t rowCount;
rowCount.vt = VT_INT;
try
{
pConn->Execute((_bstr_t)sqlcom,&rowCount,adCmdUnknown);
}
catch(_com_error &er)
{
CString errStr;
errStr.Format("执行SQL语句失败:%s",er.ErrorMessage());
pConn->Close();
return -1;
}
pConn->Close();
return rowCount.intVal;
}
//把用户访问的URL, 保存到本地Access数据库中
void InsertURL(CString strURL,CString strResult)
{
CString str;
CTime m_time;
m_time =CTime::GetCurrentTime();
CString strCurTime = m_time.Format("%Y-%m-%d %H:%M:%S");
str.Format("insert into urlhistory(mytime,myurl,myresult) values('%s','%s','%s')",strCurTime,strURL,strResult);
ExecuteSQL(str);
}
//从数据库查询不良网址列表
BOOL GetbadUrl()
{
using namespace std;
BOOL retFlg = FALSE;
CString strUrl;
try
{
if(FAILED(pPtr.CreateInstance("ADODB.Recordset")))
{
retFlg = FALSE;
return retFlg;
}
//查询语句
CString strSQL = "select urlname from badurl";
_variant_t varSRC(m_databaseStatue);
_variant_t varSQL(strSQL);
if(FAILED(pPtr->Open(varSQL,varSRC,adOpenStatic,adLockOptimistic,adCmdText)))
{
retFlg= FALSE;
pPtr.Release();
return retFlg;
}
while(!pPtr->GetadoEOF())
{
_variant_t varUrl;
varUrl = pPtr->GetCollect("urlname");
strUrl = (char *)_bstr_t(varUrl);
strUrl.TrimRight();
m_vecStr.push_back(strUrl);
retFlg = TRUE;
pPtr->MoveNext();
}
//关闭数据库连接,释放资源
pPtr->Close();
pPtr.Release();
}
catch (CException* e)
{
retFlg = FALSE;
return retFlg;
}
return retFlg;
}
//关闭不良网址
void CloseBrower(HWND hChild)
{
HANDLE hProcessHandle;
ULONG nProcessID;
//根据窗体句柄获取进程ID
::GetWindowThreadProcessId(hChild, &nProcessID );
//根据进程ID获取进程句柄
hProcessHandle = ::OpenProcess( PROCESS_TERMINATE, FALSE, nProcessID );
//关闭进程
TerminateProcess( hProcessHandle, 4 );
}
//枚举所有已经打开的Web页面
//根据页面标题来区分是否Web页面
BOOL CALLBACK EnumIEProc(HWND hChild,LPARAM l_param2)
{
char strTitle[260];
//根据句柄,获取窗体标题
int titleLength = GetWindowText(hChild,strTitle,254);
//浏览器类型
char strTitle1[30]="Internet Explorer";
char strTitle2[30]="Maxthon";
char strTitle3[30]="Firefox";
char strTitle4[30]="360安全浏览器";
char strTitle5[30]="Tencent Traveler";
char strTitle6[30]="世界之窗";
char strTitle7[30]="Opera";
char strTitle8[30]="Netscape";
if (strstr(strTitle,strTitle1)!=NULL||
strstr(strTitle,strTitle2)!=NULL||
strstr(strTitle,strTitle3)!=NULL||
strstr(strTitle,strTitle4)!=NULL||
strstr(strTitle,strTitle5)!=NULL||
strstr(strTitle,strTitle6)!=NULL||
strstr(strTitle,strTitle7)!=NULL||
strstr(strTitle,strTitle8)!=NULL)
{
if (titleLength>1)
arrIEHwnd[countIEHwd]=hChild;
countIEHwd = countIEHwd + 1;
}
return TRUE;
}
//查找Web页面中的URL文本编辑框
BOOL CALLBACK EnumChildProc2(HWND hwchld,LPARAM l_param2)
{
char stre[300];
char strm[300];
HWND hParent;
HWND hld;
hld=hwchld;
hParent=(HWND)l_param2;
char ser[10]="Edit";
CString strSwp;
CString strBadUrl;
char *p=NULL;
BOOL bFind=FALSE;
//根据句柄获取类名
int yr=GetClassName(hld,stre,254);
//查找子串出现的位置
if (strstr(stre,ser)!=NULL)
{
//获取URL文本框中网址的长度
int urlLength = SendMessage(hld,WM_GETTEXTLENGTH,0,0)+1 ;
//获取用户输入的URL
SendMessage(hld,WM_GETTEXT,299,(LPARAM)(LPCSTR)strm);
if (urlLength>1) //判断网址长度
{
isURLExist = TRUE;
//判断用户刚打开的网址,是否在不良网址列表中
for ( Iter = m_vecStr.begin() ; Iter != m_vecStr.end() ; Iter++ )
{
strBadUrl.Format("%s",*Iter);
if (strstr(strm,strBadUrl)!=NULL)
{
InsertURL(strm,"拦截");
KillTimer(h_Wnd,1000);
//MessageBox(arrIEHwnd[mi],"您所浏览的网页不允许访问","提示信息",0);
CloseBrower(arrIEHwnd[mi]);
SetTimer(h_Wnd,1000,125,0);
break;
}
}
//判断用户刚打开的网页,是否最近访问过
//如果最近访问过,则不做记录
for ( IterUrl = m_vecStrUrl.begin() ; IterUrl != m_vecStrUrl.end() ; IterUrl++ )
{
strBadUrl.Format("%s",*IterUrl);
if (strstr(strm,strBadUrl)!=NULL)
{
//最近已经访问过该网地址,不保存访问记录
isURLExist=FALSE;
break;
}
}
//收到回车消息
if (GetAsyncKeyState(VK_RETURN))
{
if (isURLExist==TRUE)
{
if(strstr(strm,"http:")!=NULL)
{
//插入到不良网址容器中
m_vecStrUrl.push_back(strm);
InsertURL(strm,"放行");
}
}
}
//收到鼠标左键消息
if (GetAsyncKeyState(VK_LBUTTON))
{
if (isURLExist==TRUE)
{
if(strstr(strm,"http:")!=NULL)
{
//插入到不良网址容器中
m_vecStrUrl.push_back(strm);
InsertURL(strm,"放行");
}
}
}
} //if (urlLength>1)
} //if (strstr(stre,ser)!=NULL)
return TRUE;
}
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
{
TCHAR buf[100];
::GetClassName( hwnd, (LPTSTR)&buf, 100 );
if ( _tcscmp( buf, _T("Internet Explorer_Server") ) == 0 )
{
*(HWND*)lParam = hwnd;
return FALSE;
}
else
return TRUE;
};
HWND hWnd = NULL;
USES_CONVERSION;
hWnd = ::FindWindowExW(hWnd, 0, L"IEFrame", NULL);
CoInitialize( NULL );
// Explicitly load MSAA so we know if it's installed
HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") );
if ( hInst != NULL )
{
if ( hWnd != NULL )
{
HWND hWndChild=NULL;
// 获取第一个文档窗口
::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
if ( hWndChild )
{
CComPtr<IHTMLDocument2> spDoc;
LRESULT lRes;
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );
LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, (LPCSTR)"ObjectFromLresult" );
if ( pfObjectFromLresult != NULL )
{
HRESULT hr;
hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument2, 0, (void**)&spDoc );
if ( SUCCEEDED(hr) )
{
// 获取各个控件
CComQIPtr < IHTMLElementCollection > spElementCollection;
hr = spDoc->get_forms(&spElementCollection);
long nFormCount=0; //取得表单数目
hr = spElementCollection->get_length( &nFormCount );
for(long i=0; i <nFormCount; i++)
{
IDispatch *pDisp = NULL; //取得第 i 项表单
hr = spElementCollection->item( CComVariant( i ), CComVariant(), &pDisp );
if ( FAILED( hr ) ) continue;
CComQIPtr < IHTMLFormElement > spFormElement = pDisp;
pDisp->Release();
long nElemCount=0; //取得表单中 域 的数目
hr = spFormElement->get_length( &nElemCount );
if ( FAILED( hr ) ) continue;
for(long j=0; j <nElemCount; j++)
{
CComDispatchDriver spInputElement; //取得第 j 项表单域
hr = spFormElement->item( CComVariant( j ), CComVariant(), &spInputElement );
if ( FAILED( hr ) ) continue;
CComVariant vName,vVal,vType; //取得表单域的 名,值,类型
hr = spInputElement.GetPropertyByName( L"name", &vName );
if( FAILED( hr ) ) continue;
hr = spInputElement.GetPropertyByName( L"value", &vVal );
if( FAILED( hr ) ) continue;
hr = spInputElement.GetPropertyByName( L"type", &vType );
if( FAILED( hr ) ) continue;
LPCTSTR strCheckType = _T("checkbox");
LPCTSTR strTextType= _T("text");
LPCTSTR strSelectType = _T("select-one");
LPCTSTR strElementType = vType.bstrVal ? OLE2CT( vType.bstrVal ) : _T("NULL");
LPCTSTR strElementName = vName.bstrVal ? OLE2CT( vName.bstrVal ) : _T("NULL");
LPCTSTR strValue = vVal.bstrVal ? OLE2CT(vVal.bstrVal) : _T("NULL");
if (StrCmp(strTextType, strElementType)==0)
{
if(!StrCmp(strElementName, _T("控件名")))
{ CComVariant vSet="xxxxx"; spInputElement.PutPropertyByName(L"value", &vSet); //为控件填充xxxxx
CComBSTR str = NULL;
hr = spGetText->get_value(&str); //获取控件文本
}
}
}//for j
}//for i
}
}
} // else document not ready
} // else Internet Explorer is not running
::BringWindowToTop(hWnd);
::FreeLibrary( hInst );
} // else Active Accessibility is not installed
CoUninitialize();
}
CComBSTR type;
hr=pPwdElement->get_type(&type); //这里修改成获取Role,Name,State属性不知道是否可以?
if(SUCCEEDED(hr)){
if(type==_T("password")){//是密码框吗?
BOOL GetObjectInfo( IAccessible * pAcc,
const VARIANT & varChild,
StrWrPos & str,
BOOL unused( bUseInvoke ) )
{
BOOL fError = FALSE;
// display IAcc, Variant...
// // str << TEXT("IAcc = 0x") << WriteHex( pAcc ) << TEXT(" VarChild:") << varChild;
if( varChild.vt == VT_EMPTY )
{
str << TEXT(" [ BUG? - Non-I4 ChildId ]");
fError = TRUE;
}
LPTSTR pszSpace = TEXT("\r\nInterfaces:\t");
// Check supported interfaces...
IUnknown * pUnk = NULL;
HRESULT hr = pAcc->QueryInterface( IID_IEnumVARIANT, (void **) & pUnk );
if( SUCCEEDED( hr ) && pUnk )
{
pUnk->Release();
str << pszSpace << TEXT("IEnumVARIANT");
pszSpace = TEXT(" ");
}
pUnk = NULL;
hr = pAcc->QueryInterface( IID_IOleWindow, (void **) & pUnk );
if( SUCCEEDED( hr ) && pUnk )
{
pUnk->Release();
str << pszSpace << TEXT("IOleWindow");
pszSpace = TEXT(" ");
}
// See if native...
if( IsOLEACCObject( pAcc ) )
{
str << pszSpace << TEXT("(Local-oleacc-proxy)");
pszSpace = TEXT(" ");
}
str << TEXT("\r\n");
return ! fError;
}
// Convert an IDispatch to an IAccessible/varChild pair.
// Releases the IDispatch.
BOOL Object_IDispatchToIAccessible( IDispatch * pdisp,
IAccessible ** ppAccOut,
VARIANT * pvarChildOut,
StrWrPos & str )
{
IAccessible * pAccTemp = NULL;
HRESULT hr = pdisp->QueryInterface( IID_IAccessible, (void**) & pAccTemp );
pdisp->Release();
if( hr != S_OK || ! pAccTemp )
{
str << WriteError( hr, TEXT("IDisp::QI(IAcc)") );
return FALSE;
}
*ppAccOut = pAccTemp;
if( pvarChildOut )
{
pvarChildOut->vt = VT_I4;
pvarChildOut->lVal = CHILDID_SELF;
}
return TRUE;
}
BOOL IsOLEACCObject( IAccessible * pAcc )
{
if( g_OLEACCAddRef == (void*)1 )
{
// Get a well-known OLEACC window...
HWND hWnd = GetDesktopWindow();
// Get an IAccessible from it...
IAccessible * pAcc = NULL;
HRESULT hr = AccessibleObjectFromWindow( hWnd, OBJID_CLIENT, IID_IAccessible, (void **) &pAcc );
if( hr != S_OK || pAcc == NULL )
return FALSE;
// Pull the address of AddRef() from its vtbl... (first member)
if( pAcc && *(void**)pAcc )
g_OLEACCAddRef = **(void***) pAcc;
pAcc->Release();
}
// Look at first member of VTBL - should be same for all
// OLEACC objects, since they all use the same AddRef code.
// pAcc interface pointer
// *(void*)pAcc points to vtbl
// **(void**)pAcc contents of first slot of vtbl (AddRef)
return pAcc
&& *(void**)pAcc
&& **(void***)pAcc == g_OLEACCAddRef;
}
void GetWindowInfo( HWND hWnd,
StrWrPos & str )
{
// Add coords...
str << TEXT("\thwnd=0x");
// add hwnd...
str << WriteHex( hWnd );
// add class...
str << TEXT(" class=\"");
int len = GetClassName( hWnd, str.ptr(), str.left() );
str.advance( len );
str << TEXT("\"");
LONG gwl = GetWindowLong( hWnd, GWL_STYLE );
str << TEXT(" style=0x") << WriteHex( gwl );
gwl = GetWindowLong( hWnd, GWL_EXSTYLE );
str << TEXT(" ex=0x") << WriteHex( gwl );
}
void DisplayObjectErrorMessage( LPCTSTR pszHowFound,
HWND hWnd,
LPCTSTR pszErrorMessage )
{
// Clear the window...
Edit_Clear( g_hEdit );
// Add the 'how found' text...
StrBuf<128> str;
str << TEXT("How found:\t") << pszHowFound << TEXT("\r\n");
Edit_Append( g_hEdit, str.str() );
if( hWnd )
{
// Add window information...
str.Reset();
GetWindowInfo( hWnd, str );
str << TEXT("\r\n");
Edit_Append( g_hEdit, str.str() );
}
Edit_Append( g_hEdit, TEXT("------\r\n\r\n") );
Edit_Append( g_hEdit, pszErrorMessage );
// TODO - clear focus rect etc. ?
// For old times' sake...
MessageBeep(0);
}
// --------------------------------------------------------------------------
//
// DisplayObjectProperties()
//
// If no object is passed in,
// this gets the object at the cursor, fills in the properties into the
//
// --------------------------------------------------------------------------
void DisplayObjectProperties( LPCTSTR pszHowFound,
HWND hWnd,
IAccessible * pAcc,
const VARIANT & varChild,
BOOL fDoHilightRect )
{
// Clear the window...
SendMessage( g_hEdit, WM_SETREDRAW, FALSE, 0 );
Edit_Clear( g_hEdit );
// Add the 'how found' text...
StrBuf<128> str;
str << TEXT("How found:\t") << pszHowFound << TEXT("\r\n");
Edit_Append( g_hEdit, str.str() );
if( hWnd )
{
// Add window information...
str.Reset();
GetWindowInfo( hWnd, str );
str << TEXT("\r\n");
Edit_Append( g_hEdit, str.str() );
}
// Get the properties...
StrBuf<4096> strInfoTip;
for( int i = 0 ; i < ARRAYSIZE( g_PropMap ) ; i++ )
{
// Only fetch if it's needed for either the infotip of the main window...
if( g_DlgPropActive[ i ] || g_TipPropActive[ i ] )
{
// Get the property string...
StrBuf<8192> str;
str << g_PropMap[ i ].m_pName << TEXT(":\t");
BOOL fSucceeded = (g_PropMap[ i ].m_pfnGetProp)( pAcc, varChild, str, g_Settings.m_fUseInvoke );
// Add to main window (if needed)...
if( g_DlgPropActive[ i ] )
{
DWORD posBefore = Edit_GetPos( g_hEdit );
Edit_Append( g_hEdit, str.str() );
DWORD posAfter = Edit_GetPos( g_hEdit );
// add newline...
// Done separately from str, since str may not have room for the \r\n...
Edit_Append( g_hEdit, TEXT("\r\n") );
// Code to make any error lines bold red. Very eye-catching.
// TODO - add this back in later when we're comfortable with it...
//
// if( ! fSucceeded )
// {
// Edit_Hilight( g_hEdit, posBefore, posAfter );
// }
}
// Add to info tip text (if needed)...
if( g_TipPropActive[ i ] )
{
strInfoTip << str.str();
strInfoTip << TEXT("\r\n");
}
}
}
// Put cursor at start, scroll to top (so first line appears at top)
Edit_Done( g_hEdit );
// show hilight rectangle...
if( fDoHilightRect )
{
RECT rc;
HRESULT hr = pAcc->accLocation( & rc.left, & rc.top, & rc.right, & rc.bottom, varChild );
if( hr == S_OK )
{
rc.right += rc.left;
rc.bottom += rc.top;
g_pHilightRect->SetLocation( rc );
g_pHilightText->SetLocation( rc );
if( g_Settings.m_fShowHilightRect )
{
g_pHilightRect->SetVisible( TRUE );
}
}
else
{
g_pHilightRect->SetVisible( FALSE );
}
}
// display tooltip information...
g_pHilightText->SetText( strInfoTip.str() );
// Remember this object...
g_SavedAcc.Set( pAcc, varChild );
// Clear the window...
SendMessage( g_hEdit, WM_SETREDRAW, TRUE, 0 );
InvalidateRect( g_hEdit, NULL, TRUE );
}
////////////////////////////////////////////////////////////////////////
BOOL GetObjProp_Parent( IAccessible * pAcc, const VARIANT & varChild, StrWrPos & str, BOOL bUseInvoke )
{
HRESULT hr;
IDispatch * pdispParent = NULL;
// if varChild is non-0, then pAcc is the parent.
// otherwise, have to use get_accParent...
if( varChild.lVal == CHILDID_SELF )
{
// use get_accParent...
if( ! bUseInvoke )
{
hr = pAcc->get_accParent(&pdispParent);
}
else
{
DISPPARAMS dispp;
EXCEPINFO excepInfo;
UINT errArg;
VARIANT varResult;
// via IDispatch::Invoke
VariantInit(&varResult);
dispp.cArgs = 0;
dispp.cNamedArgs = 0;
dispp.rgvarg = NULL;
dispp.rgdispidNamedArgs = NULL;
FillMemory(&excepInfo, sizeof(excepInfo), 0);
hr = pAcc->Invoke(DISPID_ACC_PARENT, IID_NULL, 0,
DISPATCH_PROPERTYGET, &dispp, &varResult, &excepInfo, &errArg);
if (SUCCEEDED(hr) && (varResult.vt == VT_DISPATCH))
pdispParent = varResult.pdispVal;
else
VariantClear(&varResult);
}
if( FAILED( hr ) )
{
str << WriteError( hr, TEXT("get_accParent") );
return FALSE;
}
if( ! pdispParent )
{
// TODO - could be an error?
str << TEXT("none [screen]");
return TRUE;
}
pAcc = NULL;
hr = pdispParent->QueryInterface( IID_IAccessible, (void **) & pAcc );
pdispParent->Release();
if( ! SUCCEEDED( hr ) || !pAcc )
return FALSE;
}
VARIANT var;
var.vt = VT_I4;
var.lVal = CHILDID_SELF;
// Get name, role
//获取名称和角色
GetObjProp_Name( pAcc, var, str, bUseInvoke );
str << TEXT(":");
GetObjProp_Role( pAcc, var, str, bUseInvoke );
// Did we get a parent object, if so release it...
if( pdispParent )
pAcc->Release();
return TRUE;
// TODO - how to check the name/role sub-fields for errors?
}
////////////////////////////////////////////////////////////////////////
BOOL GetObjProp_WndFromObj( IAccessible * pAcc,
const VARIANT & unused( varChild ),
StrWrPos & str,
BOOL unused( bUseInvoke ) )
{
HWND hWnd;
HRESULT hr = WindowFromAccessibleObject( pAcc, & hWnd );
BOOL fError = FALSE;
if( hr == S_OK )
{
str << TEXT("0x") << WriteHex( hWnd ) << TEXT(" ");
if( ! IsWindow( hWnd ) )
{
str << TEXT( "invalid hwnd" );
fError = TRUE;
}
else
{
str << TEXT("class=\"");
int l = GetClassName( hWnd, str.ptr(), str.left() );
str.advance( l );
LONG gwl = GetWindowLong( hWnd, GWL_STYLE );
str << TEXT("\" style=0x") << WriteHex( gwl );
gwl = GetWindowLong( hWnd, GWL_EXSTYLE );
str << TEXT(" ex=0x") << WriteHex( gwl );
}
}
else
{
str << WriteError( hr, TEXT("WndFromAccObj") );
fError = TRUE;
}
return ! fError;
}
////////////////////////////////////////////////////////////////////////
BOOL GetObjProp_ChildCount( IAccessible * pAcc,
const VARIANT & varChild,
StrWrPos & str,
BOOL unused( bUseInvoke ) )
{
if( varChild.vt != VT_I4 )
{
str << TEXT("[Error: Non-I4 ChildID - vt=") << varChild << TEXT("]");
return FALSE;
}
// Non-zero means we are over something not a container.
if( varChild.lVal != 0 )
{
str << TEXT( "Child object has no children" );
return TRUE;
}
long cChildren = 0;
HRESULT hr = pAcc->get_accChildCount( & cChildren );
if( FAILED( hr ) )
{
str << WriteError( hr, TEXT("accChildCount") );
return FALSE;
}
str << cChildren;
return TRUE;
}
////////////////////////////////////////////////////////////////////////