首页 文章

如何从QProcess获取QWidgets并与之交互

提问于
浏览
1

我有 Application A 这是使用Qt库的第三方Windows应用程序(带有GUI) .

我想写 Application B ,负责启动 Application A . 我希望 Application B 也能找到 Application BQWidgets )上的按钮并发送鼠标输入(点击,双击等) .

我可以通过在 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 回答

  • 1

    这将永远不会像你想要的那样工作 .

    如果您真的希望直接控制其他应用程序,则必须将代码注入该应用程序 . 我们假设应用程序使用动态链接的Qt . 然后:

    • 使用用于构建要调整的应用程序的相同编译器构建Qt的二进制兼容版本 .

    • 用您的Qt替换应用程序的Qt . 鉴于你的应该是二进制兼容的,一切都应该仍然可以正常工作 . 如果没有,那么二进制兼容性就不存在了,你必须调整它们才能工作 .

    • 编辑你的Qt以添加一个钩子来初始化 QApplication 构造函数末尾的代码 . 这使得提供 QApplication 的Qt模块依赖于您的代码 .

    • 将您的代码放入一个小部件,即小部件(对于Qt 5)或gui(对于Qt 4)模块现在依赖于该小部件 .

    • 再次用您的Qt替换应用程序的Qt,使用启动代码的钩子 .

    您的代码当然需要是异步的,并且将通过检查 qApp->activeWindow()qApp->allWidgets() 等来监视应用程序的进度 .

    这几乎是唯一的方法 . 您当然可以以任何其他方式注入代码,但是您需要使用Qt的二进制兼容版本来编译代码 . 请注意,二进制兼容性不仅仅包含使用相同的编译器版本和Qt版本 . 许多 configure 开关也必须相同 .

相关问题