QT-窗口嵌入外部exe

窗口类:

#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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的大海贼

联系博主,为您提供有价值的资源

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值