一,、簡介 大家都知道,,目前比較流行的網(wǎng)絡(luò)瀏覽器如Mozilla FireFox以及MyIE2等都具有多頁面瀏覽功能,,每打開一個(gè)新的頁面都自動(dòng)產(chǎn)生一個(gè)新的選項(xiàng)卡頁面,頁面的關(guān)閉也十分簡便,。這種設(shè)計(jì)思想使得用戶在瀏覽多個(gè)網(wǎng)頁時(shí)桌面十分簡潔,,也避免了用戶等待單頁面顯示的苦惱。由于這些瀏覽器一般都支持操作多種文件格式,,所以當(dāng)瀏覽本地機(jī)器上的多個(gè)文件時(shí)也極為方便,。 本文使用Visual C詳細(xì)介紹如何實(shí)現(xiàn)這種多頁面瀏覽功能。同時(shí),,還實(shí)現(xiàn)了下面附加功能: 打印, 打印預(yù)覽,,頁面屬性,選項(xiàng),,查找,,查看頁面源文件等。 二,、關(guān)鍵技術(shù)分析 解決問題的關(guān)鍵在于對瀏覽器控件WebBrowser的NewWindow2事件的編程,。當(dāng)需要顯示某種文件而生成一個(gè)新窗口時(shí),NewWindow2 事件即被激活,。注意,,該事件發(fā)生在WebBrowser控件的新窗口產(chǎn)生之前。例如,,作為對導(dǎo)航到一個(gè)新窗口或者一個(gè)腳本控制的window.open方法的響應(yīng),,即發(fā)生該事件。為了聲明當(dāng)一個(gè)新窗口被打開時(shí),,將使用我們自己的瀏覽器程序,,應(yīng)該把參數(shù)ppDisp置為Application 對象。此時(shí),,如果你選擇“在新窗口中打開”,,則新產(chǎn)生一個(gè)窗口來顯示W(wǎng)eb頁面。你也可以把RegisterAsBrowser設(shè)置為TRUE,,這將導(dǎo)致新生成的WebBrowser控件參與到窗口命名的沖突問題上,。例如,如果一個(gè)窗口的名字在腳本的另外一處用到,,那么該控件被派上用場,,而不是再產(chǎn)生一個(gè)新的窗口,,因?yàn)榭丶诖蜷_一個(gè)新的窗口之前先檢查一下所有已存在的窗口名稱以避免命名沖突。 在本文示例中,,作為對該事件的響應(yīng),,我們動(dòng)態(tài)地創(chuàng)建一個(gè)tab頁面,并通過調(diào)用CreateNewWebBrowser()方法產(chǎn)生一個(gè)WebBrowser控件作為其子控件――這里每一個(gè)子控件都有一個(gè)包含該控件相關(guān)信息的tag屬性,。詳見下面的源碼: private void axWebBrowser1_NewWindow2(object sender, AxSHDocVw.DWebBrowserEvents2_NewWindow2Event e) { AxSHDocVw.AxWebBrowser _axWebBrowser = CreateNewWebBrowser(); e.ppDisp = _axWebBrowser.Application; _axWebBrowser.RegisterAsBrowser = true; } private AxSHDocVw.AxWebBrowser CreateNewWebBrowser() { AxSHDocVw.AxWebBrowser _axWebBrowser = new AxSHDocVw.AxWebBrowser(); _axWebBrowser.Tag = new HE_WebBrowserTag(); TabPage _TabPage = new TabPage(); _TabPage.Controls.Add(_axWebBrowser); _axWebBrowser.Dock = DockStyle.Fill; _axWebBrowser.BeforeNavigate2 += new AxSHDocVw.DWebBrowserEvents2_BeforeNavigate2EventHandler(this.axWebBrowser1_BeforeNavigate2); _axWebBrowser.DocumentComplete += new AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEventHandler(this.axWebBrowser1_DocumentComplete); _axWebBrowser.NavigateComplete2 += new AxSHDocVw.DWebBrowserEvents2_NavigateComplete2EventHandler(this.axWebBrowser1_NavigateComplete2); _axWebBrowser.NavigateError += new AxSHDocVw.DWebBrowserEvents2_NavigateErrorEventHandler(this.axWebBrowser1_NavigateError); _axWebBrowser.NewWindow2 += new AxSHDocVw.DWebBrowserEvents2_NewWindow2EventHandler(this.axWebBrowser1_NewWindow2); _axWebBrowser.ProgressChange += new AxSHDocVw.DWebBrowserEvents2_ProgressChangeEventHandler(this.axWebBrowser1_ProgressChange); _axWebBrowser.StatusTextChange += new AxSHDocVw.DWebBrowserEvents2_StatusTextChangeEventHandler(this.axWebBrowser1_StatusTextChange); _axWebBrowser.TitleChange += new AxSHDocVw.DWebBrowserEvents2_TitleChangeEventHandler(this.axWebBrowser1_TitleChange); _axWebBrowser.CommandStateChange += new AxSHDocVw.DWebBrowserEvents2_CommandStateChangeEventHandler(this.axWebBrowser1_CommandStateChange); tabControl1.TabPages.Add(_TabPage); tabControl1.SelectedTab = _TabPage; return _axWebBrowser; } 注意,,每一個(gè)WebBrowser控件都有一個(gè)tag,我定義成一個(gè)簡單的class,,它用來包含一些該控件相關(guān)的獨(dú)有信息。請看: public class HE_WebBrowserTag { public int _TabIndex = 0; public bool _CanBack = false; public bool _CanForward = false; } 三,、實(shí)現(xiàn)“查找”,、“查看頁面源文件”、“選項(xiàng)”對話框等功能 注意 本例程中使用了一個(gè)未公開的GUID,,其在將來的系統(tǒng)中可以發(fā)生變更,。 1、定義 IOleCommandTarget 接口 為定義一個(gè).NET接口以獲得關(guān)于一個(gè)COM接口的參考,請遵從下列步驟: 1) 賦予.NET接口相應(yīng)的COM接口的GUID值,; 2) 包含對接口中所有方法的類型聲明,; 3) 包含對Mshtml.dll和Shdocvw.dll文件的參考,在Visual C .NET工程中操作,,請遵從: A. 在項(xiàng)目菜單下單擊“添加引用”,; B. 單擊“COM” 選項(xiàng)卡; C. 雙擊“Microsoft HTML Object Library” 和“Microsoft Internet Controls”,。 4) 應(yīng)該在程序命名空間聲明之前,,包含下面的接口聲明以添加對Microsoft HTML (MSHTML) IOleCommandTarget接口的參照引用: using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)] public struct OLECMDTEXT { public uint cmdtextf; public uint cwActual; public uint cwBuf; [MarshalAs(UnmanagedType.ByValTStr,SizeConst=100)]public char rgwz; } [StructLayout(LayoutKind.Sequential)] public struct OLECMD { public uint cmdID; public uint cmdf; } // IOleCommandTarget的Interop定義 [ComImport, Guid("b722bccb-4e68-101b-a2bc-00aa00404770"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IOleCommandTarget { //重要: 下面方法的順序非常重要,因?yàn)楸臼纠形覀兪褂玫氖窃缙诮壎?,詳見MSDN中有關(guān).NET/COM互操作的參考,。 void QueryStatus(ref Guid pguidCmdGroup, UInt32 cCmds, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] OLECMD[] prgCmds, ref OLECMDTEXT CmdText); void Exec(ref Guid pguidCmdGroup, uint nCmdId, uint nCmdExecOpt, ref object pvaIn, ref object pvaOut); } 2、為CGID_IWebBrowser定義一個(gè)GUID 必須定義CGI_IWebBrowser的GUID以通知MSHTML如何來處理你的命令I(lǐng)D,。在.NET中實(shí)現(xiàn)如下: private Guid cmdGuid = new Guid("ED016940-BD5B-11CF-BA4E-00C04FD70816"); private enum MiscCommandTarget { Find = 1, ViewSource, Options } 3,、調(diào)用Exec()方法 注意,下列三個(gè)過程成功調(diào)用Exec()的前提是,,已經(jīng)存在名為webBrowser的瀏覽器控件的被包容實(shí)例,。 private mshtml.HTMLDocument GetDocument() { try { mshtml.HTMLDocument htm = (mshtml.HTMLDocument)axWebBrowser2.Document; return htm; } catch { throw (new Exception("不能從WebBrowser控件中獲取文件對象")); } } //查看源碼的方法 public void ViewSource() { IOleCommandTarget cmdt; Object o = new object(); try { cmdt = (IOleCommandTarget)GetDocument(); cmdt.Exec(ref cmdGuid, (uint)MiscCommandTarget.ViewSource, (uint)SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o); } catch(Exception e) { System.Windows.Forms.MessageBox.Show(e.Message); } } public void Find() { IOleCommandTarget cmdt; Object o = new object(); try { cmdt = (IOleCommandTarget)GetDocument(); cmdt.Exec(ref cmdGuid, (uint)MiscCommandTarget.Find, (uint)SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o); } catch(Exception e) { System.Windows.Forms.MessageBox.Show(e.Message); } } //顯示“選項(xiàng)”對話框的方法 public void InternetOptions() { IOleCommandTarget cmdt; Object o = new object(); try { cmdt = (IOleCommandTarget)GetDocument(); cmdt.Exec(ref cmdGuid, (uint)MiscCommandTarget.Options, (uint)SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o); } catch { // 注意:因?yàn)樵撨^程相應(yīng)的CMDID是在Internet Explorer處理 // ,所以此處的異常代碼塊將總被激活,,即使該對話框及其操作成功,。 //當(dāng)然,你可以通過瀏覽器選擇設(shè)置來禁止這種錯(cuò)誤的出現(xiàn),。 //不過,,即使出現(xiàn)這種提示,,對你的主機(jī)也無任何損害。 } } |
|