2018.7.18更新: 正好在参加杭州UnrealCircle的时候见到了EPIC上海的工程师李锋,以后我经过邮件询问了他这个问题,如下是他给个人回复:html
问题所在缘由是当你把虚幻引擎的窗口做为子窗口挂在Qt后,SWindow::GetPositionInScreen()中返回的坐标是错误的。 当你单独启动虚幻引擎的窗口,这里返回的是当前窗口左上角在屏幕中的位置。而当你把虚幻引擎挂在为Qt子窗口后,SWindow::GetPositionInScreen()中的ScreenPosition的值会因为WM_MOVE更新为0. 我看了你的代码中 SetParent后:api
MoveWindow(hwnWindow,rect.x(),rect.y(), rect.width(), rect.height(), true); ::SetWindowPos( hwnWindow, nullptr,rect.x(), rect.y(), rect.width(), rect.height(), SWP_NOZORDER | SWP_FRAMECHANGED| SWP_NOCOPYBITS );
可是这两句执行后,最后系统仍是会收到WM_MOVE消息进而把窗口的坐标设置为0. 说明Qt在后面某一时刻把你的窗口从新Move回(0,0). 这个须要你去Qt中查看了. (其实这里你的MoveWindow和SetWindowPos 在后面都被覆盖掉了,没有生效。缘由是当你单首创建两个Windows窗口,不适用Qt框架,你会看到子窗口相对于父窗口左上角的位置就是你MoveWindow中设置的 rect.x(),rect.y()的值,然而在你写的Qt代码运行后,子窗口>这里无论写什么值,最终都是贴着父窗口Client Area左上角的)框架
总结缘由是由于SetParent后,SWindow就没法接受到WM_MOVE消息了。突破思路有这么几条,但限于本人技术的问题暂时不会去尝试: 1.在Qt中手动发送WM_MOVE消息给Ue4窗口 2.在Qt中经过Socket之类的方法更新ScreenPosition的数值 3.修改UE4源代码,将SWindow::GetPositionInScreen()的获取方式进行修改。less
2018.6.16更新: 一、更新了一下代码,删除了一些错误的东西函数
Ue4项目设置中的Use Borderless Window 这个选项会让Ue4窗口变成没有外框与标题栏的状态,这样在嵌入Qt的时候就不要设置WindowStyle了,这样看起来效果会更好(设置WindowStyle会让窗口短暂显现出来,这样或许就不须要作静默启动了) 解除Ue4对鼠标的限制 Set Input Game And UI 来解除Ue4对鼠标限制 让Ue4从新得到焦点 BringWindowToTop (HWND);工具
一、由于启动的exe进程并不是游戏进程,因此经过QProcess的状态来判断Ue4是否启动是不对的,推荐使用WINAPI来获取对应线程。 二、能够在项目设置中修改窗口显示标题,能够把讨厌的(32-bit, PCD3D_SM5)去掉,强烈推荐使用窗口句柄查看工具,我是网上下了句柄精灵。(窗口标题后面都是有空格的) 三、使用嵌入方法回致使Ue4客户区(不太肯定这个叫什么)坐标异常(固定在左上角),会致使Umg按钮没法点击,最大化窗口后能够点击到一部分。使用原生的win32窗口项目嵌入也是会有这个问题的,若是有对winapi了解人麻烦告知我解决方案。ui
本人尝试了许多方法,都失败了: 一、在Ue4中使用AdjustWindowRectEx 二、SetWindowPos与MoveWindow 三、在Ue4中手动调用Ue4包装的MoveWindow函数 四、先移动Ue4窗口再嵌入Qt 五、向ue4发送Resize消息this
目前的补救方案就是,在Ue4中计算鼠标坐标,再使用虚拟点击来点击按钮。spa
由于本人对WINAPI不熟因此只找了一些资料.net
打开一个外部程序,通常是经过ShellExecute/Ex或CreateProcess或WinExec等API。 至于隐藏主窗口以及控制窗口上的控件,这个根据不一样的程序会有必定的复杂程度,首先是找到所谓的主窗口,而后再枚举窗口上的子窗口,经过一系列API模拟点击或读取/设置文本内容等。 参考:http://bbs.csdn.net/topics/240049935
https://www.cnblogs.com/zjutlitao/p/3889900.html
这里我直接上代码了,一看就懂。
#include "calculateandmove.h" #include "ui_calculateandmove.h" #include <QDebug> #include <QtConcurrent> #include <QThread> #include <QWindow> #include <QTimer> CalculateAndMove::CalculateAndMove(QWidget *parent) : QWidget(parent), ui(new Ui::CalculateAndMove),process(nullptr) { ui->setupUi(this); //setAttribute(Qt::WA_NativeWindow, true); } CalculateAndMove::~CalculateAndMove() { if(hwnWindow!=0) SendMessage(hwnWindow,WM_CLOSE,0,0); if(process){ if(process->state()==QProcess::Running){ process->terminate(); process->waitForFinished(30000); } delete process; } delete ui; } void CalculateAndMove::on_insetUe4_clicked() { startUe4(); } void CalculateAndMove::on_deleteUe4_clicked() { if(hwnWindow==0) return; SendMessage(hwnWindow,WM_CLOSE,0,0); } void CalculateAndMove::startUe4(){ //启动程序 QString unreal4Path{"D:/QtProject/QtWithUnreal4/WindowsNoEditor/DemoGame.exe"}; QStringList arguments; arguments << "-WINDOWED"; process=new QProcess; process->start(unreal4Path,arguments); QtConcurrent::run([this]{ while (true) { //经过窗口名称取得窗口句柄 //hwnWindow=FindWindow(NULL,L"DemoGame "); hwnWindow=FindWindow(NULL,L"DemoGame (32-bit, PCD3D_SM5) "); qDebug()<<hwnWindow; if(hwnWindow!=0) { connect(this,SIGNAL(insetUe4Complete()),this,SLOT(insetUe4())); emit insetUe4Complete(); break; } } }); } void CalculateAndMove::insetUe4(){ ////---------------------------------------------- ////方法一,进qt后须要调用解除客户区锁定函数(Ue4 // ue4Window=QWindow::fromWinId(WId(hwnWindow)); // ue4Window->setParent( this->windowHandle()); // ue4Window->setGeometry(0,0,ui->label->width(),ui->label->height()); // ue4Window->show(); //---------------------------------------------- //方法二,进qt后须要调用解除客户区锁定函数(Ue4 QRect rect=ui->label->geometry(); QPoint pos=ui->label->mapToGlobal(ui->label->pos()); qDebug()<<"rect:"<<rect; qDebug()<<"worldPos:"<<pos; QRect worldRect={rect.x()+pos.x(),rect.y()+pos.y(),rect.width()+pos.x(),rect.height()+pos.y()}; SetParent(hwnWindow,(HWND)QWidget::winId()); //MoveWindow(hwnWindow,rect.x(),rect.y(), rect.width(), rect.height(), true); ::SetWindowPos( hwnWindow, nullptr,rect.x(), rect.y(), rect.width(), rect.height(), SWP_NOZORDER | SWP_FRAMECHANGED| SWP_NOCOPYBITS ); //---------------------------------------------- LPRECT lprect; GetClientRect(hwnWindow,lprect); qDebug()<<(int)lprect->left<<(int)lprect->top<<(int)lprect->right<<(int)lprect->bottom; this->repaint(); } void CalculateAndMove::on_pushButton_clicked() { BringWindowToTop (hwnWindow); SetForegroundWindow(hwnWindow); }