基於IE核心的多媒體檔案視覺化程式實現(一)
目的
前回書說道,在訊號處理或演算法研究中,資料的視覺化可以直觀地展現和判別結果的合理性。如果只允許用C語言做開發,或要將C語言所做演算法的輸出資料進行展示,又不許用MATLAB、Python所帶的視覺化工具,那麼,最快捷而直接的辦法就是將資料以文字方式輸出,再用Gnuplot工具來作圖了。Gnuplot可以直接生成png或svg圖片,Gnuplot所得的動畫圖還可以用gif格式儲存。這樣,通過WEB伺服器,就可以呼叫生成結果在WEB上展示了。
一般,windows中的看圖軟體是不支援gif動畫顯示的,我們會找一些看圖小工具軟體來顯示gif動圖,或利用瀏覽器直接開啟本地gif檔案。但總覺不夠方便,也顯得不夠專業。特別地,在自己的軟體產品中,應該使用自己介面的圖形視覺化視窗,而不是帶有第三方標記的東西。基於這種需求,我們特別需要有自己的本地檔案瀏覽工具。在開發中可用,在產品中也可用。
基於微軟的IE核心可以實現強大的html解析功能,而網頁中所能展現的檔案格式。IE瀏覽器核心也都能解析。許多第三方的瀏覽器都採用或至少相容了IE核心。這裡,我們採用IE核心作為多媒體檔案的解析和瀏覽工具,嘗試以最少的自編程式碼(基於VC++ MFC自動生成的程式碼量不計在內),去完成一個簡潔而功能強大的本地檔案瀏覽工具,具能使用命令列呼叫,這樣C語言就能編寫直接可看視覺化結果的程式了。
功能和特徵
如上回書說的,我們這個多媒體圖片瀏覽工具應具有如下功能和特徵:
- 能顯示各種格式的點陣圖圖片 (是一個看圖軟體)
- 能顯示向量圖(svg,wmf,emf)
- 能顯示動畫(gif)或flash的swf
- 能看各種格式的視訊 (是一個視訊播放器)
- 能播放音訊檔案 (是一個音訊播放器)
- 能閱讀pdf格式文件 (是一個Acrobat Reader)
還要求:
- 這個軟體要是有原始碼的(自己編寫的)
- 無商業版權衝突的,可以帶上自己的LOGO。
- 在軟體體積上不能太大,最好在1M以內。
- 這個軟體是以命令列模式工作的。
- 而且編寫的程式碼量在100行以內。
實現思路
- 首先通過VC++ MFC框架實現IE瀏覽器核心的嵌入,使之能瀏覽指定網頁。這個有多種方法可實現,最簡單的是採用Chtmlview類,以MFC工程嚮導自動產生程式碼,不必多寫一行程式碼即可實現。
- 然後,將瀏覽物件改為本地圖片檔案或本地html檔案,使之能正確瀏覽顯示。這裡只需改一句程式碼。
- 通過命令列引數將要開啟瀏覽的檔案路徑引數傳遞進去,使IE核心的瀏覽物件指向該檔案。這裡需要解析輸入的命令列引數,這用幾十行程式碼可完成。
- IE瀏覽器核心可直接開啟常見圖片格式的檔案,如png,bmp,jpg,動圖gif,向量圖svg,微軟的 emf,wmf 格式等等,也能開啟pdf檔案(前提是IE瀏覽器裝有acrobat的pdf外掛。)
- 對於有些檔案,特別是多媒體檔案,如mp3,wav,avi,swf等,IE核心不能直接開啟,我們可以生成臨時的html程式碼,將所要顯示的多媒體檔案包裹起來,再呼叫這個臨時html檔案即可。
編碼
基於MFC面向物件的程式碼是層層包裹的,隱藏實現,用巨集作訊息對映,微軟MFC甚至連winmain函式都給隱藏了,優點即是缺點,這讓我想起喬治·奧威爾的名言:“戰爭即和平, 自由即奴役, 無知即力量”。我們在此就不求甚解好了。
第一個程式(嚮導生成,不改程式碼)
基於Chtmlview類的MFC應用程式:開啟VC++整合環境(以 VC++6 為例, VS2010也一樣),Ctrl+N 新建立一個工程,假設工程名為wsee,通過嚮導建立MFC應用程式。一切都選預設引數即可。
只是到了最後一步(step6 of 6),將CWseeView基於CHtmlView基類即可。
點選OK即生成工程程式碼。
立即編譯(F7)之,應能通過。執行之,將會看到這樣的結果:
這是一個基於MFC多文件結構的IE瀏覽器嵌入模板。由於是VC6,很早了,所以指向的微軟網頁已經找不到了。但程式執行的正確的。
第二個程式(修改網頁指向)
開啟wseeView.cpp
, 檢視其函式OnInitialUpdate()
, 如下:
void CWseeView::OnInitialUpdate()
{
CHtmlView::OnInitialUpdate();
// TODO: This code navigates to a popular spot on the web.
// change the code to go where you'd like.
Navigate2(_T("http://www.microsoft.com/visualc/"),NULL,NULL);
}
可見其中htpp指向。將其改為http://www.wtclab.net/
試試?
Navigate2(_T("http://www.wtclab.net/"),NULL,NULL);
編譯執行,得到:
可見,只要改變Navigate2
函式的訪問字串,即可顯示相應網頁內容。
假設在本地硬碟上有一個檔案, 其絕對路徑是d:\wsee\e1.gif
, 則將字串file://d:/wsee/e1.gif
放入Navigate2函式,則可看到e1.gif動圖。
可見這樣的設計思路是可行的。
第三個程式(精簡和自定義)
VC++預設的模板可能不符合我們的需要,因此在建立工程時要依據需求重新選擇。
- 單文件框架更合適。
- 不需要選單、工具欄、狀態列等,就一個簡單說視窗即可。
- 要用自己的圖示。
為此,刪除剛才新建的wsee工程及目錄,重新建立wsee工程。這回選MFC單文件模式,且不用工具欄和狀態列。選單不能去掉,要在程式碼中改。
將網址改成指向微軟主網站: 執行後即得:
我們去掉選單欄:
在CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
函式中,增加:
cs.hMenu = NULL;//即 選單控制代碼賦值為空
即可。
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.hMenu = NULL;//即 選單控制代碼賦值為空
return TRUE;
}
將Navigate2中的連結指向百度試試。得到
這樣就符合最簡視窗的要求了。
可以通過VC的資源管理器修改系統圖標(16*16
和32*32
兩種),然後重新編譯即得自己圖示的程式了,雕蟲小技而已。
釋出為Relaese版本(24K)
可在VC++的build選單中Set Active Configuration 來設定編譯為釋出版本而非除錯版本。
Debug 版本為113KB, 釋出版本僅24KB,其實,程式只是做了一個外殼,核心是windows系統是自帶的IE瀏覽器在背後工作呢。
第四個程式(命令列引數引入)
顯然, 只要通過命令列引數引入要訪問的檔名,即可完成基本的圖片檔案顯示。
但是,查MFC的Navigate2函式說明發現,該函式只接受絕對路徑的檔案訪問。因此,如光想要在命令列引數中只使用檔名或相對路徑,則需要在程式中將輸入字串轉為絕對路徑方可正確應用。
另外一個問題是,如果我們還想利用這個程式訪問網際網路上的網頁,又該如何做?顯然採用條件句判斷是本地檔案還是遠端網址,分別處理即可。
如何實現? 且看下回分解。