overrainy 发表于 2017-2-15 10:24:07

Java UI 的模拟点击输入

应该会有一部分小伙伴有需求使用AU3在Java UI 界面如何点击输入。查阅之后发现只有零星的一些资料。最接近可使用的也是在XP上面的一个UDF,然而此UDF并不能在Win7 64bit下使用。于是翻阅一些资料,做了一个简单的dos command下的exe 可以被AU3调用,进而模拟在Java UI上进行点击输入等。由于时间问题只有简单编写,此贴也仅仅是提供一个思路。如果有很多人有需求并且有时间的话,在考虑做出一个完整的UDF来共使用。
原理是利用Oracle公司提供的Java access bridge。参考URL如下:
http://docs.oracle.com/javase/accessbridge/2.0.2/api.htm
Dos command: AutoitAccessJavaCMD.exe JavaUI_Name /button Root
For example: AutoitAccessJavaCMD.exe OfflineBuildTool-2.0.5.1 /button 0,1,0,0,0 ;点击button
                     AutoitAccessJavaCMD.exe OfflineBuildTool-2.0.5.1 /checkbox 0,1,0,1,0,0,0,0,0,15,0 ;选择checkbox
                     AutoitAccessJavaCMD.exe OfflineBuildTool-2.0.5.1 /input 0,1,0,1,0,0,0,0,0,8 abcdefg ;input窗口输入abcdefg
                     AutoitAccessJavaCMD.exe OfflineBuildTool-2.0.5.1 /combox 0,1,0,1,0,0,0,0,0,6 3 ;下拉list选择,3代表选择第三个
AU3调用很简单。
_RunDos(AutoitAccessJavaCMD.exe OfflineBuildTool-2.0.5.1 /button 0,1,0,0,0)
代码很凌乱,没有整理,大概贴一下主要的部分以及我觉得需要说明的部分。(其中有一些函数是直接copy的别人的,但是拿的谁的我忘记了。。。)
C++/MFC不是经常使用,使用率很低(其实是我很讨厌这两个家伙)自己也是边用边查(边抄)。所以代码质量很低,莫笑~
另外我只是写了我需要的部分,其他就没写。 对于子窗口的操作需要将FindWindow函数换成FindWindowEx,才能找到并操作子窗口。
MessageBoxTimeout(NULL,L"1",L"2",MB_OK,0,500); 这个很重要,想要成功运行必须先进行弹窗,如果你用MFC去编写的话,应该就不会需要先有窗口的创建。原因我也不知道为什么,只是猜测Java access bridge需要先创建一个窗口才能运行。需要证实。#include <objbase.h>
#include <iostream>
#include "AccessBridge.h"
#include "AccessBridgeCallbacks.h"
#include "AccessBridgeCalls.h"
#include "AccessBridgePackages.h"
#include <string.h>
#include <stdio.h>


#include "Au3AccessJava.h"

using namespace std;

BOOL main(int argc, char* argv[])
{
        int flag = 0;
        int g_levelOrder;
        int g_nDepthOrder;
        if (argc>5)
        {
                return FALSE;
        }else
        {
                char dst;
                //printf("%s\n", argv);
                char* deep = argv;

                int cnt = split(dst,deep,",");
                for (int i=0; i<cnt; i++)
                {
                        g_levelOrder = atoi(dst);
                        g_nDepthOrder = i+1;
                }
        }

        if (initializeAccessBridge() == TRUE)
        {
                HWND Jhwnd = FindWindow(L"SunAwtFrame",c2w(argv));
                printf("find windows %x\n", Jhwnd);
                MessageBoxTimeout(NULL,L"1",L"2",MB_OK,0,500);
                if (IsJavaWindow(Jhwnd))
                {
                        long vmID = 0;
                        AccessibleContext ac = 0;
                        if (GetAccessibleContextFromHWND(Jhwnd, &vmID, &ac) == TRUE)
                        {
                                if (strcmp(argv,"/button")==0)
                                {
                                        AccessibleContext Button_Result;
                                        Button_Result = GetAcessContextByArray(vmID,ac,g_levelOrder, g_nDepthOrder);
                                        ClickOneButton(vmID,Button_Result);
                                        flag = 1;
                                }
                                else if (strcmp(argv,"/checkbox")==0)
                                {
                                        AccessibleContext CheckBox_Result;
                                        CheckBox_Result = GetAcessContextByArray(vmID, ac, g_levelOrder, g_nDepthOrder);                               
                                        SelectCheckBox(vmID,CheckBox_Result);
                                        flag = 1;
                                }
                                else if (strcmp(argv,"/combox")==0)
                                {
                                        AccessibleSelection ComBox_Result;
                                        ComBox_Result = GetAcessContextByArray(vmID, ac, g_levelOrder, g_nDepthOrder);                               
                                        AddAccessibleSelectionFromContext(vmID,ComBox_Result,atoi(argv));
                                        flag = 1;
                                }
                                else if (strcmp(argv,"/input")==0)
                                {
                                        AccessibleContext Input_Result;
                                        Input_Result = GetAcessContextByArray(vmID, ac, g_levelOrder, g_nDepthOrder);
                                        if (setTextContents(vmID, Input_Result,c2w(argv)))
                                        {
                                                flag = 1;
                                        }
                                        else
                                        {
                                                flag = 0;
                                        }
                                }
                                else
                                {
                                        flag = 0;
                                }
                        }
                }

                shutdownAccessBridge();
        }
        if (flag==1)
        {
                return TRUE;
        }
        else
        {
                return FALSE;
        }
        //system("pause");
}

AccessibleContextFindAccessContext(long vmID, AccessibleContext parentAC, const wchar_t * name)

{
        AccessibleContext act = 0;
        AccessibleContextInfo aaci ;
        GetAccessibleContextInfo(vmID, parentAC, &aaci);
        for (int i = 0; i < aaci.childrenCount; i++)
        {
                AccessibleContext childAC = GetAccessibleChildFromContext(vmID, parentAC, i);
                AccessibleContextInfo aacif;
                GetAccessibleContextInfo(vmID, childAC, &aacif);
                const wchar_t* Aname = aacif.name;
                int childCount = aacif.childrenCount;
                if (wcscmp(name,Aname) == 0)
                {
                        act = childAC;
                        return act;
                }
                else
                {
                        if (childCount > 0)
                        {
                                //如果有子节点 递归
                                AccessibleContext acTemp =FindAccessContext(vmID, childAC, name);
                                if (acTemp != 0)
                                {
                                        //如果找到则返回,否则继续找其他兄弟路径
                                        return acTemp;
                                }
                        }
                }
        }
        return act;
}

void ClickOneButton(long vmID, AccessibleContext acButton)

{

        //获取控件的可执行动作

        AccessibleActions actionList;

        getAccessibleActions(vmID, acButton, &actionList);

        jint nReturn = 0;

        //将要执行的动作赋值给TODO

        AccessibleActionsToDo actionTodoList;

        actionTodoList.actions = actionList.actionInfo;

        actionTodoList.actionsCount = 1;

        //执行该动作

        doAccessibleActions(vmID, acButton, &actionTodoList, &nReturn);

        if (nReturn < 0)

        {

                //成功与不成功都是返回的-1

                //MessageBox("当前动作没有执行成功!");

        }

}

AccessibleContext GetAcessContextByArray( long vmId, AccessibleContext rootAc, int levelArray[], int length )
{
        AccessibleContext childAc = rootAc;
        for (int i = 0; i < length && childAc != 0; i++)
        {
                childAc = GetAccessibleChildFromContext(vmId, childAc, levelArray);
                //printf("%d\n", i);
        }
        if (childAc == 0)
        {
                //MessageBox("没有获取到控件ac!");
                printf("can not find ac\n");
        }
        return childAc;
}

void SelectCheckBox(long vmID, AccessibleContext CheckBox)

{

        //获取控件的可执行动作

        AccessibleActions actionList;

        getAccessibleActions(vmID, CheckBox, &actionList);

        jint nReturn = 0;

        //将要执行的动作赋值给TODO

        AccessibleActionsToDo actionTodoList;

        actionTodoList.actions = actionList.actionInfo;

        actionTodoList.actionsCount = 1;

        //执行该动作

        doAccessibleActions(vmID, CheckBox, &actionTodoList, &nReturn);

        if (nReturn < 0)

        {

                //成功与不成功都是返回的-1

                //MessageBox("当前动作没有执行成功!");

        }

}

int split(char dst[], char* str, const char* spl)
{
        int n = 0;
        char *result = NULL;
        result = strtok(str, spl);
        while( result != NULL )
        {
                strcpy(dst, result);
                result = strtok(NULL, spl);
        }
        return n;
}

wchar_t* c2w(const char *str)
{
        int length = strlen(str)+1;
        wchar_t *t = (wchar_t*)malloc(sizeof(wchar_t)*length);
        memset(t,0,length*sizeof(wchar_t));
        MultiByteToWideChar(CP_ACP,0,str,strlen(str),t,length);
        return t;
}所需源文件均在附件中,编译软件为Vs2010.

overrainy 发表于 2017-2-15 10:39:09


对Root路径的说明。

Wh1t3 发表于 2017-2-19 07:18:14

感谢分享~
页: [1]
查看完整版本: Java UI 的模拟点击输入