qt把unity发入widget中
头文件showunitywindowsinqt
#ifndef SHOWUNITYWINDOWSINQT_H
#define SHOWUNITYWINDOWSINQT_H
#include
#include
#include
#include
#include
class ShowUnityWindowsInQt : public QObject
{
Q_OBJECT
public:
explicit ShowUnityWindowsInQt(QObject* parent = nullptr);
~ShowUnityWindowsInQt();
void startUnityProgram(const QString& unityExePath);
void setWindowParent(HWND parentWidgetHandle, const QString& sonWindowTitleName);
signals:
void unityProgramStarted();//定义信号不需要在cpp文件中实现。信号本身是一种声明,它告诉编译器该对象将会发出该信号,其他对象可以连接到这个信号以接收通知。
private:
QProcess* process;
};
#endif // SHOWUNITYWINDOWSINQT_H
cpp文件 showunitywindowsinqt.cpp
#include "showunitywindowsinqt.h"
#include
#include
ShowUnityWindowsInQt::ShowUnityWindowsInQt(QObject* parent)
: QObject{parent}
{
//Qprocess 执行行外部进程,它提供了一种在应用程序内部启动和管理外部程序的方式
process = new QProcess(this);
connect(process, &QProcess::started, this, &ShowUnityWindowsInQt::unityProgramStarted);// 当执行新进程时将会发射信号
//QProcess::started 信号是在 QProcess 对象开始执行新进程时发出的
}
ShowUnityWindowsInQt::~ShowUnityWindowsInQt()
{
process->kill();//强制终止当前正在运行的进程
}
void ShowUnityWindowsInQt::startUnityProgram(const QString& unityExePath)
{
process->setProgram(unityExePath);//将 unityExePath 设置为要执行的程序路径
process->start(QIODevice::Truncate);//启动进程
qDebug() << "PID: " << process->processId();//打印出当前进程的进程 ID(PID)。
}
void ShowUnityWindowsInQt::setWindowParent(HWND parentWidgetHandle, const QString& sonWindowTitleName)//父窗口句柄,unity的名称
{
qDebug()<<"第一个参数"<<parentWidgetHandle<<"第二个参数"<<sonWindowTitleName;
std::wstring titleName = sonWindowTitleName.toStdWString();
HWND hfigure = nullptr;//nullptr表示一个空地址或者空指针对象
while (true)//找到unity窗口的句柄
{
//通过 FindWindowW(nullptr, titleName.c_str()) 搜索具有指定窗口名的子窗口,并将返回的子窗口句柄赋值给 hfigure。
//将 nullptr 传递给函数的第一个参数,表示查找顶级窗口(即不指定窗口类名),将 titleName.c_str() 传递给函数的第二个参数,表示查找具有指定窗口名的窗口,
hfigure = FindWindowW(nullptr, titleName.c_str());//titleName是所指定的窗口名
qDebug()<<"搜找到的hfigure是"<<hfigure;
if (hfigure != nullptr)
{
qDebug() <<"find sucess";
break;
}
QThread::msleep(100);//延时100毫秒
}
qDebug() << "话柄是"<<hfigure;
RECT rect;
qDebug() << "2222";
GetWindowRect(parentWidgetHandle, &rect);//获取父窗口的矩形区域
QThread::msleep(500);//延时500毫秒
SetParent(hfigure, parentWidgetHandle);//将子窗口设置为父窗口的子控件
qDebug() << "3333";
LONG_PTR dwStyle = GetWindowLongPtr(hfigure, GWL_STYLE);//子窗口样式
dwStyle = dwStyle & ~(WS_THICKFRAME | WS_CAPTION | WS_SIZEBOX | WS_MAXIMIZEBOX | WS_MINIMIZEBOX);//移除子窗口的移动和调整大小的样式
dwStyle |= WS_CHILD | WS_CLIPCHILDREN;//添加固定位置的样式。WS_CHILD 表示这是一个子窗口,WS_CLIPCHILDREN 表示绘制子窗口时,只绘制子窗口区域内的内容。(注释此行可实现,滑动鼠标滚轮进行放大缩小)
SetWindowLongPtr(hfigure, GWL_STYLE, dwStyle);//更新子窗口的样式
MoveWindow(hfigure, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, true);//将子窗口移动到父窗口的位置,并调整大小以适应父窗口
SetWindowPos(hfigure, HWND_TOP, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW |SWP_HIDEWINDOW);//设置窗口的位置和大小,并可以控制窗口的显示和隐藏
//(hfigure, HWND_TOP, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW |SWP_HIDEWINDOW);0,0,代表与父窗口的左上角位置相同
ShowWindow(hfigure, SW_SHOW);//显示子窗口
SetFocus(hfigure);//焦点设置到子窗口。使用户直接在该子窗口中输入字符和操作控件,而不必手动点击选中该子窗口。
}
调用上述文件,实现在一个widget中显示unity(widget:ui->tab )
要实现处的头文件(mainwindow.h)
//头文件
#include "showunitywindowsinqt.h"
#include
//定义 unit与tcp协议
ShowUnityWindowsInQt* util;
QTcpSocket *tcpSocket;
private slots:
void onConnected();//连接
void onDisconnected();//连接断开
void onReadyRead();//接受unity数据
void msg();//向unity发送数据
要实现处的cpp文件(mainwindow.cpp)
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QPushButton"
#include
#include
#include
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//unity的exe显示
util = new ShowUnityWindowsInQt(this);
// QString titleName("6");
QString titleName("baban2");//unity的.exe名称
connect(util, &ShowUnityWindowsInQt::unityProgramStarted, this, [&]()
{
util->setWindowParent((HWND)ui->tab->winId(),titleName);//ui->tab指的是ui设计界面中的一个widget
});//当信号被发射时,执行对应的槽函数
QString unityExePath("./Baban2/baban2.exe");//unity的路径
// QString unityExePath("./unity1/6.exe");
util->startUnityProgram(unityExePath);//startUnityProgram启动进程,proess有新进程,unityProgramStarted信号发射,setWindowParent函数触发将unity窗口放入widget窗口中
//tcp
tcpSocket = new QTcpSocket(this);
connect(tcpSocket, &QTcpSocket::connected, this, &MainWindow::onConnected);//tcp连接时触发onConnected函数
connect(tcpSocket, &QTcpSocket::disconnected, this, &MainWindow::onDisconnected);
connect(tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::onReadyRead);
// tcpSocket->connectToHost("127.0.0.1", 12345);//tcp连接的 ip地址 和 端口号
tcpSocket->connectToHost("127.0.0.1", 9998);
//发送按钮
QPushButton *sendbtn=new QPushButton (this);
sendbtn->setText("发送");
sendbtn->setGeometry(0,0,100,100);
connect(sendbtn,SIGNAL(clicked()),this,SLOT(msg()));
//发送json
QJsonObject jsonObject;
QJsonArray jsonArray;
jsonObject.insert("Key","K文件");
jsonObject.insert("Value",jsonArray);
QJsonDocument jsonDoc(jsonObject);//将QJsonObject转换为JSON格式的字符串。
QString jsonData = jsonDoc.toJson(QJsonDocument::Compact);
tcpSocket->write(jsonData.toUtf8());
}
void MainWindow::msg()//发送消息
{
//发送字符串
QString name="驾驶员";
tcpSocket->write(name.toUtf8());
qDebug()<<name.toUtf8();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onConnected()
{
// 连接建立时的处理
qDebug()<<"连接以建立";
}
void MainWindow::onDisconnected()
{
// 连接断开时的处理
qDebug()<<"连接断开";
}
void MainWindow::onReadyRead()
{
// 接收到数据时的处理
QByteArray receivedData = tcpSocket->readAll();
QString receivedString = QString::fromUtf8(receivedData);//转换成正确的string格式
qDebug()<<"接受的数据是 "+receivedString;
}