qt嵌入程序需要使用到QWindow::fromWinId(mWid)和QWidget::createWindowContainer(Window,this, Qt::Widget );
qt阻塞启动三方程序ShellExecuteEx(&shExecinfo);和WaitForSingleObject(shExecinfo.hProcess, INFINITE);
代码示例:
.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QtWidgets>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::Widget *ui;
QWidget* mWidget;
int mWid = 0;
QVBoxLayout* mLay;
};
class UThread : public QObject
{
Q_OBJECT
public:
UThread(QWidget *parent = nullptr);
~UThread();
public slots:
void run();
signals:
void signalWid(int wid);
void signalCloseWid(bool flag);
};
#endif // WIDGET_H
.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include "windows.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
mLay = new QVBoxLayout;
mLay->addWidget(ui->pushButton_2);
mLay->addWidget(ui->pushButton);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_2_clicked()
{
QString cmd = QString("cmd /c taskkill /F /IM notepad++.exe /T");
WinExec(cmd.toUtf8().data(),SW_HIDE);
QList<QWidget *>wList = this->findChildren<QWidget *>("exewidget");
foreach (QWidget* w, wList) {
mLay->removeWidget(w);
delete w;
}
}
void Widget::on_pushButton_clicked()
{
if (mWid > 0)
return;
UThread *load = new UThread;
QThread* thread = new QThread();
load->moveToThread(thread);
connect(thread,SIGNAL(started()),load,SLOT(run()));
connect(load,&UThread::signalCloseWid,this,[=](bool ok){
qDebug()<<"-------------------"<<ok;
mWid = 0;
});
connect(load,&UThread::signalWid,this,[=](int wid){
mWid = wid;
if( 0 == mWid){
QMessageBox::information(0,"title","启动失败");
return;
}
QWindow *Window = QWindow::fromWinId(mWid);
Window->setFlags(Window->flags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
mWidget = QWidget::createWindowContainer(Window,this, Qt::Widget );
mWidget->setObjectName("exewidget");
qDebug() << __FUNCTION__ << __LINE__ << " ===--==> " << int(mWid);
mLay->addWidget(mWidget);
this->setLayout(mLay);
});
thread->start();
// QString runExec = "C:/ProgramData/Microsoft/Windows/Start Menu/Programs/Notepad++";
// std::wstring operate = L"open";
// std::wstring path = L"C:/ProgramData/Microsoft/Windows/Start Menu/Programs";
// std::wstring lpParameters = L"";
// ShellExecute(NULL,operate.c_str(),runExec.toStdWString().c_str(),lpParameters.c_str(),path.c_str(),SW_HIDE);
// WId wid = 0;
// for(int i = 0 ;i < 7;++i){
// wid = (WId)FindWindow(L"Notepad++",NULL);
// qDebug() << __FUNCTION__ << __LINE__ << wid;
// if(wid != 0){
// break;
// }
// ::Sleep(3000);
// }
}
UThread::UThread(QWidget *parent)
{
}
UThread::~UThread()
{
}
void UThread::run()
{
std::wstring operate = L"open";
std::wstring path = L"C:/ProgramData/Microsoft/Windows/Start Menu/Programs";
std::wstring lpParameters = L"";
SHELLEXECUTEINFO shExecinfo = {0};//创建执行文件对象
shExecinfo.cbSize = sizeof(SHELLEXECUTEINFO);//结构大小
shExecinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExecinfo.hwnd = NULL;//父窗口句柄
shExecinfo.lpVerb = operate.c_str();//权限
shExecinfo.lpFile = L"C:/ProgramData/Microsoft/Windows/Start Menu/Programs/Notepad++";//执行文件
shExecinfo.lpParameters = lpParameters.c_str();//参数
shExecinfo.lpDirectory = path.c_str();//路径
shExecinfo.nShow = SW_SHOWNORMAL;//显示方式
shExecinfo.hInstApp = NULL;
int ret = (int)ShellExecuteEx(&shExecinfo);
if (ret == 0)//执行失败
{}
else//执行成功
{}
WId wid = 0;
for(int i = 0 ;i < 7;++i){
wid = (WId)FindWindow(NULL,L"Notepad++");
qDebug() << __FUNCTION__ << __LINE__ << wid;
if(wid != 0){
break;
}
::Sleep(3000);
}
emit signalWid((int)wid);
try {
DWORD wret = WaitForSingleObject(shExecinfo.hProcess, INFINITE);//阻塞,直到ShellExecuteEx()执行的程序关闭
if (wret == WAIT_OBJECT_0)
{
qDebug()<<"正常关闭";
emit signalCloseWid(true);
}
else if (wret == WAIT_TIMEOUT)
{
qDebug()<<"超时";
}
else if (wret == WAIT_FAILED)
{
qDebug()<<"异常关闭";
emit signalCloseWid(false);
}
} catch (...) {
qDebug()<<"异常关闭1";
}
}