窗口类:
#pragma once
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QProcess>
#include <QTimer>
#include <QDebug>
#include <Windows.h>
#include <QWindow>
#include <QResizeEvent>
class ExternalAppWidget : public QWidget
{
Q_OBJECT
public:
ExternalAppWidget(QString exePath, QString strTitle, QWidget *parent = nullptr);
~ExternalAppWidget();
private:
bool checkAppStartDone(QString strAppTitle);
void killProcessByExeName(QString processName);
protected:
void resizeEvent(QResizeEvent *event);
private:
QVBoxLayout *m_pLayout;
QProcess *m_pProcess;
QWidget *m_pExternalWindow;
QString m_strExePath;
QString m_strExeTile;
};
#include "externalAppWidget.h"
#include <QFileInfo>
#include <QDir>
#include <QThread>
#include <QMessageBox>
#include <QTime>
// 不阻塞定时器
struct sTimeout
{
QTime time;
uint32_t interval;
void start(uint32_t t)
{
interval = t;
time.start();
};
bool isTimeOut()
{
return time.elapsed() > interval;
};
};
ExternalAppWidget::ExternalAppWidget(QString exePath, QString strTitle,QWidget *parent) :
QWidget(parent),
m_pExternalWindow(nullptr)
, m_strExePath(exePath)
, m_strExeTile(strTitle)
{
QFileInfo fileInfo(exePath);
killProcessByExeName(fileInfo.fileName());
m_pLayout = new QVBoxLayout(this);
// 启动外部程序
m_pProcess = new QProcess(this);
m_pProcess->setWorkingDirectory(fileInfo.absolutePath());
m_pProcess->start(exePath);
m_pProcess->waitForStarted();
checkAppStartDone(m_strExeTile);
// 获取外部程序的窗口句柄
HWND hwnd = FindWindowW(NULL, reinterpret_cast<LPCWSTR>(m_strExeTile.utf16()));
if (hwnd)
{
// 修改窗口样式以去掉标题栏
LONG style = GetWindowLong(hwnd, GWL_STYLE);
style &= ~(WS_CAPTION | WS_THICKFRAME); // 移除标题栏和边框
SetWindowLong(hwnd, GWL_STYLE, style | WS_POPUP); // 设置为无边框的弹出窗口
ShowWindow(hwnd, SW_SHOW);
WId wid = (WId)hwnd;
QWindow *pQwindow;
pQwindow = QWindow::fromWinId(wid);
// 创建窗口容器
m_pExternalWindow = QWidget::createWindowContainer(pQwindow, this);
m_pExternalWindow->setAttribute(Qt::WA_NativeWindow);
m_pExternalWindow->setMinimumSize(100, 100);
m_pLayout->addWidget(m_pExternalWindow);
m_pLayout->setMargin(0);
}
else
{
//QMessageBox::information(0, "Tip", QString("未找到窗口:%1").arg(m_strExeTile), QMessageBox::Yes);
qDebug() << "Failed to find external application window.";
}
setLayout(m_pLayout);
}
ExternalAppWidget::~ExternalAppWidget()
{
QFileInfo fileInfo(m_strExePath);
killProcessByExeName(fileInfo.fileName());
}
bool ExternalAppWidget::checkAppStartDone(QString strAppTitle)
{
// 循环检查窗口是否存在
QString windowTitle = strAppTitle;
HWND hwnd = nullptr;
int nStep = 0;
sTimeout timeout;
while (true)
{
Sleep(5);
switch (nStep)
{
case 0:
{
timeout.start(30*1000);
nStep = 1;
}break;
case 1:
{
hwnd = FindWindowW(NULL, reinterpret_cast<LPCWSTR>(windowTitle.utf16()));
if (hwnd != NULL)
{
return true; // 找到窗口,退出循环
}
else if (timeout.isTimeOut())
{
return false;
}
}break;
default:
break;
}
}
return false;
}
void ExternalAppWidget::killProcessByExeName( QString processName)
{
QStringList params;
params << "-f" << "-im" << processName;
QProcess process;
process.start("taskkill", params);
process.waitForFinished();
}
void ExternalAppWidget::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
if (m_pExternalWindow) {
m_pExternalWindow->resize(event->size());
}
}
应用层调用
void cWinDebug::initRemoteDesktopWidget()
{
for (int i = 1; i <= DEV_MAX_COUNT; i++)
{
QString strTitleName = GET_PARAM_STRING(P_EXE_TITLE_NAME(i));
QString strTabName = GET_PARAM_STRING(P_TAB_NAME(i));
QString strExePath = GET_PARAM_STRING(P_EXE_PATH(i));
if (strExePath.isEmpty() || strTitleName.isEmpty() || strTabName.isEmpty())
{
continue;
}
ExternalAppWidget* e = new ExternalAppWidget(strExePath, strTitleName, this);
e->showMaximized();
ui.tabWidgetRemote->insertTab(0, (QWidget*)e, strTabName);
}
ui.tabWidgetRemote->setCurrentIndex(0);
}