当前位置:网站首页>将ue4程序嵌入qt界面显示

将ue4程序嵌入qt界面显示

2022-07-06 06:43:00 Leslie X徐

windows窗口编程

需求:将ue4程序嵌入qt界面显示
思路:通过使用 windowsAPI 对ue4窗口进行设置跟随qt界面以及活动窗口时的位置层序设置
结果:
请添加图片描述

1.打开程序获取句柄 设置样式

函数:

  1. 获取窗口句柄:HWND FindWindow(L"class name",L"window title") 数据可通过“句柄精灵”软件获取
  2. 设置窗口样式SetWindowLong(HWND, GWL_STYLE, LONG dwNewLong)
  3. 获取窗口样式:GetWindowLong(HWND, GWL_STYLE)
  4. 窗口样式宏
void Unreal4::on_pushButton_clicked()
{
    
    QString unreal4Path{
    "D:/lesliex/QTpro/QWidgetUnreal4/Windows/UEMetaFactory.exe"};
    QStringList arguments;
    arguments << "-WINDOWED";
    _process=new QProcess;
    _process->start(unreal4Path,arguments);

    QtConcurrent::run([this]{
    
        while(true){
    
            _hwnWindow=FindWindow(L"UnrealWindow",L"UEMetaFactory ");
            SetWindowLong(_hwnWindow, GWL_STYLE, GetWindowLong(_hwnWindow, GWL_STYLE) & (~WS_OVERLAPPEDWINDOW));//使用&~去除某种样式
            if(_hwnWindow != NULL){
    
                qDebug()<<("get SeerSupports");
                emit sigUe4Complete();
                break;
            }
        }
    });
}

2.等待显示 移动位置

此处不使用 createWindowContainer,对ue4有鼠标键盘交互问题
函数:

  1. 移动窗口
BOOL MoveWindow(
  [in] HWND hWnd,
  [in] int  X,
  [in] int  Y,
  [in] int  nWidth,
  [in] int  nHeight,
  [in] BOOL bRepaint
);

等待到窗口出现才能获取句柄

connect(this,&Unreal4::sigUe4Complete,this,&Unreal4::slotUe4Complete);
void Unreal4::slotUe4Complete()
{
    
//createWindowContainer方式不好
    // _window=QWindow::fromWinId((WId)_hwnWindow);
    // _windowWidget = QWidget::createWindowContainer(_window);

    _windowWidget = ui->widget_2;
    MoveWindow(_hwnWindow,mapToGlobal(_windowWidget->pos()).x(),mapToGlobal(_windowWidget->pos()).y(),_windowWidget->width(),_windowWidget->height(),false);
}

3.定时器定时显示窗口到最上层

函数:

  1. 设置窗口位置
BOOL SetWindowPos(
  [in]           HWND hWnd,
  [in, optional] HWND hWndInsertAfter,
  [in]           int  X,
  [in]           int  Y,
  [in]           int  cx,
  [in]           int  cy,
  [in]           UINT uFlags
);

hWnd移动到hWndInsertAfter下层,并设置位置和大小,显示方式。

  1. 获取窗口
HWND GetWindow(
  [in] HWND hWnd,
  [in] UINT uCmd
);

要获取已知窗口上层的窗口句柄可用 GetWindow( (HWND)this->winId() ,GW_HWNDPREV )

当主要窗口和ue程序为活动窗口时,将hWndInsertAfter设置为HWND_TOPMOSTuFlags设置为SWP_NOACTIVATE 只显示不激活
当主要窗口不为活动窗口时,将hWndInsertAfter设置为 GetWindow( (HWND)this->winId() ,GW_HWNDPREV )uFlags设置为SWP_NOACTIVATE 只显示不激活

Unreal4::Unreal4(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Unreal4)
{
    
    ui->setupUi(this);

    _timer = new QTimer(this);
    _timer->start(10);
    connect(_timer,&QTimer::timeout,this,&Unreal4::timerShowUe4);

}

void Unreal4::timerShowUe4()
{
    
    if(_windowWidget){
    
        if(GetForegroundWindow()==_hwnWindow||this->isActiveWindow()){
    
            qDebug()<<"isActive";
            SetWindowPos(_hwnWindow, HWND_TOPMOST, mapToGlobal(_windowWidget->pos()).x(),mapToGlobal(_windowWidget->pos()).y(),\
                         _windowWidget->width(),_windowWidget->height(),SWP_NOACTIVATE);
        }
        else{
    
            qDebug()<<"NotActive";
            SetWindowPos(_hwnWindow, GetWindow((HWND)this->winId(),GW_HWNDPREV), mapToGlobal(_windowWidget->pos()).x(),mapToGlobal(_windowWidget->pos()).y(),\
                         _windowWidget->width(),_windowWidget->height(),SWP_NOACTIVATE);
        }
    }
}

4.重写QWidget事件

函数:

  1. 设置窗口显示ShowWindow(HWND, int nCmdShow)
    设置nCmdShow:显示不激活为SW_SHOWNOACTIVATE,隐藏为SW_HIDE
void Unreal4::showEvent(QShowEvent *event)
{
    
    if(_process) ShowWindow(_hwnWindow,SW_SHOWNOACTIVATE);
}


void Unreal4::resizeEvent(QResizeEvent *event)
{
    
    if(_windowWidget)
        MoveWindow(_hwnWindow,mapToGlobal(_windowWidget->pos()).x(),mapToGlobal(_windowWidget->pos()).y(),_windowWidget->width(),_windowWidget->height(),false);
}


void Unreal4::hideEvent(QHideEvent *event)
{
    
    if(_process) ShowWindow(_hwnWindow,SW_HIDE);
}

5.源码

pro文件中加入:
LIBS += -luser32

头文件:

#ifndef UNREAL4_H
#define UNREAL4_H

#include "mwidget.h"
#include <QProcess>
#include "windows.h"
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui {
     class Unreal4; }
QT_END_NAMESPACE

/// \brief The Unreal4 class
/// \details 将UE4界面嵌入QT界面

class Unreal4 : public QWidget
{
    
    Q_OBJECT

public:
    Unreal4(QWidget *parent = nullptr);
    ~Unreal4();

    void closeUe4();


private slots:
    void slotUe4Complete();
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();
    void on_pushButton_3_clicked();
    void on_pushButton_4_clicked();

signals:
    void sigUe4Complete();
private:
    Ui::Unreal4 *ui;
    QProcess *_process{
    Q_NULLPTR};
    HWND _hwnWindow{
    Q_NULLPTR};
    QWidget *_windowWidget{
    Q_NULLPTR};
    QWindow * _window{
    Q_NULLPTR};
    QTimer* _timer{
    Q_NULLPTR};

    // QWidget interface
protected:
    void timerShowUe4();
    void showEvent(QShowEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;
    void hideEvent(QHideEvent *event) override;
};
#endif // UNREAL4_H

源文件:

#include "Unreal4.h"
#include "ui_Unreal4.h"

#include <QWindow>
#include <QDebug>
#include <QPalette>

#include <QtConcurrent>
#include <QMouseEvent>
#include <QPainter>

Unreal4::Unreal4(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Unreal4)
{
    
    ui->setupUi(this);

    connect(this,&Unreal4::sigUe4Complete,this,&Unreal4::slotUe4Complete);
    _timer = new QTimer(this);
    _timer->start(10);
    connect(_timer,&QTimer::timeout,this,&Unreal4::timerShowUe4);

}


Unreal4::~Unreal4()
{
    
    closeUe4();
    delete ui;
}

void Unreal4::closeUe4()
{
    
    if(!_process) return;
    if(_process->state()==QProcess::Running){
    
       _process->kill();
       QString exe = "UEMetaFactory-Win64-Shipping.exe";
       _process->execute("taskkill",QStringList()<<"-im"<<exe<<"-f");
       _process->waitForFinished(5000);
       delete _process; _process = Q_NULLPTR;
       ui->verticalLayout->removeWidget(_windowWidget); delete _windowWidget;
    }
}

void Unreal4::slotUe4Complete()
{
    
    _windowWidget = ui->widget_2;
    MoveWindow(_hwnWindow,mapToGlobal(_windowWidget->pos()).x(),mapToGlobal(_windowWidget->pos()).y(),_windowWidget->width(),_windowWidget->height(),false);
}

void Unreal4::on_pushButton_clicked()
{
    
    QString unreal4Path{
    "D:/lesliex/QTpro/QWidgetUnreal4/Windows/UEMetaFactory.exe"};
    QStringList arguments;
    arguments << "-WINDOWED";
    _process=new QProcess;
    _process->start(unreal4Path,arguments);

    QtConcurrent::run([this]{
    
        while(true){
    
            _hwnWindow=FindWindow(L"UnrealWindow",L"UEMetaFactory ");
            SetWindowLong(_hwnWindow, GWL_STYLE, GetWindowLong(_hwnWindow, GWL_STYLE) & (~WS_OVERLAPPEDWINDOW));
            if(_hwnWindow != NULL){
    
                qDebug()<<("get SeerSupports");
                emit sigUe4Complete();
                break;
            }
        }
    });
}

//==================================show ue4===============================
void Unreal4::timerShowUe4()
{
    
    if(_windowWidget){
    
        if(GetForegroundWindow()==_hwnWindow||this->isActiveWindow()){
    
            qDebug()<<"isActive";
            SetWindowPos(_hwnWindow, HWND_TOPMOST, mapToGlobal(_windowWidget->pos()).x(),mapToGlobal(_windowWidget->pos()).y(),\
                         _windowWidget->width(),_windowWidget->height(),SWP_NOACTIVATE);
        }
        else{
    
            qDebug()<<"NotActive";
            SetWindowPos(_hwnWindow, GetWindow((HWND)this->winId(),GW_HWNDPREV), mapToGlobal(_windowWidget->pos()).x(),mapToGlobal(_windowWidget->pos()).y(),\
                         _windowWidget->width(),_windowWidget->height(),SWP_NOACTIVATE);
        }
    }
}

void Unreal4::showEvent(QShowEvent *event)
{
    
    if(_process) ShowWindow(_hwnWindow,SW_SHOWNOACTIVATE);
}


void Unreal4::resizeEvent(QResizeEvent *event)
{
    
    if(_windowWidget)
        MoveWindow(_hwnWindow,mapToGlobal(_windowWidget->pos()).x(),mapToGlobal(_windowWidget->pos()).y(),_windowWidget->width(),_windowWidget->height(),false);
}


void Unreal4::hideEvent(QHideEvent *event)
{
    
    if(_process) ShowWindow(_hwnWindow,SW_HIDE);
}

//=====================button==========================
void Unreal4::on_pushButton_3_clicked()
{
    
    _timer->start(10);
    if(_process) ShowWindow(_hwnWindow,SW_SHOWNOACTIVATE);
}

void Unreal4::on_pushButton_2_clicked()
{
    
    this->close();
}

void Unreal4::on_pushButton_4_clicked()
{
    
    _timer->stop();
    if(_process) ShowWindow(_hwnWindow,SW_HIDE);
}


原网站

版权声明
本文为[Leslie X徐]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_44342705/article/details/125539399