• QT中使用unity


    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    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);//焦点设置到子窗口。使用户直接在该子窗口中输入字符和操作控件,而不必手动点击选中该子窗口。
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    调用上述文件,实现在一个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发送数据
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    要实现处的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;    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
  • 相关阅读:
    LeetCode每日一题:面试题 01.09. 字符串轮转 (简单)串匹配
    自己动手写RTOS:02-在M3内核上实现pendsvc
    [附源码]计算机毕业设计汽车美容店管理系统Springboot程序
    Redis之缓存一致性
    两名高管遭解雇,Twitter:只出不进
    设计模式 原型模式来复制女朋友
    美国Westar光学测试设备改造升级(精通TestStand编程管理软件)
    Express项目
    docker引起服务器磁盘爆满
    Pyparsing模块使用介绍
  • 原文地址:https://blog.csdn.net/weixin_46657636/article/details/134499620