#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "AppRunEmbeded.h"
#include <QDir>
#ifndef Q_WS_WIN
#include <QX11EmbedContainer>
QX11EmbedContainer* container;
#else
#include "qt_windows.h"
#endif
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_Process(NULL),
winEmbedded(0)
{
ui->setupUi(this);
#ifndef Q_WS_WIN
container = new QX11EmbedContainer(ui->widget);
container->show();
#endif
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
// original size of application window
// used to resize it after embedding
origSize = ui->widget->size();
// working directory
QString workDir = "D:\\prog\\";
// prepare environment variables and run the program
QDir::setCurrent(workDir);
m_Process = new QProcess;
m_Process->setWorkingDirectory(workDir);
QStringList env = QProcess::systemEnvironment();
int index = env.indexOf(QRegExp("^PATH=(.*)", Qt::CaseInsensitive));
QString old = env[index];
QString newPath = old + ";" +
workDir+";" +
"";
env[index] = newPath;
m_Process->setEnvironment(env);
qDebug(qPrintable("newPath : " + newPath));
qDebug("Before run");
QString eee = "prog.exe ";
m_Process->start(eee/*, arguments*/);
// embed process to a widget
if (m_Process) qDebug("Yes process");
if (ui->widget) qDebug("Yes widget");
EmbedResult::T er = embedProcess(m_Process, ui->widget, &winEmbedded);
QString output = QString("Result: %1 - WindId - %2").
arg(EmbedResult::toText(er)).
arg(qint64(winEmbedded));
qDebug(qPrintable(output));
Программа в программе
Моя задача создать средствами QT приложение которое запускало бы ехе у себя во вкладках.
Поясню имеется некоторое приложение , предположим prog.exe, мне нужно запустить это приложение и встроить его в табвиджет приложения на QT4.7.1, с запуском проблем нет, использую QProcces::start, но встроить в виджет не получается, прошу помочь.
Код:
Код:
#include "AppRunEmbeded.h"
#include <QProcess>
#include <QStringList>
#include <QDir>
#include <QtGui/QApplication>
#ifdef Q_WS_WIN
#include "qt_windows.h"
bool AttachToWin(HWND parentWnd, qint64 pid);
#endif
// milliseconds to wait for process starts if it is not runinng
const int WAIT_FOR_RUN = 250;
// number of tries to look for main window
const int MAX_TRIES = 5;
// number of seconds between main window searches
const int TRY_PAUSE = 50;
#ifdef Q_WS_WIN
//------- Windows Utilites -------------------------------------------------
// Iterate through all existing windows
HWND theHwnd;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
DWORD processId;
::GetWindowThreadProcessId(hwnd, &processId);
if( processId == (DWORD)lParam )
{
theHwnd = hwnd;
return FALSE;
}
return TRUE;
}
// Embed process to a widget
// parentWnd = window to embed in
// pid = pid of running process
// winId = pointer to a embedded window
// return true in case of success
bool AttachToWin(HWND parentWnd, qint64 pid, WId *winId)
{
theHwnd = 0;
EnumWindows(EnumWindowsProc, (LPARAM)pid);
if (theHwnd)
{
qDebug(qPrintable(QString("Window %1 is found").arg(qint64(theHwnd))));
if (winId)
{
*winId = theHwnd;
}
// Embed application to a widget
LONG style = GetWindowLong(theHwnd, GWL_STYLE);
style &= ~(WS_BORDER | WS_THICKFRAME);
SetWindowLong(theHwnd, GWL_STYLE, style);
SetParent(theHwnd, parentWnd);
// resize parent widget to a embedded one
RECT rct;
GetWindowRect(parentWnd, &rct);
MoveWindow(theHwnd, 0, 0, (rct.right - rct.left), (rct.bottom - rct.top), TRUE);
return true;
}
else
{
qDebug("Window of the launched application is not found!");
return false;
}
}
#endif
QString EmbedResult::toText(EmbedResult::T res)
{
switch (res) {
case EmbedResult::Ok: return "OK";
case EmbedResult::InvalidParam: return "Invalid argument";
case EmbedResult::ProcessNotRunning: return "Process is not found";
case EmbedResult::ProcessInfoFailed: return "Failed to get process information";
case EmbedResult::NoMainWindow: return "Failed to get main process windows (console process?)";
case EmbedResult::Unsupported: return "OS is not supported. Windows only function.";
default: return "????";
}
}
// a try to embed process
EmbedResult::T try_attach(QWidget *parent, qint64 pid, WId *winHandle)
{
if (! pid) return EmbedResult::InvalidParam;
bool attached = AttachToWin(parent->winId(), pid, winHandle);
if (!attached) return EmbedResult::NoMainWindow;
return EmbedResult::Ok;
}
// main procedure of process embedding
EmbedResult::T embedProcess(
QProcess *process,
QWidget *parent,
WId *winHandle)
{
if (! process || ! parent) return EmbedResult::InvalidParam;
#ifndef Q_WS_WIN
return EmbedResult::Unsupported;
#else
// if process is not running yet then wait it some time
Sleep(WAIT_FOR_RUN);
if (process->state() != QProcess::Running)
{
Sleep(WAIT_FOR_RUN);
if (process->state() != QProcess::Running)
{
return EmbedResult::ProcessNotRunning;
}
}
// find main process window
_PROCESS_INFORMATION *pInfo = process->pid();
if (pInfo)
{
for(int i = 0; i < MAX_TRIES; ++i)
{
qDebug(qPrintable(QString("Try #%1").arg(i+1)));
EmbedResult::T rc = try_attach(parent, pInfo->dwProcessId, winHandle);
if (rc != EmbedResult::NoMainWindow) return rc;
Sleep(TRY_PAUSE);
}
return EmbedResult::NoMainWindow;
}
else {
return EmbedResult::ProcessInfoFailed;
}
return EmbedResult::Ok;
#endif
}
#include <QProcess>
#include <QStringList>
#include <QDir>
#include <QtGui/QApplication>
#ifdef Q_WS_WIN
#include "qt_windows.h"
bool AttachToWin(HWND parentWnd, qint64 pid);
#endif
// milliseconds to wait for process starts if it is not runinng
const int WAIT_FOR_RUN = 250;
// number of tries to look for main window
const int MAX_TRIES = 5;
// number of seconds between main window searches
const int TRY_PAUSE = 50;
#ifdef Q_WS_WIN
//------- Windows Utilites -------------------------------------------------
// Iterate through all existing windows
HWND theHwnd;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
DWORD processId;
::GetWindowThreadProcessId(hwnd, &processId);
if( processId == (DWORD)lParam )
{
theHwnd = hwnd;
return FALSE;
}
return TRUE;
}
// Embed process to a widget
// parentWnd = window to embed in
// pid = pid of running process
// winId = pointer to a embedded window
// return true in case of success
bool AttachToWin(HWND parentWnd, qint64 pid, WId *winId)
{
theHwnd = 0;
EnumWindows(EnumWindowsProc, (LPARAM)pid);
if (theHwnd)
{
qDebug(qPrintable(QString("Window %1 is found").arg(qint64(theHwnd))));
if (winId)
{
*winId = theHwnd;
}
// Embed application to a widget
LONG style = GetWindowLong(theHwnd, GWL_STYLE);
style &= ~(WS_BORDER | WS_THICKFRAME);
SetWindowLong(theHwnd, GWL_STYLE, style);
SetParent(theHwnd, parentWnd);
// resize parent widget to a embedded one
RECT rct;
GetWindowRect(parentWnd, &rct);
MoveWindow(theHwnd, 0, 0, (rct.right - rct.left), (rct.bottom - rct.top), TRUE);
return true;
}
else
{
qDebug("Window of the launched application is not found!");
return false;
}
}
#endif
QString EmbedResult::toText(EmbedResult::T res)
{
switch (res) {
case EmbedResult::Ok: return "OK";
case EmbedResult::InvalidParam: return "Invalid argument";
case EmbedResult::ProcessNotRunning: return "Process is not found";
case EmbedResult::ProcessInfoFailed: return "Failed to get process information";
case EmbedResult::NoMainWindow: return "Failed to get main process windows (console process?)";
case EmbedResult::Unsupported: return "OS is not supported. Windows only function.";
default: return "????";
}
}
// a try to embed process
EmbedResult::T try_attach(QWidget *parent, qint64 pid, WId *winHandle)
{
if (! pid) return EmbedResult::InvalidParam;
bool attached = AttachToWin(parent->winId(), pid, winHandle);
if (!attached) return EmbedResult::NoMainWindow;
return EmbedResult::Ok;
}
// main procedure of process embedding
EmbedResult::T embedProcess(
QProcess *process,
QWidget *parent,
WId *winHandle)
{
if (! process || ! parent) return EmbedResult::InvalidParam;
#ifndef Q_WS_WIN
return EmbedResult::Unsupported;
#else
// if process is not running yet then wait it some time
Sleep(WAIT_FOR_RUN);
if (process->state() != QProcess::Running)
{
Sleep(WAIT_FOR_RUN);
if (process->state() != QProcess::Running)
{
return EmbedResult::ProcessNotRunning;
}
}
// find main process window
_PROCESS_INFORMATION *pInfo = process->pid();
if (pInfo)
{
for(int i = 0; i < MAX_TRIES; ++i)
{
qDebug(qPrintable(QString("Try #%1").arg(i+1)));
EmbedResult::T rc = try_attach(parent, pInfo->dwProcessId, winHandle);
if (rc != EmbedResult::NoMainWindow) return rc;
Sleep(TRY_PAUSE);
}
return EmbedResult::NoMainWindow;
}
else {
return EmbedResult::ProcessInfoFailed;
}
return EmbedResult::Ok;
#endif
}
QT на такие извращения не рассчитана
Тогда посоветуйте пожалуйста возможное решение этой задачи
Попробовал сейчас в WinForms C#: Блокнот нормально запускается и показывается во вкладке TabControl'а с использованием SetParent.