摘要: 本文主要介紹了一種在MFC應(yīng)用程序中實現(xiàn)起來比較方便的瀏覽PDF、Word格式文檔文件的方法,同時給出了具體的編程步驟和較詳細(xì)的實現(xiàn)代碼。
概述隨著網(wǎng)絡(luò)技術(shù)的迅速發(fā)展,越來越多的電子圖書資料能夠更加方便的網(wǎng)上被檢索、下載。其文件格式不僅限于HTML格式的Web頁,PDF、Word等多種格式也逐漸成為網(wǎng)絡(luò)資料交換的主流文件格式。尤其在一些科研、技術(shù)類網(wǎng)站,有相當(dāng)數(shù)量的科技文獻(xiàn)都是以上述格式來發(fā)布的,而且從傳統(tǒng)習(xí)慣上大多數(shù)科研人員也更傾向于閱讀PDF或Word格式的文獻(xiàn)資料。
雖然使用Acrobat Reader和Word等專用軟件能夠比較方便的閱讀上述格式的資料文件,但如果需要在自己編寫的應(yīng)用程序中打開上述格式文檔仍免不了自己動手進(jìn)行處理。有多種途徑可以實現(xiàn)此目的:通過創(chuàng)建子進(jìn)程直接調(diào)用外部Acrobat Reader或Word應(yīng)用程序打開指定文檔;使用COM自動化技術(shù)在應(yīng)用程序中嵌入Acrobat Reader或Word而打開指定文檔;使用合適的ActiveX控件等等。其中,第一種方法是在應(yīng)用程序之外打開文檔,會使程序顯的不是很“專業(yè)”,第二種方法同樣會在打開文檔而使嵌入對象處于現(xiàn)場激活狀態(tài)時將Acrobat Reader或Word程序控制菜單嵌入到自己的程序當(dāng)中,而在許多情況下這并不是我們所希望的。本文將針對最后一種方式,即通過對“Microsoft Web瀏覽器”ActiveX控件的使用而在應(yīng)用程序中完成對PDF、Word格式文檔文件的打開、顯示。當(dāng)用戶用以該方法編寫的應(yīng)用程序在打開這些格式文檔文件時將不再感覺是在Acrobat Reader或Word程序中的瀏覽。
控件的創(chuàng)建 “Microsoft Web瀏覽器”控件隨Visual C++開發(fā)環(huán)境一起安裝到系統(tǒng)。從“Project”菜單下“Add To Project”彈出菜單的“Components and Controls…”子菜單彈出“Components and Controls Gallery”對話框,進(jìn)入“Registered ActiveX Controls”目錄并選中“Microsoft Web瀏覽器”控件,點擊“Insert”按鈕將其添加到VC++開發(fā)環(huán)境的控件工具欄中。
通常對ActiveX控件的使用多是在資源視圖中將指定的ActiveX控件拖拽到相應(yīng)的對話框中,并完成對其屬性的設(shè)置和對事件處理函數(shù)的添加。但由于本程序應(yīng)用“Microsoft Web瀏覽器”控件的目的是為了瀏覽PDF和Word等格式的文檔,因此應(yīng)用程序框架采取多文檔視圖結(jié)構(gòu)比較合適,在這種情況下顯然不能再以傳統(tǒng)方式創(chuàng)建控件而應(yīng)通過代碼來完成動態(tài)創(chuàng)建。
在將 “Microsoft Web瀏覽器”控件插入到工程后,派生于CWnd類的CWebBrowser2類被添加到工程,它提供了一個可供重載使用的虛函數(shù)Create()和一個類成員函數(shù)Create():
virtual BOOL Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName,DWORD dwStyle,const RECT& rect,CWnd* pParentWnd, UINT nID,CCreateContext* pContext = NULL); BOOL Create(LPCTSTR lpszWindowName,DWORD dwStyle,const RECT& rect, CWnd* pParentWnd, UINT nID, CFile* pPersist = NULL, BOOL bStorage = FALSE, BSTR bstrLicKey = NULL); |
通過該函數(shù)將可以象動態(tài)創(chuàng)建編輯框、按鈕等標(biāo)準(zhǔn)控件一樣動態(tài)創(chuàng)建。這里需要特別指出的是,一個“Microsoft Web瀏覽器”控件只能負(fù)責(zé)對一個文檔的維護(hù),也就是說,在多文檔結(jié)構(gòu)的本程序中需要為每一個打開的文檔分配一個“Microsoft Web瀏覽器”控件以進(jìn)行管理。這在具體實施上,只需在文檔或視圖類中聲明CWebBrowser2類對象即可。下面這段代碼在視圖類完成,在OnInitialUpdate()函數(shù)更新視圖時完成對控件的動態(tài)創(chuàng)建,創(chuàng)建的控件將占據(jù)視圖的全部客戶區(qū):
CWebBrowser2 m_Web; …… // 得到客戶區(qū) CRect rect; GetClientRect(&rect); // 創(chuàng)建控件窗體 m_Web.Create(NULL, WS_CHILD | WS_VISIBLE, rect, this, ID_WORD); |
文檔的打開顯示
本程序在文件打開顯示上采取的策略是:由程序框架負(fù)責(zé)獲取需要打開的文件路徑,并新建一文檔。在視圖更新“Microsoft Web瀏覽器”控件創(chuàng)建完畢后,由CWebBrowser2類成員函數(shù)Navigate ()負(fù)責(zé)對具體文檔的維護(hù)管理。這部分工作的具體處理代碼如下:
// 主框架類: // 顯示打開文件對話框 CFileDialog fileDlg(TRUE, "*.doc", "*.doc", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Word文件(*.doc)|*.doc|PDF文件(*.pdf)|*.pdf|Web頁(*.htm)|*.htm|所有文件(*.*)|*.*||", NULL); if (fileDlg.DoModal() == IDOK) { // 得到文件路徑 m_sPath = fileDlg.GetPathName(); // 新建文檔 PostMessage(WM_COMMAND, ID_FILE_NEW, 0); } …… // 視圖類: // 得到并保存要打開的文件路徑 m_sFilePath = ((CMainFrame*)AfxGetApp()->GetMainWnd())->m_sPath; ((CMainFrame*)AfxGetApp()->GetMainWnd())->m_sPath = "about:blank"; // 打開指定的文件 m_Web.Navigate(m_sFilePath, NULL, NULL, NULL, NULL); // 窗體設(shè)置為大小可變 m_Web.SetResizable(TRUE); |
為了在刷新視圖或窗口尺寸變更時能夠即使刷新顯示,還需要在OnDraw()函數(shù)和WM_SIZE消息響應(yīng)函數(shù)OnSize()中添加額外的處理代碼:
// 重繪窗口 (OnDraw()函數(shù)) if (m_Web.m_hWnd != NULL) m_Web.RedrawWindow(); …… void CShowWordView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); if (m_Web.m_hWnd != NULL) { // 得到新的客戶區(qū) CRect rect; GetClientRect(&rect); // 設(shè)置新的窗口位置 m_Web.SetWindowPos(&wndTop, rect.left, rect.top, rect.Width(), rect.Height(), NULL); // 重繪窗體 m_Web.RedrawWindow(); } } |
其中,SetWindowPos()函數(shù)將重新設(shè)置“Microsoft Web瀏覽器”控件窗口的放置位置以使其能夠占據(jù)尺寸更改后的文檔窗口的全部客戶區(qū)大小。
小結(jié) 上圖展示了程序?qū)嶋H運行效果,不僅能夠同時瀏覽Word格式文檔和PDF文檔,還能夠同時打開、并列顯示多個PDF文檔(在Acrobat Reader中雖然能夠同時打開多個文檔但不能并列顯示)。此外,本文雖然論述的是PDF和Word格式文檔文件的打開,但由于實際是通過CWebBrowser2類來完成具體的文檔打開和顯示處理的,因此支持的文檔格式并不局限于PDF和Word格式,只要符合IE接口規(guī)范的任意一種文件格式如HTML、JPEG等,使用本文所述方法同樣能夠?qū)⑵浯蜷_、顯示。本文所述程序在Windows 2000 Professional下由Microsoft Visual C++ 6.0編譯運行通過。需要有Microsoft Word 2000和Acrobat Reader 5.0以上版本軟件的支持。