当前位置:网站首页>将ue4程序嵌入qt界面显示
将ue4程序嵌入qt界面显示
2022-07-06 06:43:00 【Leslie X徐】
windows窗口编程
需求:将ue4程序嵌入qt界面显示
思路:通过使用 windowsAPI 对ue4窗口进行设置跟随qt界面以及活动窗口时的位置层序设置
结果:
1.打开程序获取句柄 设置样式
函数:
- 获取窗口句柄:
HWND FindWindow(L"class name",L"window title")数据可通过“句柄精灵”软件获取 - 设置窗口样式:
SetWindowLong(HWND, GWL_STYLE, LONG dwNewLong) - 获取窗口样式:
GetWindowLong(HWND, GWL_STYLE) - 窗口样式宏
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有鼠标键盘交互问题
函数:
- 移动窗口:
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.定时器定时显示窗口到最上层
函数:
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下层,并设置位置和大小,显示方式。
HWND GetWindow(
[in] HWND hWnd,
[in] UINT uCmd
);
要获取已知窗口上层的窗口句柄可用 GetWindow( (HWND)this->winId() ,GW_HWNDPREV )
当主要窗口和ue程序为活动窗口时,将hWndInsertAfter设置为HWND_TOPMOST,uFlags设置为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事件
函数:
- 设置窗口显示:
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);
}
边栏推荐
- LeetCode - 152 乘积最大子数组
- CS passed (cdn+ certificate) PowerShell online detailed version
- Suspended else
- What is the difference between int (1) and int (10)? Senior developers can't tell!
- 机器人类专业不同层次院校课程差异性简述-ROS1/ROS2-
- 翻译生物医学说明书,英译中怎样效果佳
- [ 英语 ] 语法重塑 之 英语学习的核心框架 —— 英语兔学习笔记(1)
- How do programmers remember code and programming language?
- [ 英語 ] 語法重塑 之 動詞分類 —— 英語兔學習筆記(2)
- The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
猜你喜欢

Leetcode daily question (971. flip binary tree to match preorder traversal)

LeetCode每日一题(971. Flip Binary Tree To Match Preorder Traversal)

BUU的MISC(不定时更新)

利用快捷方式-LNK-上线CS

ECS accessKey key disclosure and utilization

A method to measure the similarity of time series: from Euclidean distance to DTW and its variants

女生学软件测试难不难 入门门槛低,学起来还是比较简单的

Changes in the number of words in English papers translated into Chinese

【软件测试进阶第1步】自动化测试基础知识

我的创作纪念日
随机推荐
翻译影视剧字幕,这些特点务必要了解
Phishing & filename inversion & Office remote template
Leetcode daily question (1870. minimum speed to arrive on time)
Pallet management in SAP SD delivery process
Introduction and underlying analysis of regular expressions
Latex文字加颜色的三种办法
Data security -- 13 -- data security lifecycle management
Fledgling Xiao Li's 103rd blog CC2530 resource introduction
The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
A 27-year-old without a diploma, wants to work hard on self-study programming, and has the opportunity to become a programmer?
Practical guidance for interface automation testing (Part I): what preparations should be made for interface automation
SQL Server manager studio(SSMS)安装教程
Apache dolphin scheduler source code analysis (super detailed)
电子书-CHM-上线CS
Wish Dragon Boat Festival is happy
Brief introduction to the curriculum differences of colleges and universities at different levels of machine human major -ros1/ros2-
Day 246/300 ssh连接提示“REMOTE HOST IDENTIFICATION HAS CHANGED! ”
Bitcoinwin (BCW): 借贷平台Celsius隐瞒亏损3.5万枚ETH 或资不抵债
LeetCode每日一题(971. Flip Binary Tree To Match Preorder Traversal)
Difference between backtracking and recursion