Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Want Tabbed Browsing in Internet Explorer? Build It Yourself with WinForms : Page 3

You can have the best of Firefox without changing browsers. Learn the new controls in WinForms 2.0 and use them to enhance Internet Explorer with a tabbed browsing UI.


advertisement
Coding the Application
Now that I have all of the controls in place on the form I'm ready to start coding the business logic. First, I'll import the following namespaces:

Imports System.xml Imports System.Net

These two namespaces contain classes to retrieve XML documents over the Web. In particular, I will use them when downloading content of live bookmarks (RSS feeds). I will also make use of XPath expressions to extract the relevant sections of the document to display. Declare a global variable—a string array to store the list of URLs that the user has typed:

Dim URLsTyped() As String

Define the ResizeAddressBar() method so that the address ComboBox can be stretched when the form resizes:


Private Sub ResizeAddressBar() '===Resize the Address combobox when the form is ' resized Dim size As Size size.Height = cbbURL.Size.Height size.Width = Me.Size.Width - btnGo.Size.Width _ - lblAddress.Size.Width - 25 cbbURL.Size = size End Sub

The Form1_Resize event will be fired whenever the form resizes:

Private Sub Form1_Resize(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles Me.Resize '===When the form resizes=== ResizeAddressBar() End Sub


Author's Note: Due to a bug in beta 1, the address bar is hidden when the form is first loaded. Maximizing the form will reveal the address bar.


I will define two methods: DisplayNewTab() and DisplayinCurrentTab(). The DisplayNewTab() method first dynamically creates a new instance of the WebBrowser control and then creates a new tab page within the TabControl control.

The WebBrowser control in WinForms 2.0 is a managed wrapper for the WebBrowser ActiveX control. And thus it is now much easier to use the WebBrowser control than it was in .NET 1.1.

Add the WebBrowser control to the new tab page. Note that when the Web page is being loaded, I set the title of the tab page to "Loading…" (because the title of the document is not yet available at this stage). When the WebBrowser control has finished loading the document, the DocumentTitleChanged event will fire. This is serviced by the WebBrowser_DocumentTitleChanged() method (I will discuss this later). Also note that I have made use of the ToolTipText property of the tab page to store the URL for the page. This is important because you need to be able to display the URL of the current page in the address bar when a tab is selected.

Private Sub DisplayNewTab(ByVal URL As String) '===Display a page in a new tab page=== '---create a new WebBrowser control instance Dim wb As New WebBrowser wb.Dock = System.Windows.Forms.DockStyle.Fill wb.Location = New System.Drawing.Point(3, 3) wb.Navigate(URL) '---update the tab title when the document title ' has finished loading AddHandler wb.DocumentTitleChanged, AddressOf _ WebBrowser_DocumentTitleChanged '---create a new tab page and then add to the tab ' control Dim tp As New TabPage tp.Text = "Loading..." tp.ToolTipText = URL tp.Controls.Add(wb) TabControl1.TabPages.Add(tp) '---always display the latest tab TabControl1.SelectTab(TabControl1.TabCount - 1) End Sub

The DisplayinCurrentTab() method displays a Web page in the current selected page. Note that I need to first check if there is a current a tab page selected; if not, I will need to call the DisplayNewTab() method.

Private Sub DisplayinCurrentTab(ByVal URL As String) '===Display a page in the current tab page=== If TabControl1.SelectedTab Is Nothing Then DisplayNewTab(URL) Exit Sub End If Dim wb As WebBrowser = _ TabControl1.SelectedTab.Controls(0) TabControl1.SelectedTab.Text = "Loading..." TabControl1.SelectedTab.ToolTipText = URL wb.Navigate(URL) '---update the tab title when the document title ' has finished loading AddHandler wb.DocumentTitleChanged, AddressOf _ WebBrowser_DocumentTitleChanged End Sub

As mentioned previously, the WebBrowser_DocumentTitleChanged() method will handle the DocumentTitleChanged event. One limitation that I faced when using this event is that it passes in a reference from the WebBrowser control that fires the event—not the tab page. Hence I needed to write code to cycle through all the tab pages to look for the container (i.e. tab page) of this WebBrowser control. Once the particular tab page is located, I will update its page title as well as the address bar and status bar.

Private Sub WebBrowser_DocumentTitleChanged( _ ByVal sender As Object, _ ByVal e As System.EventArgs) '===Update the title of a tab page when the page ' has finished loading=== '--locate which tab page contains the webbrowser ' control Dim wb As WebBrowser = CType(sender, WebBrowser) Dim i As Integer = 0 While Not TabControl1.TabPages(i).Contains(wb) i += 1 End While '---Set the tab page title TabControl1.TabPages(i).Text = wb.DocumentTitle TabControl1.TabPages(i).ToolTipText = wb.Url '---Display the URL in the Address combobox and ' Statusbar cbbURL.Text = wb.Url StatusStripPanel1.Text = wb.Url End Sub

There is another TabControl event that I need to service and that is the SelectedIndexChanged event. This event is fired whenever a tab page is selected. What I want to do in this event is to display the URL of the currently selected tab page in the address bar and the status bar:

Private Sub TabControl1_SelectedIndexChanged( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles TabControl1.SelectedIndexChanged '===Update the URL of the selected tab page in ' the Address combobox and Statusbar Dim tp As TabControl = CType(sender, TabControl) If tp.SelectedTab IsNot Nothing Then cbbURL.Text = tp.SelectedTab.ToolTipText StatusStripPanel1.Text = _ tp.SelectedTab.ToolTipText End If End Sub

When the user types in a URL and clicks the Go button, I want to display the Web page in a new tab page and then save the typed URL into the global variable string array:

Private Sub btnGo_Click(ByVal sender As _ System.Object, _ ByVal e As System.EventArgs) _ Handles btnGo.Click '===GO button=== '---display page in a new tab DisplayNewTab(cbbURL.Text) '---save the typed URL into a string array If URLsTyped Is Nothing Then ReDim URLsTyped(0) Else ReDim Preserve URLsTyped(URLsTyped.Length) End If URLsTyped(URLsTyped.Length - 1) = cbbURL.Text End Sub

Instead of clicking the Go button to load a page, it is much easier for the user to type the URL and then press the Enter key. This can be trapped using the KeyPress event of the ComboBox control:

Private Sub cbbURL_KeyPress(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyPressEventArgs) _ Handles cbbURL.KeyPress '===When the enter types in the Address ' combobox=== '---bug: this event did not fire when the Enter ' key is pressed If e.KeyChar = Microsoft.VisualBasic.ChrW(13) _ Then e.Handled = True '---display page in a new tab DisplayNewTab(cbbURL.Text) '---save the typed URL into a string array If URLsTyped Is Nothing Then ReDim URLsTyped(0) Else ReDim Preserve _ URLsTyped(URLsTyped.Length) End If URLsTyped(URLsTyped.Length - 1) = cbbURL.Text End If End Sub


Author's Note: The KeyPress event did not fire correctly when the Enter key was pressed in Beta 1. This should be fixed with Beta 2, which isn't far off.


The user can also view a list of URLs that he has typed previously by clicking on the dropdown arrow of the address ComboBox control:

Private Sub cbbURL_DropDown(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles cbbURL.DropDown '===Display in the Address combobox the list=== ' of last few web sites URL typed=== If URLsTyped IsNot Nothing Then cbbURL.Items.Clear() cbbURL.Items.AddRange(URLsTyped) End If End Sub


Author's Note: For simplicity I did not persist the list of URLs. Using this code, the list will contain only URLs typed by the user in the current run of the application.


When the user selects the menu Favorites -> Add Live Bookmark..., the application prompts the user to supply the feed URL and then calls the LoadLiveFavorite() method. This method will load the RSS feed from the supplied URL and then return the title of the feed. The feed title is used to create a file in the "My documents" directory where the URL is written to the content. The file will have a .live extension.

Private Sub AddlivefavoriteToolStripMenuItem_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles _ AddlivefavoriteToolStripMenuItem.Click '===Add a live favorite to the browser=== Dim RSSfeedURL As String = _ Microsoft.VisualBasic.InputBox( _ "Enter feed", , , , ) Dim RSSTitle As String = _ LoadLiveFavorite(RSSfeedURL) '---save live favorite to file Try Dim filePath As String filePath = System.IO.Path.Combine( _ My.Computer.FileSystem.SpecialDirectories._ MyDocuments, _ RSSTitle.Replace(":", "") & ".live") My.Computer.FileSystem.WriteAllText( _ filePath, RSSfeedURL, True) Catch fileException As Exception Throw fileException End Try End Sub

Figure 13. Bookmarks: The "live bookmark" content from an RSS feed is now available to the application.
The LoadLiveFavorite() method takes in the feed URL and then makes a request over the Web and loads the return document using an XmlTextReader object. I then apply XPath expressions to extract the title of the feed as well as the title of the various news items. This information is then used to create menus in the Live Bookmark ToolStrip (see Figure 13).

Each menu item can be clicked to display its page. Again, I make use of the ToolTipText property of each ToolStripMenuItem control to store its URL and I've also added an event handler to each menu item to service the Click event when the user selects one (see Listing 1).

To load all the live bookmarks subscribed, the user can select the menu item: Favorites -> Load all live bookmarks. This loads all ".live" files from "My documents" onto the live bookmarks bar:

Private Sub _ LoadallLiveBookmarksToolStripMenuItem_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles _ LoadallLiveBookmarksToolStripMenuItem.Click '===load all live bookmarks from disk=== '---look for all files with .live extension For Each foundFile As String In _ My.Computer.FileSystem.GetFiles _ (My.Computer.FileSystem. _ SpecialDirectories.MyDocuments, _ True, "*.live") '---read the content of each file, i.e. the RSS ' Feed URL Dim filePath As String Dim RSSURL As String Try filePath = System.IO.Path.Combine( _ My.Computer.FileSystem. _ SpecialDirectories.MyDocuments, _ foundFile) RSSURL = _ My.Computer.FileSystem. _ ReadAllText(filePath) '---display the live bookmark in the toolbar LoadLiveFavorite(RSSURL) Catch fileException As Exception Throw fileException End Try Next End Sub

When the user selects a menu item in a live bookmark, two behaviors can result: If one page is selected, it will display in the current tab page or if all items are selected, each will display in a series of new tab pages:

Private Sub menu_Click(ByVal sender As _ System.Object, _ ByVal e As System.EventArgs) '===Display the selected links in a live bookmark ' menu=== Dim menuitem As ToolStripMenuItem = _ CType(sender, ToolStripMenuItem) '---display all links in tabs If menuitem.Text = "Open in tabs" Then If TabControl1.TabPages.Count > 0 Then TabControl1.TabPages.Clear() End If For i As Integer = 0 To _ menuitem.Owner.Items.Count - 3 DisplayNewTab(menuitem.Owner. _ Items(i).ToolTipText) Next Else '---display link in current tab DisplayinCurrentTab(menuitem.ToolTipText) End If End Sub

Finally, when the user right-clicks on a tab page, the context menu appears to allow the user to close the tab:

Private Sub CloseTabToolStripMenuItem_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles CloseTabToolStripMenuItem.Click '===Close tab context menu to close the current ' tab page=== TabControl1.TabPages.Remove( _ TabControl1.SelectedTab) End Sub

And there you have it. I began with a simple form using WinForms 2.0's WebBrowser control, among others, and then walked you through each step to write the code that makes these form controls come to life in the form of an enhanced Firefox-like browser. If you've followed along, you should now be able to run your application and try out your own next-generation tabbed browser.

There are still lots areas that you can enhance yourself. I strongly suggest you download the sample code and customize the application for your own use and according to your whims. For me, the ability to use live bookmarks is a good reason for this application to stay on my desktop. And I finally have a Web browser to call my own.



Wei-Meng Lee is a Microsoft .NET MVP and co-founder of Active Developer, a training company specializing in .NET and wireless technologies. He is a frequent speaker and author of numerous books on .NET, XML, and wireless technologies.
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap