我有 Application A
这是使用Qt库的第三方Windows应用程序(带有GUI) .
我想写 Application B
,负责启动 Application A
. 我希望 Application B
也能找到 Application B
( QWidgets
)上的按钮并发送鼠标输入(点击,双击等) .
我可以通过在 QProcess
上使用 start
函数来运行 Application A
.
如何从我的 QProcess
实例中执行以下操作:
-
获取流程的顶级窗口
-
按名称或(其他可识别属性)获取小部件
-
获取小部件 Headers ,颜色和坐标(可能还有其他一些数据)
-
发送鼠标移动并单击事件到特定坐标
-
给小部件键盘焦点
-
发送键盘按键
注意 - 我知道如何使用Windows API执行此操作,但要求通过Qt的方法 . 有问题的 Application A
不使用本机窗口系统,因此窗口句柄不会显示在Spy或Windows API函数中 .
Update 1 - Cannot seem to get any meaningful objects through the process's children
我尝试为此过程获取子窗口小部件:
QProcess* process = new QProcess();
QString program = "\"C:\\Program Files (x86)\\foo\\bar.exe\"";
process->start(program);
auto widgets = process->findChildren<QWidget*>("", Qt::FindChildrenRecursively);
auto i = widgets.count();
// i = 0
如果我找到类型为 <QObject*>
的孩子,我会得到4个结果 . 我用 metaObject()->className()
看到我有两对QWindowsPipeReader和QWinOverlappedIoNotifier对象 .
Update 2 - Cannot create/inject window from another process
我注意到,当我运行QProcess时,我可以使用Windows API函数来获取顶级窗口(仅限顶级) . 我在Qt文档中读到,您可以使用QWindow::fromWinId从另一个进程中的窗口句柄创建QWindow .
使用此函数将抛出 0xC0000005: Access violation reading location 0x00000000.
错误 . 我没有传入一个空句柄 . 我正在使用reinterpret_cast将 HWND
变为 WId
类型 . 它只在我事先创建QApplication时才创建QWindow .
新的QWindow将没有孩子(使用 window->findChildren<QObject*>("", Qt::FindChildrenRecursively);
我假设QWindow的创建不会带来相关的子窗口小部件 .
Update 3 - I am currently reading into whether inter-process communication can be used
我遇到过有关ICP in Qt的各种主题,问题和代码片段 . 到目前为止,我没有看到任何具体表明当其中一个进程是第三方时ICP可能的情况 .
我已经看到Squish Gui测试工具可以让你查询QWidget属性 .
1 回答
这将永远不会像你想要的那样工作 .
如果您真的希望直接控制其他应用程序,则必须将代码注入该应用程序 . 我们假设应用程序使用动态链接的Qt . 然后:
使用用于构建要调整的应用程序的相同编译器构建Qt的二进制兼容版本 .
用您的Qt替换应用程序的Qt . 鉴于你的应该是二进制兼容的,一切都应该仍然可以正常工作 . 如果没有,那么二进制兼容性就不存在了,你必须调整它们才能工作 .
编辑你的Qt以添加一个钩子来初始化
QApplication
构造函数末尾的代码 . 这使得提供QApplication
的Qt模块依赖于您的代码 .将您的代码放入一个小部件,即小部件(对于Qt 5)或gui(对于Qt 4)模块现在依赖于该小部件 .
再次用您的Qt替换应用程序的Qt,使用启动代码的钩子 .
您的代码当然需要是异步的,并且将通过检查
qApp->activeWindow()
,qApp->allWidgets()
等来监视应用程序的进度 .这几乎是唯一的方法 . 您当然可以以任何其他方式注入代码,但是您需要使用Qt的二进制兼容版本来编译代码 . 请注意,二进制兼容性不仅仅包含使用相同的编译器版本和Qt版本 . 许多
configure
开关也必须相同 .