最近的项目中有个需求是在界面中显示PPT幻灯片,之前项目中对PPT文件的处理是首先将.ppt或.pptx文件转化为.html文件,然后使用WebBrowser(Navigate2)控件打开进行显示。由于新项目需要有点击按钮切换页面功能,采用之前的方式不能够实现该需求,于是采用COM的方式打开PPT进行显示。在实现的过程中发现在执行m_SlideShowSettings.Run(); 显示幻灯片时,幻灯片时全屏显示的,再将全屏显示的幻灯片移入对话框中,这个过程会出现闪屏的现象,体验效果很不好,尝试了好多种方法,最后采用多线程的方式完美解决此问题。
1.操作环境:
①需要安装office软件,没有安装office的环境无法使用;
②VS2015+MFC
2.详细步骤:
①新建MFC对话框应用程序,取名为ShowPowerPoint,如图所示:
②在对话框中拖入以下控件,如图所示:
③生成OFFICE头文件:右击解决方案添加类MFCTypeLib中的MFC类添加注册表可用的类型库(Microsoft PowerPoint 12.0 Object Library<2.9>)如图所示:
点击上图中的箭头,生成的类中出现许多项:
点击完成,至此已经生成了相应的头文件。
还有一种方法是选择文件,在office安装目录下找到MSPPT.OLB,其它操作不用改,能达到一样的效果,如下图所示:
生成的头文件有很多,但是单纯的显示的话,只需要保留其中几个头文件就可以了。
需要将这些头文件中的一段注释掉,文件太多记得使用查找替换:
//#import “E:\Program Files (x86)\Microsoft Office\Office12\MSPPT.OLB” no_namespace
在InitInstance()函数中加入OLE初始化代码:
//OLE
if (!AfxOleInit())
{
AfxMessageBox(L"Failed to initialize OLE");
return false;
}
在ShowPowerPointDlg.h中加入头文件:
#include "CApplication.h"
#include "CPresentations.h"
#include "CPresentation.h"
#include "CSlides.h"
#include "CSlide.h"
#include "CSlideShowWindow.h"
#include "CSlideShowSettings.h"
#include "CSlideShowView.h"
添加对象:
CApplication m_Application;
CPresentations m_Presentations;
CPresentation m_Presentation;
CSlides m_Slides;
CSlide m_Slide;
CSlideShowWindow m_SlideShowWindow;
CSlideShowSettings m_SlideShowSettings;
CSlideShowView m_SlideShowView;
unsigned __stdcall ShowPPTFunc(LPVOID nlps);
unsigned __stdcall ShowPPTFunc(LPVOID nlps)
{
CShowPowerPointDlg* dlg = (CShowPowerPointDlg *)nlps;
while (true)
{
HWND hWnd = ::FindWindow(_T("ScreenClass"), 0);//幻灯片窗口
if (NULL != hWnd)
{
CWnd *pWnd = dlg->GetDlgItem(IDC_STATIC);//随便的显示控件
::SetParent(hWnd, pWnd->GetSafeHwnd());//设置父窗口
CRect rect;
pWnd->GetWindowRect(&rect);
CWnd *pWnd2 = CWnd::FromHandle(hWnd);
rect.SetRect(0, 0, rect.Width(), rect.Height());
pWnd2->MoveWindow(&rect);
pWnd2->Invalidate();
break;
}
}
return 0;
}
//打开
void CShowPowerPointDlg::OnBnClickedOpen()
{
// TODO: 在此添加控件通知处理程序代码
//查找PPT文件
CString strFilter = L"PowerPoint Files (*.ppt;*.pptx)|*.ppt;*.pptx|All Files(*.*)|*.*||";
CFileDialog FileDlg(TRUE, L"PPT", NULL, OFN_FILEMUSTEXIST | OFN_NONETWORKBUTTON | OFN_PATHMUSTEXIST, strFilter);
FileDlg.DoModal();
CString strFilePath;
strFilePath = FileDlg.GetPathName();
try
{
if (!m_Application.CreateDispatch(_T("Powerpoint.Application"), NULL))
{
AfxMessageBox(_T("创建PowerPoint应用程序失败!"));
return ;
}
if (!m_Application.m_lpDispatch)
{
AfxMessageBox(_T("PPT application was not initialized!"));
return ;
}
//开启线程监测幻灯片窗口_T("ScreenClass"),如果没有这一步操作,转到下面的注释代码,会出现全屏显示的幻灯片
//然后幻灯片移到会话框中,出现闪屏的现象,视觉效果比较差
HANDLE hThread;
unsigned int threadid;
hThread = (HANDLE)::_beginthreadex(NULL, 0, &ShowPPTFunc, (LPVOID)this, 0, &threadid);
CloseHandle(hThread);
m_Presentations.AttachDispatch(m_Application.get_Presentations());
m_Presentation.AttachDispatch(m_Presentations.Open(strFilePath, TRUE, -1, 0));
m_Slides = m_Presentation.get_Slides();
m_Slide = m_Slides.Item(COleVariant((long)1));
m_SlideShowSettings = m_Presentation.get_SlideShowSettings();
m_SlideShowSettings.put_LoopUntilStopped(TRUE); //设置循环放映
m_SlideShowSettings.Run(); //运行ppt
ShowPageNum();
//在对话框中显示
//HWND hWnd = ::FindWindow(_T("ScreenClass"), 0);//幻灯片窗口
//if (NULL != hWnd)
//{
// CWnd *pWnd = GetDlgItem(IDC_STATIC);//随便的显示控件
// ::SetParent(hWnd, pWnd->GetSafeHwnd());//设置父窗口
// CRect rect;
// pWnd->GetWindowRect(&rect);
// CWnd *pWnd2 = CWnd::FromHandle(hWnd);
// rect.SetRect(0, 0, rect.Width(), rect.Height());
// pWnd2->MoveWindow(&rect);
// pWnd2->Invalidate();
//}
}
catch (...)
{
m_Application.ReleaseDispatch();
return ;
}
}
//关闭
void CShowPowerPointDlg::OnBnClickedClose()
{
// TODO: 在此添加控件通知处理程序代码
try
{
m_Presentation.Close();
m_Presentation.ReleaseDispatch();
m_Presentations.ReleaseDispatch();
m_Slide.ReleaseDispatch();
m_SlideShowSettings.ReleaseDispatch();
m_SlideShowWindow.ReleaseDispatch();
m_SlideShowView.ReleaseDispatch();
m_Application.ReleaseDispatch();
m_Application.Quit();
}
catch (...)
{
}
CDialogEx::OnOK();
}
//首页
void CShowPowerPointDlg::OnBnClickedStart()
{
// TODO: 在此添加控件通知处理程序代码
m_Presentation = m_Application.get_ActivePresentation();
m_SlideShowWindow = m_Presentation.get_SlideShowWindow();
m_SlideShowView = m_SlideShowWindow.get_View();
m_SlideShowView.First();
m_SlideShowWindow.Activate();//刷新
ShowPageNum();
}
//尾页
void CShowPowerPointDlg::OnBnClickedEnd()
{
// TODO: 在此添加控件通知处理程序代码
m_Presentation = m_Application.get_ActivePresentation();
m_SlideShowWindow = m_Presentation.get_SlideShowWindow();
m_SlideShowView = m_SlideShowWindow.get_View();
m_SlideShowView.Last();
m_SlideShowWindow.Activate();//刷新
ShowPageNum();
}
//上一页
void CShowPowerPointDlg::OnBnClickedLast()
{
// TODO: 在此添加控件通知处理程序代码
m_Presentation = m_Application.get_ActivePresentation();
m_SlideShowWindow = m_Presentation.get_SlideShowWindow();
m_SlideShowView = m_SlideShowWindow.get_View();
m_SlideShowView.Previous();
m_SlideShowWindow.Activate();//刷新
ShowPageNum();
}
//下一页
void CShowPowerPointDlg::OnBnClickedNext()
{
// TODO: 在此添加控件通知处理程序代码
m_Presentation = m_Application.get_ActivePresentation();
m_SlideShowWindow = m_Presentation.get_SlideShowWindow();
m_SlideShowView = m_SlideShowWindow.get_View();
m_SlideShowView.Next();
m_SlideShowWindow.Activate();//刷新
ShowPageNum();
}
//显示页码
void CShowPowerPointDlg::ShowPageNum()
{
// TODO: 在此添加控件通知处理程序代码
m_Presentation = m_Application.get_ActivePresentation();
m_SlideShowWindow = m_Presentation.get_SlideShowWindow();
m_SlideShowView = m_SlideShowWindow.get_View();
m_Slide = m_SlideShowView.get_Slide();
CString strPages; strPages.Format(L"%d/%d", m_Slide.get_SlideIndex(), m_Slides.get_Count());
GetDlgItem(IDC_EDIT1)->SetWindowText(strPages);
}
至此在对话框中打开ppt的功能就完成啦!效果如图所示:
下载链接:
https://download.youkuaiyun.com/download/xhlzjd/11240220