乱七八糟,没有整理。 记录了心路历程。
入口是main中调用了init,凑合看吧。只看#ifdef _WIN32分支。#elif linux 分支的代码是有问题的, ubuntu 20.04.3 下可以看另外一篇文章
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
#include
#include
#include // 包含这个头文件以处理宽字符输出
#ifdef _WIN32
// Windows 平台的代码
#include
#elif __linux__
// Linux 平台的代码
// ...
#include
#else
// 其他平台的代码或错误处理
// ...
#endif
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
, m_pProcess(nullptr)
, wid(0)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::init()
{
m_pProcess = new QProcess(this);
#ifdef _WIN32
// Windows 平台的代码
cmd = QString("D:/Qt/build-MyQtApp-Desktop_Qt_5_9_6_MinGW_32bit-Debug/debug/MyQtApp");
#elif __linux__
cmd = QString("/usr/bin/gnome-calculator");
cmd = QString("/home/lxk/Code/build-MyQtApp-Desktop_Qt_5_9_6_GCC_64bit-Debug/MyQtApp");
#endif
qDebug() << "insert map\n";
//-- 测试win10系统下调用外部qt程序,外部程序MyQtApp嵌套到本程序中。
func();
}
//-- 这个函数是测试 同一个程序内部的两个窗口嵌套的。
int MainWindow::func1()
{
QWidget *w = new QWidget;
//widget2->setStyleSheet("background-color: red;");
QPalette palette1 = w->palette();
palette1.setColor(QPalette::Background, Qt::red);
w->setPalette(palette1);
w->setMinimumSize(QSize(20,20));
//这两句不能把同时出现,如同时出现则两个窗口不能合在一起
//w->show();
//QThread::sleep(3);
// 获取QWidget的窗口标识符
WId wid2 = w->winId();
//这行代码是在Qt框架中使用的C++代码。Qt是一种用于开发GUI程序的跨平台C++库。
//在这行代码中,'QWindow* pWindow = QWindow::fromWinId(wid);'是在创建一个QWindow对象的指针,这个对象是通过调用QWindow类的静态方法fromWinId()得到的。
//这个方法需要一个参数,通常是一个窗口的标识符(wid),它返回一个指向这个窗口的QWindow对象的指针。如果找不到对应的窗口,那么这个方法会返回nullptr。
QWindow* pWindow = QWindow::fromWinId(wid2);
//--第一个参数 pWindow 它代表了你要嵌入的外部窗口;第二个参数 this新创建的子窗口将会嵌套在这个父窗口中。
QWidget* pWidget = QWidget::createWindowContainer(pWindow);
//pWidget->show();
//-- 为什么缺了这句,不能显示被嵌入的页面
w->show();
//-- zan shi zhu xiao
QWidget *container = new QWidget;
QPalette palette = container->palette();
//palette.setColor(QPalette::Background, Qt::blue);
container->setPalette(palette);
container->setMinimumSize(QSize(200,200));
QVBoxLayout* layout = new QVBoxLayout(container);
QLabel* label = new QLabel("Hello Kandy", container);
layout->addWidget(label);
layout->addSpacing(10);
layout->addWidget(pWidget, 1);
layout->addSpacing(10);
container->show();
}
int MainWindow::func()
{
if (wid == 0)
{
m_pProcess->setProcessChannelMode(QProcess::MergedChannels);
m_pProcess->start(cmd);
QThread::sleep(5);
#ifdef _WIN32
HWND hwnd = FindWindow(nullptr, L"pp"); // 获取窗口句柄
wchar_t className[256];
GetClassName(hwnd, className, 256); // 获取类名
std::wcout << L"Class Name: " << className << std::endl;
// Windows 平台的代码
wid = (WId)FindWindow(L"Qt5QWindowIcon", nullptr);
#elif __linux__
// Linux 平台的代码
//-- XOpenDisplay 允许你的程序与 X Window System 进行通信,从而实现图形界面交互。
Display* display = XOpenDisplay(NULL);
if (display == NULL) {
fprintf(stderr, "无法打开显示\n");
return 1;
}
//-- "根窗口"是一个特殊的窗口,它是所有其他窗口的祖先。所有的窗口,无论是顶级窗口还是子窗口,都是从根窗口派生出来的。
//-- 在大多数情况下,根窗口是整个屏幕或整个显示设备。
Window root = DefaultRootWindow(display);
Window root_return, parent_return;
Window* children;
unsigned int num_children;
if (XQueryTree(display, root, &root_return, &parent_return, &children, &num_children)) {
for (unsigned int i = 0; i < num_children; i++) {
char* name = NULL;
if (XFetchName(display, children[i], &name)) {
qDebug() << "name:" << name;
//if (name != NULL && strcmp(name, "gnome-calculator") == 0) {
if (name != NULL && strcmp(name, "MyQtApp") == 0) {
wid = children[i];
XFree(name);
break;
}
XFree(name);
}
}
XFree(children);
}
if (wid == 0) {
fprintf(stderr, "未找到指定窗口\n");
XCloseDisplay(display);
return 1;
}
else
{
//窗口的名字是"MyQtApp",那么会将这个窗口的ID赋值给wid,否则wid会是无效的。所以,如果窗口的名字是"MyQtApp",那么pWindow应该是有效的。
//但是,需要注意的是,你在代码中使用了XCloseDisplay(display);来关闭display。在调用XCloseDisplay后,所有与这个display相关的资源都应该被释放,所以如果你在这之后再使用wid,可能会引发问题。你应该在调用XCloseDisplay之前使用wid,或者确保wid在你调用XCloseDisplay后仍然有效。
//在使用 Xlib(X Window System 的 C 语言库)时,你需要通过 XOpenDisplay 函数来打开一个连接到 X Server 的会话。
//这个会话会在你的程序运行期间保持打开状态,直到你显式地关闭它。
//CloseDisplay(display) 就是用于关闭这个连接的函数调用。在你的代码中,display 是一个指向 Display 结构体的指针,它代表了与 X Server 的连接。
//关闭连接是一个良好的做法,因为它会释放与 X Server 的通信资源,并且可以确保你的程序在退出时不会留下未关闭的连接。
//所以,XCloseDisplay(display) 就是在关闭你的程序与 X Server 之间的通信连接。
XCloseDisplay(display);
// 现在你可以使用 'wid' 变量来操作该窗口
qDebug() << "Window ID:" << wid;
}
#else
// 其他平台的代码或错误处理
#endif
if (wid == 0) {
qDebug() << "can not find window\n";
return 1;
}
//这行代码是在Qt框架中使用的C++代码。Qt是一种用于开发GUI程序的跨平台C++库。
//在这行代码中,'QWindow* pWindow = QWindow::fromWinId(wid);'是在创建一个QWindow对象的指针,这个对象是通过调用QWindow类的静态方法fromWinId()得到的。
//这个方法需要一个参数,通常是一个窗口的标识符(wid),它返回一个指向这个窗口的QWindow对象的指针。如果找不到对应的窗口,那么这个方法会返回nullptr。
QWindow* pWindow = QWindow::fromWinId(wid);
qDebug() << "QWindow* pWindow :" << pWindow;
QWidget *container = new QWidget;
QVBoxLayout* layout = new QVBoxLayout(container);
container->setMinimumSize(QSize(600,500));
QLabel* label = new QLabel("Hello Kandy8888");
//pWindow->setFlags(Qt::FramelessWindowHint);
//--第一个参数 pWindow 它代表了你要嵌入的外部窗口;第二个参数 this新创建的子窗口将会嵌套在这个父窗口中。
/*
this不加,则不能正确嵌套。
在Qt中,如果你不将一个部件的父对象设置为其他部件,它就会成为一个顶级窗口。这意味着它将被视为一个独立的窗口,而不是其他窗口的子部件。
在Windows下,如果你试图将一个顶级窗口(而不是子部件)嵌套到另一个窗口中,通常会出现一些问题。这是因为一个独立的顶级窗口和一个子部件在窗口管理方面有很大的区别。
通过将一个部件的父对象设置为其他部件,你将建立一个父子关系,使得子部件成为父部件的一部分。这样,在父部件关闭时,所有子部件也会被自动关闭和释放。
因此,在你的情况下,如果你想将一个窗口嵌套到另一个窗口中,你应该将这个要嵌套的窗口作为子部件,并将父窗口作为它的父对象。这样,你就可以正确地将一个窗口嵌套到另一个窗口中。
*/
QWidget* pWidget = QWidget::createWindowContainer(pWindow, this);
qDebug() << "pWidget :" << pWidget;
layout->addWidget(pWidget);
//layout->addWidget(label);
//pWidget->show();
//pWindow->show();
container->show();
qDebug() << "地图zb嵌入";
}
else
{
qDebug() << "wid = " << wid;
}
return 0;
}