Qt如何将外部窗口嵌入部件中

一、简述

今天给大家讲解的是使用QWindow类通过窗口句柄将外部的应用程序嵌入到我们的部件中来显示。在讲解之前可以延伸一下,当时项目中使用QProcess启动一些本地软件或者执行脚本时,需要将启动的第三方窗口嵌入到我们自己写的窗口中,此时我们通过QProcess类的start方法执行相应的启动命令,并获取到启动程序的进程id(pid),然后通过pid获取到窗口对应的句柄,最后通过QWindow类创建容器将外部应用程序嵌入到我们的界面中来。

所以讲解之前,会先讲解下如何通过WinApi根据进程id(pid)获取到窗口的句柄,然后再通过窗口句柄使用QWindow来嵌入到我们的界面中来。

二、代码之路

我们先使用WinApi通过进程id(pid)获取到窗口句柄,具体接口以及示例代码如下,大家可直接拷贝即可:


struct FindWindowData
{
    DWORD processId;
    HWND hWnd;
};

BOOL FindWindowCB(HWND hWnd, LPARAM lParam)
{
    DWORD processId = 0;
    if (GetWindowThreadProcessId(hWnd, &processId)) {
        // 分配足够大的缓冲区来存储窗口标题
        const int MAX_TITLE_LENGTH = 255;
        WCHAR windowTitle[MAX_TITLE_LENGTH];

        // 调用 GetWindowTextW 来获取窗口标题
        int result = GetWindowTextW(hWnd, windowTitle, MAX_TITLE_LENGTH);
        // qDebug() << "the text:" << QString::fromWCharArray(windowTitle) << result << hWnd << processId;

        QString title = QString::fromWCharArray(windowTitle);

        FindWindowData* dataPtr = (FindWindowData*)lParam;
        // 这里的筛选条件可能需要继续优化
        if (processId == dataPtr->processId && IsWindowVisible(hWnd) && title.length() > 0) {
            qDebug() << QString("FindWindow  title:%1, hWnd:%2, pid:%3")
                .arg(title).arg((WId)hWnd).arg(processId);
            dataPtr->hWnd = hWnd;
        }

        return TRUE;
    }

    return FALSE;
}

// 寻找特定PID的窗口句柄
HWND findWindowByPID(DWORD dwProcessId)
{
    FindWindowData winData = { dwProcessId, 0 };
    LPARAM p = (LPARAM)&winData;
    EnumWindows((WNDENUMPROC)FindWindowCB, (LPARAM)p); // 遍历系统上打开的窗口

    return winData.hWnd;
}

HWND getWinIdByPid(int pid)
{
    return findWindowByPID(pid);
}

// 测试示例
void testFunc()
{
	 // 创建进程
    QProcess* process = new QProcess(this);
    connect(process, QOverload<int>::of(&QProcess::finished), this, [=]() {
        process->close();
        process->deleteLater();
    });

    QString command = "xxx.exe";
    process->start(command);
	// 这里等待500毫秒是执行完命令等待窗口显示出来,具体时间得看程序启动的快慢;
    QThread::msleep(500);

	// 获取到pid之后通过接口转为窗口句柄;
    int pid = process->processId();
	HWND hWnd = getWinIdByPid(pid);
}

参考自 https://blog.csdn.net/joyopirate/article/details/140928311。


下方代码将获取到的窗口具体通过QWindow::fromWinId方法将窗口句柄转为QWindow对象,通过QWidget::createWindowContainer方法创建一个QWidget,可以将刚刚的窗口对象嵌入到基于QWidget的应用程序中,可以在测试方法中看到具体用法,拿到最终QWidget对象大家就可以嵌入到我们界面的布局中去了。

QWidget* getWindowContainerWgt(int pid)
{
	QWidget* pContainerWgt = nullptr;
    HWND hWnd = getWinIdByPid(pid);
    if (hWnd != nullptr) {
		pContainerWgt = new QWidget;
		// 这里也可以设置具体的大小;
		pContainerWgt->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

        QWindow* pDestWindow = QWindow::fromWinId((WId)hWnd);
        pDestWindow->setFlags(pDestWindow->flags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
        QWidget* pChildWidget = QWidget::createWindowContainer(pDestWindow, pContainerWgt);
        pChildWidget->setObjectName("WindowContainer");

		QHBoxLayout* hLayout = new QHBoxLayout(pContainerWgt);
		hLayout->addWidget(pChildWidget);
		hLayout->setMargin(0);
    }
    else {
        qDebug() << "Can not find winId by pid";
    }

	return pContainerWgt;
}

void testFunc()
{
 	// 创建进程
    QProcess* process = new QProcess(this);
    connect(process, QOverload<int>::of(&QProcess::finished), this, [=]() {
        process->close();
        process->deleteLater();
    });

    QString command = "xxx.exe";
    process->start(command);
	// 这里等待500毫秒是执行完命令等待窗口显示出来,具体时间得看程序启动的快慢;
    QThread::msleep(500);

	// 获取到pid之后通过接口转为窗口句柄;
    int pid = process->processId();
	QWidget* windowWgt = getWindowContainerWgt(pid)
	// 如果获取到的widget不为空,说明已经成功将窗口嵌入到widget中
	if(windowWgt != nullptr){
		// todo
		// ...
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/885249.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

低空经济时代:无人机飞行安全要点详解

随着低空经济的蓬勃发展&#xff0c;无人机&#xff08;UAV&#xff09;在农业、航拍、物流、应急救援等多个领域的应用日益广泛。然而&#xff0c;无人机的安全飞行不仅关乎任务的成功与否&#xff0c;更直接关系到地面人员、财产及空中交通的安全。本文将从飞行前检查、环境评…

react crash course 2024(7) react router dom

安装 npm i react-router-dom 引入 import {Route,createBrowserRouter,createRoutesFromElements,RouterProvider} from react-router-dom 在app.jsx const router createBrowserRouter(createRoutesFromElements(<Route index element {<h1>My App</h1>…

Centos 8安装VNC及多用户配置详细教程

Centos 8安装VNC及多用户配置详细教程 参考一、安装前准备二、安装三、创建新用户和设置VNC密码四、创建VNC系统服务文件五、多用户映射和配置VNC六、客户端用VNC Viewer登录 参考 1、参考1&#xff1a; VNC安装英文说明&#xff08;英文说明有误且仅适合单用户&#xff09;&a…

tauri中加载本地文件图片或者下载网络文件图片后存储到本地,然后通过前端页面展示

有一个需求是需要将本地上传的文件或者网络下载的文件存储到本地&#xff0c;并展示在前端页面上的。其实如果只是加载本地文件&#xff0c;然后展示还是挺简单的&#xff0c;可以看我的文章&#xff1a;tauri程序加载本地图片或者文件在前端页面展示-CSDN博客 要想实现上述需…

[OpenGL]使用OpenGL加载obj模型、绘制纹理

一、简介 本文介绍了如何使用OpenGL加载obj模型&#xff0c;绘制简单纹理。 在加载obj模型时&#xff0c;使用glm库确定对顶点进行坐标变换的MVP(model, view, projection)矩阵。 在绘制纹理时&#xff0c;使用stb_image.h头文件加载纹理图片&#xff0c;生成纹理。 按照本文…

108.WEB渗透测试-信息收集-FOFA语法(8)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;107.WEB渗透测试-信息收集-FOFA语法&#xff08;7&#xff09; 指挥系统的后台&#xff…

排序题目:重新排列后的最大子矩阵

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;重新排列后的最大子矩阵 出处&#xff1a;1727. 重新排列后的最大子矩阵 难度 7 级 题目描述 要求 给定一个大小为 m n \texttt{m} \times \tex…

可以白嫖PPT模板的6个网站,赶紧收藏

推荐6个PPT模板网站&#xff0c;免费下载&#xff0c;绝对的高质量&#xff0c;赶紧收藏&#xff01; 1、菜鸟图库 ppt模板免费下载|ppt背景图片 - 菜鸟图库 菜鸟图库网有非常丰富的免费素材&#xff0c;像设计类、办公类、自媒体类等素材都很丰富。PPT模板种类很多&#xff0…

Python和MATLAB库尔巴克–莱布勒散度信息论统计学生物学和算法模型

&#x1f3af;要点 高斯混合模型聚类和t分布随机邻域嵌入底层分析信息论测量复合彩票统计学计算结果离散分布速率最优估计器样本统计相似性快速闭环散度和交叉熵计算催乳素诱导模型贝叶斯快速推理模型视觉皮层活动神经数据分布 Python散度 在数理统计中&#xff0c;库尔巴克…

Gson将对象转换为JSON(学习笔记)

JSON有两种表示结构&#xff0c;对象和数组。对象结构以"{"大括号开始&#xff0c;以"}"大括号结束。中间部分由0或多个以”&#xff0c;"分隔的”key(关键字)/value(值)"对构成&#xff0c;关键字和值之间以":"分隔&#xff0c;语法结…

PHP程序如何实现限制一台电脑登录?

PHP程序如何实现限制一台电脑登录&#xff1f; 可以使用以下几种方法&#xff1a; 1. IP地址限制&#xff1a;在PHP中&#xff0c;可以通过获取客户端的IP地址&#xff0c;然后与允许登录的IP地址列表进行比对。如果客户端的IP地址不在列表中&#xff0c;就禁止登录。 “php $…

HTTP 1.0 2.0 3.0详解

HTTP HTTP全称超文本传输协议&#xff0c;是一种属于应用层的通信协议。它允许将超文本标记语言文档&#xff08;HTML&#xff09;从Web服务器传输到客户端的浏览器。 HTTP报文结构 请求报文结构 请求方法&#xff1a; GET&#xff1a;一般用来请求已被URI识别的资源&#x…

永不失联!遨游双卫星三防手机成为高效应急关键所在

今年9月被戏称为“台风月”&#xff0c;台风“摩羯”、“贝碧嘉”以及热带气旋“普拉桑”接连来袭&#xff0c;极端天气不仅导致了电力中断、道路损毁&#xff0c;更使得传统的通信网络遭受重创&#xff0c;给应急通信保障工作带来了极大的压力。面对“三断”的实战难题&#x…

从文本图片到多模态:3D 数字人打开企业全域商业增长新空间

摘要&#xff1a;数字化与AI浪潮推动各行业变革&#xff0c;内容形式也发生巨变&#xff0c;从文本到多媒体的多模态表达&#xff0c;标志着内容创造走向升维。AIGC 3D生成技术的突飞猛进&#xff0c;彻底打破了传统3D内容生产门槛高、周期长、成本高昂的问题。将3D数字人的打造…

数学建模研赛总结

目录 前言进度问题四分析问题五分析数模论文经验分享总结 前言 本文为博主数学建模比赛第五天的内容记录&#xff0c;希望所写的一些内容能够对大家有所帮助&#xff0c;不足之处欢迎大家批评指正&#x1f91d;&#x1f91d;&#x1f91d; 进度 今天已经是最后一天了&#xf…

nginx常用的性能优化

第一步调整工作进程数&#xff1a; 设置成auto&#xff0c;会自动按照CPU核心数来启动工作进程数&#xff0c;如果设置具体数字&#xff0c;则只会使用指定数量的CPU核心&#xff0c;无法将CPU同一时间都能用得到&#xff0c;所以就不能发挥服务器的最大的性能。 第二步增加进程…

el-table添加fixed后错位问题

1 方案1 return {isShow:false, }mounted() {this.isShowtrue},watch: {$route(newRoute) {this.monitoredRoute newRoute; // 将新的路由信息保存到组件的monitoredRoute属性中// 执行其他操作或调用其他方法},//或$route(newRoute) {this.monitoredRoute newRoute; // 将新…

Java项目实战II基于Java+Spring Boot+MySQL的免税商品优选购物商城(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者 一、前言 随着全球贸易的日益繁荣和消费者需求的多样化&#xff0c;免税商品购物已成为众多旅行者和消费者的热…

浸没式密封连接器

在当今科技快速发展的背景下&#xff0c;电子设备的整合度与性能需求持续提高&#xff0c;而连接技术作为电子设备间交互的关键&#xff0c;其重要性显而易见。在各式各样的连接技术当中&#xff0c;浸没式密封连接器凭借其独到设计和高超性能&#xff0c;在特定使用环境中显示…

SpringBoot3中ymal配置文件(持续更新)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;JavaWeb关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 在SpringBoot项目中,使用application.properties进行配置管理时&#xff0c;…