窗口类:
#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_OBJECTpublic: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);
}