Qt-窗口嵌套exe

某些特殊场景,我们要在主程序中嵌套第三方程序。这样臃肿的设计好比,在乡村小楼里面建设一个商业广场,本人不是很喜欢。Qt的QProcess和QWindow可以为我们完成这样的任务,核心思路即

  1. QProcess启动第三方exe,获取进程ID
  2. winApi通过进程ID获取窗口句柄
  3. QWindow::fromWinId(WId id)创建window
  4. window代理的widget,即我们常见的QWidget

最好的是,第三方exe也是Qt开发的app。下面就是这样的情况

第三方exe

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // OtherWidget inherit from QWidget
    OtherWidget w;
    w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
    w.show();
    return a.exec();
}

如上,OtherWidget继承于QWidget ,如果继承QMainWindow,在嵌入后更改主窗口size时出现丢失。

嵌套

// 枚举窗口参数
typedef struct
{
    HWND hwndWindow; // 窗口句柄
    DWORD dwProcessID; // 进程ID
}EnumWindowsArg;

// 枚举窗口回调函数
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    EnumWindowsArg *pArg = (EnumWindowsArg *)lParam;
    DWORD dwProcessID = 0;
    // 通过窗口句柄取得进程ID
    ::GetWindowThreadProcessId(hwnd, &dwProcessID);
    if (dwProcessID == pArg->dwProcessID)
    {
        pArg->hwndWindow = hwnd;
        // 找到了
        return FALSE;
    }
    // 没找到
    return TRUE;
}
// 通过进程ID获取窗口句柄
HWND GetWindowHwndByPID(DWORD dwProcessID)
{
    HWND hwndRet = NULL;
    EnumWindowsArg ewa;
    ewa.dwProcessID = dwProcessID;
    ewa.hwndWindow = NULL;
    EnumWindows(EnumWindowsProc, (LPARAM)&ewa);
    if (ewa.hwndWindow)
    {
        hwndRet = ewa.hwndWindow;
    }
    return hwndRet;
}
    QString cusExePath = "D:/VSpro/mainpro/x64/Debug/mainpro.exe";
    QString otherPath = "D:/QtProject/build-ModelDemo-Desktop_Qt_5_10_0_MSVC2015_64bit-Debug/debug/ModelDemo.exe";

    QStringList exePathList;
    exePathList << cusExePath << otherPath;

    for(int i = 0; i < exePathList.length(); i++){
        QProcess *process = new QProcess;
        QString path = exePathList.at(i);
        
        // 启动 第三方 exe, exepath 含有空格时,再次填充path即可
        if(path.contains(" ")){
            process->start(path, QStringList() << path);
        }
        else{
            process->start(path);
        }

        m_listProcess << process;

        qint64 proID = process->processId();

        HWND wid = NULL;

        do{
            wid = GetWindowHwndByPID(proID);
            if(wid){
                break;
            }
        }while(1);

        // window
        QWindow *window;
        window = QWindow::fromWinId((WId)wid);

        // proxyWidget
        QWidget *widget;
        widget = QWidget::createWindowContainer(window,this);

        ui->tabWidget->addTab(widget,QString::number(ui->tabWidget->count()));
    }

如上,我们开启了2个Qt APP exe,对于exePath含有空格的进行处理,结合winApi实现窗口句柄的获取,剩下的就很好办了。

退出

开启的第三方程序与主程序的依附问题,进程杀死等。对此的方法也很多

void MainWindow::closeEvent(QCloseEvent *event)
{
    for(auto &one : m_listProcess){
        one->close();
    }
}

当然,如果时其他开发的App,嵌套中会出现问题,所以还是说,小楼里面开商场,搞笑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值