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// ...}
}
相关文章:
Qt如何将外部窗口嵌入部件中
一、简述 今天给大家讲解的是使用QWindow类通过窗口句柄将外部的应用程序嵌入到我们的部件中来显示。在讲解之前可以延伸一下,当时项目中使用QProcess启动一些本地软件或者执行脚本时,需要将启动的第三方窗口嵌入到我们自己写的窗口中,此时我…...
2024年9月30日随笔
今天是国庆假期前的最后一天了,刚上完课,坐在实验室的工位前,感到焦虑又无奈,11月9号,网络规划工程师软考考试,学了一部分了,感觉有些难,还有一个月多一点点的时间,不知道…...
springboot+satoken实现刷新token(值变化)
欢迎来到我的博客,代码的世界里,每一行都是一个故事 🎏:你只管努力,剩下的交给时间 🏠 :小破站 springbootsatoken实现刷新token satoken是什么?支持什么?为什么需要&…...
63.HDMI显示器驱动设计与验证-彩条实验
(1)常见的视频传输接口有三种: VGA 接口、 DVI 接口和 HDMI 接口,目前的显示设备都配有这三种视频传输接口。三类视频接口的发展历程为 VGA→DVI→HDMI。其中 VGA 接口出现最早,只能传输模拟图像信号; 随后…...
安卓13设置删除网络和互联网选项 android13隐藏设置删除网络和互联网选项
总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改4.1修改方法14.2修改方法25.编译6.彩蛋1.前言 有些客户不想让用户修改默认的网络配置,禁止用户进入里面调整网络相关的配置。 2.问题分析 像这个问题,我们有好几种方法去处理,这种需求一般…...
C++的6种构造函数
在 C 中,构造函数是一种特殊的成员函数,用于初始化类对象。在对象创建时自动调用,构造函数的主要作用是分配资源、初始化数据成员等。根据不同的功能和使用场景,C 提供了多种类型的构造函数: 1. 默认构造函数 (Defaul…...
【FE】NPM——概述
NPM基本使用 下载Node 老生常谈,选择LTS版本官网放这里:https://nodejs.cn/download/ 1.镜像配置:镜像源 镜像配置 依赖仓库:版本查看 //不确定仓库有哪些版本,列出指定包的所有版本 npm view <package-name&…...
Clipboard.js实现复制文本到剪贴板功能
一、Clipboard.js简介 Clipboard.js是一个轻量级的实现复制文本到剪贴板功能的JavaScript插件,该插件可以将输入框,文本域,DOM节点元素中的文本内容复制到剪贴板中。 官网地址:Clipboard.js 浏览器兼容性:兼容Chrome、…...
Harbor安装笔记
下载离线安装包 wget https://github.com/goharbor/harbor/releases/download/v2.11.1/harbor-offline-installer-v2.11.1.tgz 解压 tar -zxvf harbor-offline-installer-v2.11.1.tgz 复制一份配置文件出来,修改配置 cp harbor.yml.tmpl harbor.yml vim harbor…...
HTTP 1.0 2.0 3.0详解
HTTP HTTP全称超文本传输协议,是一种属于应用层的通信协议。它允许将超文本标记语言文档(HTML)从Web服务器传输到客户端的浏览器。 HTTP报文结构 请求报文结构 请求方法: GET:一般用来请求已被URI识别的资源&#x…...
Python操作TXT文本:从入门到精通
在数字化时代,文本处理成为了许多工作和项目的基础。Python作为一种强大且易学的编程语言,在文本处理方面展现出了无与伦比的优势。本文将通过举例的方式,向读者介绍如何使用Python来操作TXT文本,让您轻松掌握文本处理的精髓。 一、读取TXT文本内容 首先,我们需要学会如…...
开源 AI 智能名片 2+1 链动模式 S2B2C 商城小程序的数据运营策略与价值创造
一、引言 1.1 研究背景 在当今数字化时代,数据运营已成为企业发展的核心驱动力。开源 AI 智能名片 21 链动模式 S2B2C 商城小程序作为一种创新的营销工具,与数据运营紧密相连。该小程序通过集成人工智能、大数据分析等先进技术,能够实时收集…...
ip 地址查看cmd命令
ip 地址查看cmd命令 在不同的操作系统中,查看IP地址的命令可能会有所不同。以下是一些常见操作系统中查看IP地址的命令: Windows: 打开命令提示符(CMD),然后输入 ipconfig 命令。 Linux/Unix: 打开终端࿰…...
力扣9.26
931. 下降路径最小和 给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即…...
HT8731 内置自适应H类升压和防破音功能的10W D类及AB类音频功率放大器
1、特点 防削顶失真功能(防破音,Anti-Clipping Function, ACF) 免滤波器数字调制,直接驱动扬声器 输出功率 10W(VBAT4.2V,RL3Ω,THDN10%, fiN 1kHz) 6W(VBAT3.3~4.2V,RL4Ω,THDN<1%,20-20kHz 全频段) 3W (VBAT3.3~4.2V,RL8Ω, THDN<1%, 20- 20kHz 全频段 VB…...
webpack使用
一、简介 概述 本次使用webpack4进行构建打包 二、webpack 安装webpack、webpack-cli npm install webpack4.2.0 webpack-cli4.2.0 -D 三、loader 加载器概述 raw-loader:加载文件原始内容(utf-8) file-loader:把文件输出…...
高通Android 12 音量API设置相关代码
// 获取当前音量大小public static int getCurrentVolume(Context context) {AudioManager audioManager (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);return audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); // 使用 STREAM_MUSIC 作为示例…...
Qt开发第一讲
一、Qt项目里面有什么? 对各个文件的解释: Empty.pro文件 QT core gui # 要引入的Qt模块,后面学习到一些内容的时候可能会修改这里 #这个文件相当于Linux里面的makefile文件。makefile其实是一个非常古老的技术了。 #qmake搭配.pr…...
详细指南:如何有效解决Windows系统中msvcp140.dll丢失的解决方法
如果你在使用Windows系统时遇到“msvcp140.dll丢失”的错误提示,通常是因为你的计算机上缺少或损坏了msvcp140.dll文件。msvcp140.dll是Microsoft Visual C Redistributable包的一部分,许多应用程序和游戏需要它来正常运行。以下是几种解决msvcp140.dll丢…...
【RabbitMQ】幂等性、顺序性
幂等性 概述 幂等性是数学和计算机科学中某些运算的性质,他们可以被多次应用,而不会改变初始应用的结果。RabbitMQ的幂等性则是指同一条消息,多次消费,对系统的影响是相同的。 一般消息中间件的消息传输保障分为三个层级&#…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
