基本信息
源码名称:WinACC测试
源码大小:5.13KB
文件格式:.zip
开发语言:C/C++
更新时间:2021-04-16
   友情提示:(无需注册或充值,赞助后即可获取资源下载链接)

     嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300

本次赞助数额为: 2 元 
   源码介绍

#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#include <oleacc.h>
#include <atlcomcli.h>
#pragma comment(lib, "Oleacc.lib")

BOOL Init(HWND hWnd, CComQIPtr<IAccessible, &IID_IAccessible>& ppAcc)
{
    HRESULT hr = AccessibleObjectFromWindow(hWnd, OBJID_WINDOW, IID_IAccessible, (void**)&ppAcc);
    if (hr != S_OK) 
        return FALSE;
    return TRUE;
}

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)
    {
        // 根据返回的状态值生成以逗号连接的字符串。
        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(strlen(lpszState));
}

void GetObjectName(
                   IAccessible* child,
                   VARIANT* varChild,
                   char* objName,
                   int len) 
{  
    BSTR strTmp;  
    HRESULT hr = child->get_accName(*varChild, &strTmp);  
    if(S_OK!=hr) {  
        return;  
    }  
    //_bstr_t str = strTmp;  
    //wchar_t* tmp = str;  
    wchar_t* tmp = strTmp;  

    WideCharToMultiByte(CP_ACP, 
        0, 
        tmp, 
        -1, 
        objName,
        len, 
        NULL, 
        NULL);
}

void GetObjectRole(
                   IAccessible* child,
                   VARIANT* varChild,
                   char* objRole,
                   int len) 
{  
    VARIANT pvarRole;  
    DWORD roleId;  
    child->get_accRole(*varChild,&pvarRole);  

    if(varChild->vt!=VT_I4) {  
        pvarRole.vt = VT_EMPTY;  
        return /*E_INVALIDARG*/;  
    }  
    roleId = pvarRole.lVal;  
    UINT   roleLength;  
    LPTSTR lpszRoleString;  

    // Get the length of the string.  
    roleLength = GetRoleText(roleId,NULL,0);  

    // Allocate memory for the string. Add one character to  
    // the length you got in the previous call to make room  
    // for the null character.  
    lpszRoleString = (LPTSTR)malloc((roleLength 1) * sizeof(TCHAR));  
    if(lpszRoleString!=NULL) {  
        // Get the string.  
        GetRoleText(roleId,lpszRoleString,roleLength 1);  
    }  
    wchar_t* tmp = lpszRoleString;  
    WideCharToMultiByte(CP_ACP, 
        0, 
        tmp, 
        -1, 
        objRole,
        len, 
        NULL, 
        NULL);
    free(lpszRoleString);  
    return /*S_OK*/;  

}

void GetObjectClass(IAccessible* child,char* objClass,int len) {  
    HWND htmp;  
    LPTSTR strClass;  
    strClass = (LPTSTR)malloc(MAX_PATH);  
    ::WindowFromAccessibleObject(child,&htmp);  
    if(0==::GetClassName(htmp,strClass,MAX_PATH)) {  
        free(strClass);  
        return;  
    }  
    wchar_t* tmp = strClass;  
    WideCharToMultiByte(CP_ACP, 
        0, 
        tmp, 
        -1, 
        objClass,
        len, 
        NULL, 
        NULL);
    free(strClass);  
}  

BOOL FindChild (IAccessible* paccParent, 
                LPSTR szName, LPSTR szRole, 
                LPSTR szClass, 
                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;
    char szObjName[256], szObjRole[256], szObjClass[256], szObjState[256];

    //得到父亲支持的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);
        }
        else
            //如果父支持IEnumVARIANT接口可以直接得到子IDispatch 接口
            pDisp = varChild.pdispVal;

        // 通过 IDispatch 接口得到子的 IAccessible 接口 pCAcc
        if (pDisp)
        {
            hr = pDisp->QueryInterface(IID_IAccessible, (void**)&pCAcc);
            hr = pDisp->Release();
        }

        // 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;

        //跳过了有不可访问状态的元素
        GetObjectState(*paccChild, 
            &varChild, 
            szObjState, 
            sizeof(szObjState));
        if(NULL != strstr(szObjState, "unavailable"))
        {
            if(pCAcc)
                pCAcc->Release();
            continue;
        }
        //通过get_accName得到Name
        GetObjectName(*paccChild, &varChild, szObjName, sizeof(szObjName));
        //通过get_accRole得到Role
        GetObjectRole(*paccChild, &varChild, szObjRole, sizeof(szObjRole));
        //通过WindowFromAccessibleObject和GetClassName得到Class
        GetObjectClass(*paccChild, szObjClass, sizeof(szObjClass));
        //以上实现代码比较简单,大家自己看代码吧。

        //如果这些参数与输入相符或输入为NULL
        if ((!szName || 
            !strcmp(szName, szObjName)) && 
            (!szRole || 
            !strcmp(szRole, szObjRole)) && 
            (!szClass || 
            !strcmp(szClass, szObjClass)))
        {
            found = true;
            *pvarChild = varChild;
            break;
        }
        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 EnumWechat()
{
    // 获取微信窗口 
    HWND hWnd = FindWindow(TEXT("WeChatMainWndForPC"), TEXT("微信"));

    // 转成ACC接口 
    CComQIPtr<IAccessible,&IID_IAccessible> m_pAcc;
    if( !Init(hWnd, m_pAcc) )
    {
        printf("打开失败!\n");
        return ;
    }

    // 获取控件 
    VARIANT varControl;
    IAccessible* paccControl = NULL;
    if( FindChild(m_pAcc, 
        "聊天", 
        "按下按钮", 
        NULL, 
        &paccControl, 
        &varControl) )
    {
        printf("找到控件!\n");
        // 操作控件  
        HRESULT hr = paccControl->accDoDefaultAction(varControl);
        // 发送事件 
        long pxLeft = 0;
        long pyTop = 0;
        long pcxWidth = 0;
        long pcyHeight = 0;
        if (S_OK == paccControl->accLocation(&pxLeft, &pyTop, &pcxWidth, &pcyHeight, varControl)) // 获取到坐标 是全局坐标 
        {
            printf("%u\n", pxLeft);
            HDC hdc = GetDC(GetDesktopWindow());

            // 在控件上画个矩形 
            HPEN hPen = CreatePen(PS_SOLID,0,RGB(255,0,0));  
            HBRUSH hBrush = CreateSolidBrush(RGB(255,0,0)); 
            SelectObject(hdc, hPen);  
            SelectObject(hdc, hBrush); 
            Ellipse(hdc, pxLeft, pyTop, pxLeft pcxWidth, pyTop pcyHeight);
            ReleaseDC(GetDesktopWindow(), hdc);

            // 点击聊天 
            RECT rect = {0};
            GetWindowRect(hWnd, &rect);
            int xpoint, ypoint;
            xpoint = pxLeft-rect.left pcxWidth/2;
            ypoint = pyTop-rect.top pcyHeight/2;
            printf("坐标(%u, %u)\n", xpoint, ypoint);
            SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(xpoint, ypoint));
            SendMessage(hWnd, WM_LBUTTONUP, 0, MAKELONG(xpoint, ypoint));

            Sleep(800);
            // 切换到联系人 
            ypoint  = pcyHeight;
            SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(xpoint, ypoint));
            SendMessage(hWnd, WM_LBUTTONUP, 0, MAKELONG(xpoint, ypoint));
        }

        paccControl->Release();
        VariantClear(&varControl);
    }
}

INT _tmain(INT argc, TCHAR **argv)
{
    CoInitializeEx(NULL, COINIT_MULTITHREADED);

    EnumWechat();

    CoUninitialize();
    return 0;
}