https://www.cnblogs.com/findumars/p/8001326.html
https://blog.youkuaiyun.com/weixin_43956958/article/details/124948569
https://blog.youkuaiyun.com/qq_38040674/article/details/83546357?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-83546357-blog-111567062.235%5Ev35%5Epc_relevant_increate_t0_download_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-83546357-blog-111567062.235%5Ev35%5Epc_relevant_increate_t0_download_v2&utm_relevant_index=2
一、主要思路
运行exe—>FindWindow获得窗口句柄—>QWindow::fromWinId获得QWindow—>createWindowContainer为QWindow对象创建容器即窗口—>设置窗口属性并显示
- FindWindow获得外部应用窗口句柄
①
HWND WINAPI FindWindow(
_In_opt_ LPCTSTR lpClassName,// pointer to class name
_In_opt_ LPCTSTR lpWindowName // pointer to window name
);
FindWindow的两个参数填入一个即可查找到窗口句柄。
②如何获取外部应用的类名或者窗口名:
使用VS中的Spy++工具(在VS菜单栏“工具”中可以找到)。运行外部应用程序,打开Spy++,可以看到所有窗口的信息。
右键菜单中的“属性”项,可以查看窗口属性,其中“常规”- 窗口标题 即为窗口名,“类”- 类名 即为所要的类名。
#include<Windows.h>
Sleep(5000);//在代码之前增加延时
WId wid = (WId)FindWindow(NULL, L"honestech TVR - Screen");
//如果函数成功,则返回值是具有指定类名和窗口名的窗口句柄。如果函数失败,则返回值为NULL。
- 获取QWindow。QWindow::fromWinId用来创建一个win32窗口的代理。
QWindow*m_window;
m_window= QWindow::fromWinId(wid);
- 获取代理QWidget。QWidget::createWindowContainer用来把窗口封装为一个QWidget控件。
m_widget = QWidget::createWindowContainer(m_window, this); //第二个参数是作为window的父类,也可以用layout
二、源码
step1:Qt打开外部exe。创建进程:CreateProcess是Windows下用于创建进程的API函数
step2:启动外部exe,找到该exe窗口的句柄。FindWindow()
step3:将打开的外部程序嵌入到Qt的UI界面中
补充:设置窗口属性
https://www.cnblogs.com/shuoguoleilei/p/12766432.html
https://blog.youkuaiyun.com/xuebing1995/article/details/96478891?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-96478891-blog-77772635.235%5Ev36%5Epc_relevant_default_base3&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-96478891-blog-77772635.235%5Ev36%5Epc_relevant_default_base3&utm_relevant_index=1
#include "stdafx.h"
#include "winId.h"
winId::winId(QWidget *parent)
: QWidget(parent),ui(new Ui::winIdClass)
{
ui->setupUi(this);
//创建进程
QString cmd = "C:/Windows/system32/calc.exe";
STARTUPINFO si = { sizeof(si) }; //一些必备参数设置
PROCESS_INFORMATION pi;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = true; //必备参数设置结束
bool bRet = CreateProcess(
NULL,
(LPWSTR)cmd.toStdWString().c_str(),
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL, &si, &pi);
Sleep(5000);
WId wid = (WId)FindWindow(L"CalcFrame", L"计算器");
//WId wid = (WId)FindWindow(L"Rgui Workspace",NULL);
QWindow *m_window = nullptr;
m_window = QWindow::fromWinId(wid);
m_window->setFlags(m_window->flags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint); //
QWidget* m_widget = nullptr;
m_widget = QWidget::createWindowContainer(m_window, this);
m_widget->setMinimumSize(400, 300); //必须设置大小,否则可能因为嵌入后窗口太小看不到效果
}
winId::~winId()
{
delete ui;
}
或者参考:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>
#include <QDir>
#include "windows.h"
#include "stdio.h"
#include <QDebug>
#include <QMainWindow>
#include <QWindow>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
//启动
QDir::setCurrent("C:\\windows\\system32");
QProcess *pro = new QProcess(this);
pro->start("notepad.exe");
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::integrate()
{
QString Name = "无标题 - 记事本";
QString Name2 = "MainWindow";
WId hwnd = (WId)FindWindow(L"Notepad",(LPCTSTR)Name.unicode());
WId m_hWnd = (WId)FindWindow(L"Qt5QWindowIcon",(LPCTSTR)Name2.unicode());
qDebug()<<hwnd;
qDebug()<<m_hWnd;
//嵌入
if (hwnd > 0)
{
QWindow *m_window;
m_window = QWindow::fromWinId(WId(hwnd));
QWidget *m_widget;
m_widget = QWidget::createWindowContainer(m_window,this);
setCentralWidget(m_widget);
}
}
void MainWindow::on_pushButton_clicked()
{
integrate();
}
另一种方法:
#include <windows.h>
#include <QProcess>
#include <QWindow>
QString cmd = "D:/XXX.exe";
myProcess = new QProcess(this);
myProcess->start(cmd);
Sleep(3000);
HWND hwnd = NULL;
while (1) {
hwnd = FindWindow(L"CalcFrame", L"计算器");
if(hwnd){
break;
}
}
::SetParent(hwnd,(HWND)winId());//参数一:子类句柄,参数二:父类句柄。(HWND)对象名->winId()
WId wid = (WId)hwnd;
m_window = QWindow::fromWinId(wid);
m_window->setGeometry(80,50,1000,700);
三、句柄
https://blog.youkuaiyun.com/zhangchuan7758/article/details/121967154
https://blog.youkuaiyun.com/weixin_43956958/article/details/124948569
Windows 环境中有很多对象,诸如窗口、画笔、位图、光标、设备环境、程序实例等,可以通过API函数以不同的形式对这些对象进行操作。为此,必须以某种方法对这些对象进行标识,并把它们以参数的形式传递给函数。Windows用一个32位的整数对各种对象进行标识,这就是“句柄”(Handle)。也就是说句柄是一个对象的标识符。
句柄----用来标识指定一个窗体的,一个窗体有一个唯一的标识,引用句柄就可以引用窗体”。
在windows编程中类型名前面加H的基本是句柄。 常用的句柄:
HBITMAP 保存位图信息的内存域的句柄
HBRUSH 画刷句柄
HCTR 子窗口控件句柄
HCURSOR 鼠标光标句柄
HDC 设备描述表句柄
HDLG 对话框句柄
HFONT 字体句柄
HICON 图标句柄
HINSTANCE 应用程序实例句柄
HMENU 菜单句柄
HMODULE 模块句柄
HPALETTE 颜色调色板句柄
HPEN 笔的句柄
HWND 窗口句柄