全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2278
推到 Plurk!
推到 Facebook!

直接訪問webbrowser控制項中的html源碼

 
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-09-26 15:51:08 IP:61.221.xxx.xxx 未訂閱
直接訪問webbrowser控制項中的html源碼 作者: 華中師範大學 盧小海 評價: 上站日期: 2001年06月28日 內容說明: 來源: http://data.sportschina.com/sf/program/delphi/00251.htm ---- 爲了實現在自己的程式中顯示html文檔,我們一般採用ie(internet explorer本文中簡稱爲ie)發行時附帶的一個activex控制項twebbrowser。這個控制項使用和ie相同的內核,功能強大,並從delphi5開始,正式得到inprise公司的支援,取代了原來的那個thtml控制項,成爲delphi中顯示html文檔的首選控制項。 ---- 但是在實際編程過程中,我發現這個控制項提供的功能有很多限制,比如對html文檔的瀏覽,只能通過指定url或檔案名來實現,不能像以往使用thtml控制項那樣直接讀寫html源碼。因此如果程式動態生成了一段html文本,就必須把文本內容先寫到一個暫存檔案,然後再將此文件的檔案名傳遞給webbrowser控制項,實現顯示。走這一個彎路使程式回應速度受到很大影響,而且容易遺留下一些"垃圾"(暫存檔案)。 ---- 在考察了一些使用了webbrowser控制項的程式後,我發現大部分程式,如著名國產軟體foxmail,都是使用的通過暫存檔案傳遞html文檔的方法;但一些國外的軟體,如ms自己的outlook express則不存在這個問題,而因爲其無需産生暫存檔案,因此對html文檔的顯示速度明顯超過foxmail。 ---- 爲此,我查閱了一些相關資料,最後在網友的幫助下找到了實現直接訪問webbrowser控制項中的html源碼的方法。在此要特別感謝白雲黃鶴bbs(bbs.whnet.edu.cn)上的網友anglefalls提供線索。 ---- 其實,webbrowser控制項中的document物件,這個物件提供了一個ipersiststreaminit介面,通過此介面,我們可以方便地實現對html源碼的讀寫。 ---- 以下是ipersiststreaminit介面的相關定義及說明: { ipersiststream interface } {$externalsym ipersiststream} ipersiststream = interface(ipersist) ['{00000109-0000-0000-c000-000000000046}'] function isdirty: hresult; stdcall; // 最後一次存檔後是否被修改 function load(const stm: istream): hresult; stdcall; // 從流中載入 function save(const stm: istream; fcleardirty: bool): hresult; stdcall; // 保存到流 function getsizemax(out cbsize: largeint): hresult; stdcall; // 取得保存所需空間大小 end; { ipersiststreaminit interface } {$externalsym ipersiststreaminit} ipersiststreaminit = interface(ipersiststream) ['{7fd52380-4e07-101b-ae2d-08002b2ec713}'] function initnew: hresult; stdcall; // 初始化 end; 首先來實現寫,因爲這是最迫切的要求: procedure sethtml(const webbrowser: twebbrowser; const html: string); var stream: istream; hhtmltext: hglobal; psi: ipersiststreaminit; begin if not assigned(webbrowser.document) then exit; hhtmltext := globalalloc(gptr, length(html) 1); if 0 = hhtmltext then raiselastwin32error; copymemory(pointer(hhtmltext), pchar(html), length(html)); olecheck(createstreamonhglobal (hhtmltext, true, stream)); try olecheck(webbrowser.document. queryinterface(ipersiststreaminit, psi)); try olecheck(psi.initnew); olecheck(psi.load(stream)); finally psi := nil; end; finally stream := nil; end; end; ---- 首先,此過程需要的兩個參數,webbrowser是顯示目的控制項,html是需要顯示的html源碼;然後,先檢查webbrowser.document物件是否有效,無效則退出;接著在系統全局堆裏分配一塊記憶體,將需要顯示的html源碼複製進去。這是因爲下一步需要建立一個webbrowser控制項可以讀取的流。globalalloc函數的參數gptr表示需要分配一塊固定的以0初始化過的記憶體區域,如果分配失敗則返回0,則通過raiselastwin32error函數引發一個異常,提示用戶;然後用createstreamonhglobal函數建立一個基於全局堆記憶體塊的流,第二個參數如果爲true則流在釋放時自動釋放所占全局堆記憶體。如果建立成功則此流和剛剛建立的記憶體塊共用同一塊記憶體區域。接著用webbrowser.document.queryinterface函數建立一個ipersiststreaminit介面。然後就可以直接使用此介面,psi.initnew初始化狀態;psi.load(stream)從流中載入html源碼。 ---- 至此,以html參數指定的html源碼就在webbrowser參數指定的控制項中顯示出來。 ---- 值得注意的是,每個關於com介面的函數調用,也就是那些返回類型爲hresult的函數,都必須以olecheck包裝,因爲一個不檢查返回狀態的com介面操作實在太危險了;此外介面的釋放,雖然delphi可以在後臺自動完成,但作爲一個好的編程習慣,還是應該顯式地手工釋放,釋放只需將介面設爲nil即可。 ---- 接著來實現html源碼的讀: function gethtml(const webbrowser: twebbrowser): string; const bufsize = $10000; var size: int64; stream: istream; hhtmltext: hglobal; psi: ipersiststreaminit; begin if not assigned(webbrowser.document) then exit; olecheck(webbrowser.document.queryinterface (ipersiststreaminit, psi)); try //olecheck(psi.getsizemax(size)); hhtmltext := globalalloc(gptr, bufsize); if 0 = hhtmltext then raiselastwin32error; olecheck(createstreamonhglobal(hhtmltext, true, stream)); try olecheck(psi.save(stream, false)); size := strlen(pchar(hhtmltext)); setlength(result, size); copymemory(pchar(result), pointer(hhtmltext), size); finally stream := nil; end; finally psi := nil; end; end; ---- 此函數有一個參數webbrowser指定從那個控制項讀取html源碼,返回一個字串爲此控制項中的html源碼。首先還是要先檢查webbrowser.document物件是否有效,無效則退出;然後取得ipersiststreaminit介面;接著取得html源碼的大小:本來應該使用ipersiststreaminit介面的getsizemax函數,但在我的機器上測試,這個函數範圍值衡爲0,無效。因此只能先定義一個足夠大的緩衝區,如bufsize = $10000位元組(注意此緩衝區應該足夠大);然後同樣地分配全局堆記憶體塊,建立流,然後將html文本寫到流中。因爲此html文本在流中是以#0結尾的字串,因此可以用size := strlen(pchar(hhtmltext))取得實際長度,用setlength(result, size);設置返回字串長度爲html源碼實際長度,最後複製字串到返回字串中。 ---- 至此,直接訪問webbrowser控制項中的html源碼所需的兩個函數全部解析完畢。 ---- 不過需要注意的時,在使用這兩個函數前,最好對webbrowser.document物件進行初始化。下面提供一個函數,通過顯示一個空白頁面實現webbrowser.document物件初始化。 procedure showblankpage(webbrowser: twebbrowser); var url: olevariant; begin url := 'about:blank'; webbrowser.navigate2(url); end; ---- 建議在你有webbrowser控制項的form的formcreate事件裏調用此函數,初始化webbrowser.document物件。 ---- 本文程式在win nt delphi 5 環境下調試通過 ---- 參考資料:msdn ---- 特別感謝:白雲黃鶴bbs(bbs.whnet.edu.cn)網友anglefalls ********************************************************* 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind to make knowledge together! 希望能大家敞開心胸,將知識寶庫結合一起
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好

Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
系統時間:2024-05-06 9:41:39
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!