Qt窗口内嵌Word,PPT,Excel

参考

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QDesktopServices>
#include <QUrl>
#include <windows.h>
#include <winuser.h>
#include <QTime>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    OpenWindow("e:\\111.xls");
    //    OpenWindow("e:\\123.doc");
}

MainWindow::~MainWindow()
{
    delete ui;
    CloseWindow();
}

void MainWindow::WaitForOpenWindow()
{
    if (!m_fileName.isEmpty()){
        QDesktopServices::openUrl(QUrl::fromLocalFile(m_fileName));
        // Sleep(1500);
//        QTime t;
//        t.start();
//        while(t.elapsed()<1500)
//            QCoreApplication::processEvents();
        int lastSeparatorIndex = m_fileName.lastIndexOf("/");
        if (lastSeparatorIndex == -1){
            lastSeparatorIndex = m_fileName.lastIndexOf("\\");
        }
        QString name = m_fileName.mid(lastSeparatorIndex + 1);
        //如打开的word名称是123.docx,则窗口标题名称为123.docx - Word ,,, 123.doc - WPS Office
        std::string strName = name.toStdString() + " - WPS Office";//我用的是WPS,如果是Office则需要修改
        //进行类型转换
        int dwLen = strlen(strName.c_str()) + 1;
        int nwLen = MultiByteToWideChar(CP_ACP, 0, strName.c_str(), dwLen, NULL, 0);//算出合适的长度
        LPWSTR lpszPath = new WCHAR[dwLen];
        MultiByteToWideChar(CP_ACP, 0, strName.c_str(), dwLen, lpszPath, nwLen);

        int dec = 0;
        while (m_fileShowHwnd == NULL){
            dec++;qDebug()<<"dec:"<<dec;
            //用类名和窗口标题名找到窗口句柄
            m_fileShowHwnd = FindWindow(L"XLMAIN", lpszPath);//word: OpusApp , excel:XLMAIN ,PPT:PPTFrameClass
            //不会立即找到句柄,有延时
            if (dec > 1000000){
                //    MessageBox(NULL, TEXT("No word!"), TEXT("Error"), MB_SYSTEMMODAL);
                break;
            }
        }
    }
}
//入参:要打开文件绝对路径
void MainWindow::OpenWindow(const QString & str)
{
    m_fileName = str;
    WaitForOpenWindow();
    //嵌入窗口,设置父窗口。减30是把为了把关闭按钮遮挡住。
    SetParent(m_fileShowHwnd, (HWND)ui->frame->winId());
    //移动窗口,把关闭按钮遮住
    //    MoveWindow(m_FileShowHwnd, 0, -30, ui->frame->width(), ui->frame->height() + 30, true);
    MoveWindow(m_fileShowHwnd, 0, 0, ui->frame->width(), ui->frame->height(), true);
    update();
}

#if 0
void MainWindow::CloseWindow()
{
    if (m_FileShowHwnd != nullptr){
        SendMessage(m_FileShowHwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
        int k = GetLastError();
        qDebug() << "SendMessage k  " << k << "\n";
        m_FileShowHwnd = NULL;
    }
}
#else
void MainWindow::CloseWindow()
{
     if (m_fileShowHwnd != nullptr)
     {
         DWORD dwPID;
         ::GetWindowThreadProcessId(m_fileShowHwnd, &dwPID);
         qDebug() << "GetWindowThreadProcessId dwPID = " << dwPID << "\n";
         HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
         if (hProcess)
         {
            qDebug() << "OpenProcess hProcess = " << hProcess << "\n";
            UINT unExitCode = 0;
            BOOL bRet = TerminateProcess(hProcess, unExitCode);
            if (!bRet)
            {
                DWORD dwErorCode = GetLastError();
                qDebug() << "TerminateProcess error = " << dwErorCode << "\n";
            }
         }
         m_fileShowHwnd = NULL;
     }
}
#endif

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    void WaitForOpenWindow();
    void OpenWindow(const QString & str);
    void CloseWindow();//关闭office窗口
private:
    Ui::MainWindow *ui;

    QString m_fileName;
    HWND m_fileShowHwnd = NULL;

};
#endif // MAINWINDOW_H

LIBS += -luser32

原理很简单,就是先按正常方式打开word,然后调用微软的FindWindow找到刚打开的这个word窗口,最后用SetParent方法设置此word窗口的父窗口为qt的窗口即可。

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值