先上代码
#include "mainwindow.h"
#include
#include
using namespace std;
#ifdef _WIN32
// Windows 平台的代码
#include
#elif __linux__
// Linux 平台的代码
// ...
#include
#else
// 其他平台的代码或错误处理
// ...
#endif
QString cmd = QString("/home/lxk/Code/build-MyQtApp-Desktop_Qt_5_9_6_GCC_64bit-Debug/MyQtApp");
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
//w.init();
//w.show();
QString cmd = QString("/home/lxk/Code/build-MyQtApp-Desktop_Qt_5_9_6_GCC_64bit-Debug/MyQtApp");;
QProcess m_pProcess(&a);
//m_pProcess.setProcessChannelMode(QProcess::MergedChannels);
m_pProcess.start(cmd);
WId wid2 = 0;
//-- 只保证进程已经开始,但不保证进程的主窗口已经创建
if (m_pProcess.waitForStarted()) {
QThread::sleep(2);
// 获取外部窗口句柄
QStringList arguments;
{
arguments << "search";
arguments << "--name" << "oop";
QProcess xprop;
xprop.start("xdotool", arguments);
xprop.waitForFinished();
//if(xprop.waitForFinished())
{
QByteArray byteArray = xprop.readAllStandardOutput();
QString input = QString::fromUtf8(byteArray);
QStringList numbers = input.trimmed().split("\n");
QString tmp = numbers[0];
wid2 = numbers[0].toULong();
qDebug() << "WId2:" << wid2;
//xdotool windowunmap 52428805
arguments.clear();
arguments << "windowunmap";
arguments << tmp;
xprop.start("xdotool", arguments);
QWidget *container = new QWidget;
container->setMinimumSize(QSize(600,500));
QLabel* label = new QLabel("Hello Kand");
QWidget* pWidget2 = QWidget::createWindowContainer(QWindow::fromWinId(wid2));
//pWidget2->setWindowFlags(pWidget2->windowFlags() | Qt::WindowStaysOnTopHint);
// pWidget2->raise(); // 将窗口降低到最后面
QVBoxLayout* layout = new QVBoxLayout(container);
layout->addWidget(pWidget2);
//layout->addWidget(label);
container->setLayout(layout); // This is important, it sets the layout for the container widget
container->show();
}
}
}
return a.exec();
}
一般情况下,宿主程序嵌入子程序的思路是个window下的思路是一样的。
1.也是先启动程序
QString cmd = QString("/home/Code/build-MyQtApp-Desktop_Qt_5_9_6_GCC_64bit-Debug/MyQtApp");;
QProcess m_pProcess(&a);
//m_pProcess.setProcessChannelMode(QProcess::MergedChannels);
m_pProcess.start(cmd);
WId wid2 = 0;
2.找到窗口句柄
if (m_pProcess.waitForStarted()) {
QThread::sleep(2);
// 获取外部窗口句柄
QStringList arguments;
{
arguments << "search";
arguments << "--name" << "oop";
QProcess xprop;
xprop.start("xdotool", arguments);
xprop.waitForFinished();
//if(xprop.waitForFinished())
{
QByteArray byteArray = xprop.readAllStandardOutput();
QString input = QString::fromUtf8(byteArray);
QStringList numbers = input.trimmed().split("\n");
QString tmp = numbers[0];
wid2 = numbers[0].toULong();
qDebug() << "WId2:" << wid2;
xdotool search --name oop
这个oop是WindowTitle
3.设置窗口的状态(有的系统不需要设置窗口的状态,比如window10不设置窗口状态,也可以嵌入)很重要。
//xdotool windowunmap 52428805
arguments.clear();
arguments << "windowunmap";
arguments << tmp;
xprop.start("xdotool", arguments);
4.然后常规的嵌入就ok了
QWidget* pWidget2 = QWidget::createWindowContainer(QWindow::fromWinId(wid2));
//pWidget2->setWindowFlags(pWidget2->windowFlags() | Qt::WindowStaysOnTopHint);
// pWidget2->raise(); // 将窗口降低到最后面
QVBoxLayout* layout = new QVBoxLayout(container);
layout->addWidget(pWidget2);
//layout->addWidget(label);
container->setLayout(layout); // This is important, it sets the layout for the container widget
container->show();
相关命令如下:
WindowTitle不要重名;
xdotool search --name oop 查看WindowTitle为oop的窗口的id
xprop -id <window_id> WM_STATE 查看这个窗口的状态
比如:
(base) l@ubuntu:~/Desktop$ xprop -id 52428805 WM_STATE
WM_STATE(WM_STATE):
window state: Normal
icon window: 0x0
改变这个窗口的状态
xdotool windowunmap 52428805
上文需要在系统中安装一些工具。
下文可以不用看!
Ps: 一个进程可以管理程序的多个窗口,我的测试代码如下,不知为何我检测到两个MyQtApp,我没有深究,可能原本启动一个程序,个人猜测 ------然后在嵌入的时候又复制了一个吧,不清楚!反正不对!也许把窗口状态改变就可以了。 我没试。
#ifdef _WIN32
// Windows 平台的代码
wid = (WId)FindWindow(L"UnityWndClass", nullptr);
#elif __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应该是有效的。
//在使用 Xlib(X Window System 的 C 语言库)时,你需要通过 XOpenDisplay 函数来打开一个连接到 X Server 的会话。
//这个会话会在你的程序运行期间保持打开状态,直到你显式地关闭它。
//但是,需要注意的是,你在代码中使用了XCloseDisplay(display);来关闭display。在调用XCloseDisplay后,所有与这个display相关的资源都应该被释放。CloseDisplay(display) 就是用于关闭这个连接的函数调用。在你的代码中,display 是一个指向 Display 结构体的指针,它代表了与 X Server 的连接。关闭连接是一个良好的做法,因为它会释放与 X Server 的通信资源,并且可以确保你的程序在退出时不会留下未关闭的连接。
XCloseDisplay(display);
// 现在你可以使用 'wid' 变量来操作该窗口
qDebug() << "Window ID:" << wid;
}
#else
// 其他平台的代码或错误处理
// ...
#endif