很早就有搞一個瀏覽器的想法了,在vs2003上就試圖做過,苦于經(jīng)常會有這種情況出現(xiàn):當(dāng)自治的瀏覽器遇到彈出窗口時無法捕獲新的彈出窗口,于是乎新的彈出窗口仍舊用ie(或其他系統(tǒng)默認(rèn)瀏覽器)打開,在研究vs2005的WebBrowser控件時發(fā)現(xiàn)有NewWindow事件,于是乎興奮不已,決定用這個分頁瀏覽器體驗(yàn)一下vs2005。
實(shí)現(xiàn)功能
預(yù)覽圖如下:
|
當(dāng)前瀏覽器的"另存為","打印","打印御覽","頁面設(shè)置",刷新,前進(jìn),后退等等。幾乎都是控件封裝好了的,沒有幾句代碼。
瀏覽器的分頁功能。當(dāng)瀏覽器有NewWindow激發(fā)時產(chǎn)生新的一頁。主要依靠NewWindow事件。
當(dāng)前頁面的狀態(tài)。例如標(biāo)題,狀態(tài)欄等。
實(shí)現(xiàn)過程以及關(guān)鍵點(diǎn)
新建一個vs2005的windows applaction項(xiàng)目
界面
一個MenuStrip實(shí)現(xiàn)最上面的菜單。
兩個ToolStrip分別是工具欄和地址欄。
一個TabControl也就是瀏覽器的主體了,它的每個TabPage就是每一個分頁了。
一個StatusStrip也就是狀態(tài)欄了。
另外為了使窗體大小變化時控件也隨著變化注意使用控件的dock屬性。
搭成如下界面:
|
順便說一句和vs2003不同的是vs2005把例如
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.saveasToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.printToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.printPreToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
這些通過我們拖拽控件,系統(tǒng)生成的界面代碼分離出來統(tǒng)一放在叫*.Designer.cs文件里了,詳見事例代碼中的Form1.Designer.cs文件。
輔助方法
#region //輔助方法 /// <summary> /// 當(dāng)在瀏覽器地址欄敲"回車"時當(dāng)前瀏覽器重定向到指定url(tscbUrl.Tex) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void tscbUrl_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { newCurrentPageUrl(tscbUrl.Text); } } /// <summary> /// 新建空白頁 /// </summary> private void newPage() { tscbUrl.Text = "about:blank"; TabPage mypage = new TabPage(); WebBrowser tempBrowser = new WebBrowser(); tempBrowser.Navigated += new WebBrowserNavigatedEventHandler(tempBrowser_Navigated); tempBrowser.NewWindow += new CancelEventHandler(tempBrowser_NewWindow); tempBrowser.ProgressChanged += new WebBrowserProgressChangedEventHandler(tempBrowser_ProgressChanged); tempBrowser.StatusTextChanged += new EventHandler(tempBrowser_StatusTextChanged); tempBrowser.Dock = DockStyle.Fill; mypage.Controls.Add(tempBrowser); tabControl1.TabPages.Add(mypage); tabControl1.SelectedTab = mypage; } /// <summary> /// 臨時瀏覽器進(jìn)度變化事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void tempBrowser_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e) { toolStripProgressBar1.Maximum = (int)e.MaximumProgress; toolStripProgressBar1.Value = (int)e.CurrentProgress; } /// <summary> /// 新建一頁并定向到指定url /// </summary> /// <param name="address">新一頁的瀏覽器重新定向到的url</param> private void newPage(string address) { TabPage mypage = new TabPage(); WebBrowser tempBrowser = new WebBrowser(); tempBrowser.Navigated += new WebBrowserNavigatedEventHandler(tempBrowser_Navigated); tempBrowser.NewWindow += new CancelEventHandler(tempBrowser_NewWindow); tempBrowser.StatusTextChanged += new EventHandler(tempBrowser_StatusTextChanged); tempBrowser.ProgressChanged += new WebBrowserProgressChangedEventHandler(tempBrowser_ProgressChanged); tempBrowser.Url = getUrl(address); tempBrowser.Dock = DockStyle.Fill; mypage.Controls.Add(tempBrowser); tabControl1.TabPages.Add(mypage); } /// <summary> /// 獲取當(dāng)前瀏覽器 /// </summary> /// <returns>當(dāng)前瀏覽器</returns> private WebBrowser getCurrentBrowser() { WebBrowser currentBrowser = (WebBrowser)tabControl1.SelectedTab.Controls[0]; return currentBrowser; } /// <summary> /// 處理字符串為合法url /// </summary> /// <param name="address"></param> /// <returns></returns> private Uri getUrl(string address) { string tempaddress = address; if ((!address.StartsWith("http://")) && (!address.StartsWith("https://")) && (!address.StartsWith("ftp://"))) { tempaddress = "http://" + address; } Uri myurl; try { myurl = new Uri(tempaddress); } catch { myurl = new Uri("about:blank"); } return myurl; } /// <summary> /// 截取字符串為指定長度 /// </summary> /// <param name="oldstring"></param> /// <returns></returns> private string newstring(string oldstring) { string temp; if (oldstring.Length < TITLE_COUNT) { temp = oldstring; } else { temp = oldstring.Substring(0, TITLE_COUNT); } return temp; } /// <summary> /// 設(shè)置"前進(jìn)","后退"button的可用狀態(tài) /// </summary> private void setStatusButton() { backButton.Enabled = getCurrentBrowser().CanGoBack; forwordButton.Enabled = getCurrentBrowser().CanGoForward; } #endregion |
說明:其中g(shù)etCurrentBrowser()是獲取當(dāng)前頁面的瀏覽器,這里把它叫當(dāng)前瀏覽器,即getCurrentBrowser()為獲取當(dāng)前瀏覽器。
菜單欄
#region//菜單欄 /// <summary> /// 另存為 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void saveasToolStripMenuItem_Click(object sender, EventArgs e) { getCurrentBrowser().ShowSaveAsDialog(); } /// <summary> /// 打印 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void printToolStripMenuItem_Click(object sender, EventArgs e) { getCurrentBrowser().ShowPrintDialog(); } /// <summary> /// 打印御覽 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void printPreToolStripMenuItem_Click(object sender, EventArgs e) { getCurrentBrowser().ShowPrintPreviewDialog(); } /// <summary> /// 關(guān)閉瀏覽器 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void exitToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit(); } /// <summary> /// 頁面設(shè)置 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void pageSetupToolStripMenuItem_Click(object sender, EventArgs e) { getCurrentBrowser().ShowPageSetupDialog(); } /// <summary> /// 屬性設(shè)置 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void propeToolStripMenuItem_Click(object sender, EventArgs e) { getCurrentBrowser().ShowPropertiesDialog(); } #region//關(guān)于 private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { AboutBox1 myabout = new AboutBox1(); myabout.Show(); } private void tipToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show("小提示:雙擊分頁標(biāo)題即可關(guān)閉當(dāng)前頁面。"); } #endregion #endregion |
說明:其中文件菜單的功能大都是WebBrowser控件封裝好的僅僅是用上文提到的getCurrentBrowser()獲取一下當(dāng)前瀏覽器罷了。
工具欄
#region//工具欄 /// <summary> /// 后退 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backButton_Click(object sender, EventArgs e) { getCurrentBrowser().GoBack(); setStatusButton(); } /// <summary> /// 前進(jìn) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void forwordButton_Click(object sender, EventArgs e) { getCurrentBrowser().GoForward(); setStatusButton(); } /// <summary> /// 停止 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void stopButton_Click(object sender, EventArgs e) { getCurrentBrowser().Stop(); } /// <summary> /// 刷新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void refreshButton_Click(object sender, EventArgs e) { getCurrentBrowser().Refresh(); } /// <summary> /// 定向到主頁 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void homeButton_Click(object sender, EventArgs e) { getCurrentBrowser().GoHome(); } /// <summary> /// 搜索 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void searchButton_Click(object sender, EventArgs e) { getCurrentBrowser().GoSearch(); } /// <summary> /// 打印 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void printButton_Click(object sender, EventArgs e) { getCurrentBrowser().Print(); } /// <summary> /// 新建空白頁 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void newButton_Click(object sender, EventArgs e) { newPage(); } /// <summary> /// 使當(dāng)前的瀏覽器定位到給定url /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void gotoButton_Click(object sender, EventArgs e) { newCurrentPageUrl(tscbUrl.Text); } #endregion |
說明:和菜單欄實(shí)現(xiàn)的功能類似,也是一些簡單的調(diào)用,僅僅是表現(xiàn)形式不同。
初始化
#region//初始化 /// <summary> /// 初始化 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Load(object sender, EventArgs e) { initMainForm(); } /// <summary> /// 初始化瀏覽器 /// </summary> private void initMainForm() { TabPage mypage = new TabPage(); WebBrowser tempBrowser = new WebBrowser(); tempBrowser.Navigated += new WebBrowserNavigatedEventHandler(tempBrowser_Navigated); tempBrowser.NewWindow += new CancelEventHandler(tempBrowser_NewWindow); tempBrowser.StatusTextChanged += new EventHandler(tempBrowser_StatusTextChanged); tempBrowser.ProgressChanged += new WebBrowserProgressChangedEventHandler(tempBrowser_ProgressChanged); tempBrowser.Dock = DockStyle.Fill; tempBrowser.GoHome();//和新建空白頁不同 mypage.Controls.Add(tempBrowser); tabControl1.TabPages.Add(mypage); } #endregion |
說明:分頁瀏覽器初始化時要定向到主頁,雖然我們的瀏覽器暫時沒有提供設(shè)置主頁的功能。
臨時瀏覽器事件
#region//臨時瀏覽器事件 /// <summary> /// 臨時瀏覽器狀態(tài)變化事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void tempBrowser_StatusTextChanged(object sender, EventArgs e) { WebBrowser myBrowser = (WebBrowser)sender; if (myBrowser != getCurrentBrowser()) { return; } else { toolStripStatusLabel1.Text = myBrowser.StatusText; } } /// <summary> /// 在當(dāng)前頁面上重新定向 /// </summary> /// <param name="address">url</param> private void newCurrentPageUrl(String address) { getCurrentBrowser().Navigate(getUrl(address)); } /// <summary> /// 臨時瀏覽器產(chǎn)生新窗體事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void tempBrowser_NewWindow(object sender, CancelEventArgs e) { //獲取觸發(fā)tempBrowser_NewWindow事件的瀏覽器 WebBrowser myBrowser = (WebBrowser)sender; //獲取觸發(fā)tempBrowser_NewWindow事件的瀏覽器所在TabPage TabPage mypage = (TabPage)myBrowser.Parent; //通過StatusText屬性獲得新的url string NewURL = ((WebBrowser)sender).StatusText; //生成新的一頁 TabPage TabPageTemp = new TabPage(); //生成新的tempBrowser WebBrowser tempBrowser = new WebBrowser(); //臨時瀏覽器定向到新的url tempBrowser.Navigate(NewURL); tempBrowser.Dock = DockStyle.Fill; //為臨時瀏覽器關(guān)聯(lián)NewWindow等事件 tempBrowser.NewWindow += new CancelEventHandler(tempBrowser_NewWindow); tempBrowser.Navigated += new WebBrowserNavigatedEventHandler(tempBrowser_Navigated); tempBrowser.ProgressChanged += new WebBrowserProgressChangedEventHandler(tempBrowser_ProgressChanged); tempBrowser.StatusTextChanged+=new EventHandler(tempBrowser_StatusTextChanged); //將臨時瀏覽器添加到臨時TabPage中 TabPageTemp.Controls.Add(tempBrowser); //將臨時TabPage添加到主窗體中 this.tabControl1.TabPages.Add(TabPageTemp); //使外部無法捕獲此事件 e.Cancel = true; } /// <summary> /// 臨時瀏覽器定向完畢 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void tempBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e) { tscbUrl.Text = getCurrentBrowser().Url.ToString(); WebBrowser mybrowser = (WebBrowser)sender; TabPage mypage=(TabPage)mybrowser.Parent; //設(shè)置臨時瀏覽器所在tab標(biāo)題 mypage.Text= newstring(mybrowser.DocumentTitle); } #endregion |
說明:臨時瀏覽器實(shí)際上是用程序的方式先new出一個tempBrowser然后添加到一個分頁中去。其中這個tempBrowser我稱它為臨時瀏覽器。其中void tempBrowser_NewWindow(object sender, CancelEventArgs e){..}事件是比較重要的,我認(rèn)為它是整個程序的核心部分。
tabControl1事件
#region//tabControl1事件 /// <summary> /// 切換tab /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) { WebBrowser mybor = (WebBrowser)tabControl1.SelectedTab.Controls[0]; if (mybor.Url != null) { //地址輸入框 tscbUrl.Text = mybor.Url.ToString(); tabControl1.SelectedTab.Text = newstring(mybor.DocumentTitle); } else { tscbUrl.Text = "about:blank"; tabControl1.SelectedTab.Text = "空白頁"; } setStatusButton(); } /// <summary> /// 關(guān)閉當(dāng)前tab /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void tabControl1_DoubleClick(object sender, EventArgs e) { //僅僅剩下一個tab時返回 if (tabControl1.TabPages.Count <= 1) { tabControl1.SelectedTab.Text = "空白頁"; getCurrentBrowser().Navigate("about:blank"); } else { //先將tabControl1隱藏然后remove掉目標(biāo)tab(如果不隱藏則出現(xiàn)閃爍,即系統(tǒng)自動調(diào)轉(zhuǎn)到tabControl1的第一個tab然后跳會。)最后顯示tabControl1。 tabControl1.Visible = false; WebBrowser mybor = getCurrentBrowser(); //釋放資源 mybor.Dispose(); mybor.Controls.Clear(); this.tabControl1.TabPages.Remove(this.tabControl1.SelectedTab); //重新設(shè)置當(dāng)前tab tabControl1.SelectedTab = tabControl1.TabPages[tabControl1.TabPages.Count - 1]; tabControl1.Visible = true; } } #endregion |
說明:當(dāng)雙擊當(dāng)前Tabpage從而關(guān)閉當(dāng)前頁面時,tabControl1 會首先定位到第一個tab然后再定位到指定的Tabpage上,我采取隱藏tabControl1-處理-顯示tabControl1思路解決此問題。
總結(jié)
分頁瀏覽器所謂"分頁",從實(shí)現(xiàn)上講就是"控件的動態(tài)添加",當(dāng)前瀏覽器產(chǎn)生新窗體時,先new出一個TabPage,再new一個WebBrowser,把這個WebBrowser加載了一些事件以后添加到先前的這個TabPage上,然后把這個TabPage添加到"主窗體"tabControl1中。
不足之處
最大的不足:
用((WebBrowser)sender).StatusText無法捕獲的url(例如StatusText 為"javascript:void(0)")目前無法解決這也是某些莫名其妙的問題的出處。另外某些腳本不支持。其他一些罪狀讓我們共同羅列…