前言
近期项目中,要将子进程界面嵌入到主进程中,双方都是自己开发的,之前有过研究,曾经写过一篇文章
将外部exe嵌入到界面中(Windows)——Qt_startf_useshowwindow-CSDN博客,如今发现不好用,界面是嵌入了,但是并没有按照要求的大小展示,通过了几种方法(布局、绝对位置)仍然行不通。
如何将一个进程(子进程)界面嵌入另一个进程界面
- 方式一:在主进程中启动子进程,获取子进程的窗口句柄。
- 方式二:如果子进程也是自己开发的,在启动子进程时,可以将主进程的容纳子进程界面的窗体句柄作为运行参数传入子进程,通过进程通讯的方式,进行控制。
QStringList argl = a.arguments();qDebug() << argl;if (argl.size() <2){ return 0;}WId wid = WId(argl.at(1).toInt());QWindow* window = QWindow::fromWinId(wid);SubProcessWidget w;w.setProperty("_q_embedded_native_parent_handle", QVariant(wid));//设置属性,这句是必须的w.winId();//必须调用一次,生成winIdw.windowHandle()->setParent(window);//设置父窗口
如何控制大小位置
通过Windows API重置大小
之前都是通过Qt的方式对界面大小进行控制,失败了,后面查资料,发现有通过Windows API的方法(SetWindowPos)设置子进程界面的大小和位置的,所以就试了试,结果差强人意:可放大和还原,但是拖动主进程界面边框无法缩放,原因不清。
qint64 pid = processStart();WId wid = getProcessWid(pid);if(wid!=0){m_wnd =(HWND)wid;SetParent(m_wnd,(HWND)ui->widget->winId());SetWindowPos(m_wnd, 0, 0, 0 ,ui->widget->width(), ui->widget->height(), SWP_NOZORDER);}
qint64 Widget::processStart()
{pro =new QProcess(this);pro->setProgram("programName");connect(pro,&QProcess::errorOccurred,this,&Widget::onErrorOccurred);connect(pro,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(onFinished(int,QProcess::ExitStatus)));connect(pro,&QProcess::started,this,&Widget::onStarted);connect(pro,&QProcess::stateChanged,this,&Widget::onStateChanged);pro->setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args){args->startupInfo->wShowWindow = SW_HIDE;args->startupInfo->dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;});pro->start();pro->waitForStarted();return pro->processId();}WId Widget::getProcessWid(qint64 pid)
{WId winId = NULL;while (true) {winId=(WId)FindWindowW(L"Qt5152dQWindowIcon",L"Form");if (winId != NULL){break;}}return winId;
}void Widget::resizeEvent(QResizeEvent *e)
{QWidget::resizeEvent(e);SetWindowPos(m_wnd, 0, 0, 0 ,ui->widget->width(), ui->widget->height(), SWP_NOZORDER);
}
子进程内部控制
由于子进程也是我开发的,所以可以通过TCP或者其他方式进行通讯,告诉子进程的大小和位置,在子进程中进行设置(setGeometry)。
结束语
纸上得来终觉浅,绝知此事要躬行。