Embedding One Qt Application into another on Windows [SOLVED]
-
Hi there currently trying to create program than launches two instances of calculator and places it inside a QWidget.
@#include "mplayer.h"
#include "mplayer_wrapper.h"
#include <QState>
#include <QDebug>
#include <Windows.h>
#include <QWindow>mplayer::mplayer(QString rtsp_path, QWidget *parent) :
QWidget(parent)
{
QPalette p(palette());
p.setColor(QPalette::Background, Qt::black);
this->setAutoFillBackground(true);
this->setPalette(p);
this->setMinimumSize(720,576);qDebug("\nCreating Process = Mplayer"); WId winid = this->winId(); arguments << ""; qDebug() << arguments; this->m_process = new QProcess(); this->m_process->setProgram(program); this->m_process->setArguments(arguments); this->m_process->start(); if(this->m_process->waitForStarted()) { qDebug("\nSuccess in starting Process = Mplayer"); } else { qDebug("\nFailed To start Process = Mplayer"); }/**/ WId ide = (WId)FindWindowW(L"CalcFrame", NULL); if (ide) qDebug() << ide << "is the ID of mplayer"; //return -1; QWindow *container = QWindow::fromWinId(ide); QWidget *program_start = QWidget::createWindowContainer(container); //QMessageBox test; //test.setText(QString::number(id)); //test.exec(); //setCentralWidget(program_start); program_start->setParent(this); program_start->setMinimumSize(400,400); program_start->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(program_start); program_start->setLayout(layout);
}
mplayer::~mplayer()
{
qDebug("\nDeleting Process = Mplayer");
this->m_process->close();
}@
However if I create a window fromwinid, the program crashes, once I have again removed this and the container the programs will start but just obviously doesn't launch inside the QWidget. If anyone has any idea how I should do this or if there is a better/easier way of doing this please let me know. Currently using FindWindow does output the correct ID for the device (checked via winspector) just have no idea why it isn't creating the QWindow and why this isn't being placed inside the created window container QWidget.
@MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//mplayer_wrapper *cameras = new mplayer_wrapper("rtsp://169.254.133.191/output","rtsp://169.254.133.193/output",this);
QPalette p(palette());
p.setColor(QPalette::Background, Qt::lightGray);
this->setAutoFillBackground(true);
this->setPalette(p);
this->setWindowTitle(QApplication::translate("toplevel", "CCTV"));
//centralWidget()->layout()->addWidget(cameras);connect(ui->Start_Stream, &QPushButton::clicked,ui->widget,&mplayer_wrapper::start_mplayer); //connect(ui->Stop_Stream, &QPushButton::clicked,cameras,&mplayer_wrapper::stop_mplayer); //connect(ui->Start_Stream, &QPushButton::clicked,cameras,&mplayer_wrapper::start_mplayer); connect(Timer,&QTimer::timeout,this,&MainWindow::show_time); cmd_text = ui->cmd_edit->text(); Timer->start();
Timer = new QTimer(this);
connect(ui->Stop_Stream, &QPushButton::clicked,ui->widget,&mplayer_wrapper::stop_mplayer);
} @ -
Figured out the problem had a silly mistake (forgot to include request activate on the main Qwindow).
@#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);QVBoxLayout *mainLayout = new QVBoxLayout; QTimer t; t.start(2500); QProcess *m_process = new QProcess(this); QStringList arguments; arguments << ""; //m_process->setProgram("C:\\Windows\\SysWOW64\\calc.exe"); //m_process->setArguments(arguments); m_process->start("C:\\Windows\\SysWOW64\\calc.exe"); if(m_process->waitForStarted()) { qDebug("\nSuccess in starting Process = Mplayer"); } else { qDebug("\nFailed To start Process = Mplayer"); } WId id = (WId)FindWindow(NULL,L"Calculator"); if (id) qDebug() << id; QWindow* window = QWindow::fromWinId(id); window->show(); window->requestActivate(); QWidget* widget = QWidget::createWindowContainer(window); widget->show(); widget->setFixedWidth(1000); //setCentralWidget(widget);
}
MainWindow::~MainWindow()
{
delete ui;
}@Made a mini program that embeds the Calculator into the QWidget however it's has to contain requestactivate otherwise the program will crash.
However when testing this I have found an error that I cannot figure out how to resolve. If I launch the program without any calculator program already in the background the program will just start an instance of the calculator (which isn't inside the QWidget, then only if I run the program again will the system actually place the calculator program inside a QWindow, however this means that every time the program needs to be launch the internal program (in this case the calculator, has to be launched twice (once for external and then the second for internal of the QWindow). If anyone has an idea why this is happening or if i'm missing anything please let me know.
Here is the only error below that I am receivin.
ASSERT: "result.hwnd" in file qwindowswindow.cpp, line 555
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.Thanks
Nick -
Found the problem was related to QProcess not starting the process properly before it began searching for the HWID of the Process so once I had place waitforfinished before starting the program it would work (after quite a wait).
To resolve this I place a timeout on waitforfinished of 200 msecs so that the process had time to start but wasn't waiting for ages till wait for finished had cleared.
-
Hi,
waitForFinished doesn't mean that the application started by QProcess has in fact started, it's for when it should finish.
You should rather use waitForStarted