Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Web Browser with C#

0.00/5 (No votes)
25 Apr 2010 1  
New functionalities for a web browser (for beginners).

Introduction

In my second article, I covered more stuff. As I am learning C#, things are going very good. I hope you will find my code useful and apply it in your own solutions with some modifications. After all, while you modify other people's codes, you'll learn faster (so I believe).

This program is called "WebPlus-V01". I know there are many web browsers out there with all the "bells-n-whistles", but I wanted to add a few new things that I haven't seen before... I'll get into the C# code as much as I can, and also tell you most of the functionalities of the program. Please feel free to download and play around with the code. I am very curious to see what else you guys would do to it (if you choose to enhance it).

The features of WebPlus:

  • Alarm timer: Have you ever had a problem while browsing on the Internet and not knowing how long you were on, and forget about an important meeting or something? Well... no more. Use WebPlus' timer, up to 2 hours, to remind yourself of the important meeting and not worry about the passing time when reading your favorite blogs :)
  • Blackout: I am always annoyed by some people looking over my shoulder to see what I am doing or where I am going on the Internet. So, if you want to keep those annoying eyes out of your site, just blackout your page and its address bar, turn around, and say "Did you want to ask me something?" without closing your browser.
  • Notepad for your favorite websites: Each bookmark can also holds notes. It's there as an option. You can always make yourself notes if you see something interesting.
  • Conversion tool: Next time when you are browsing a website and wonder how far 45 Km is in miles, use the tool provided with the browser.
  • Bookmark folders: You can always create yourself separate bookmark folders and show only the selected favorites on your list. No more clicking through the trees ;)

Enjoy :)

Background

My very first article's subject was a small program called "Code Database". I use it every day. I only wanted a single function from the program, which it does pretty good... keeping my code. I use an XML file as my database because of some problems I had with the MS Jet engine. I also mentioned that I tried SQL Express for that program, but decided to go with XML anyway. This time I am using a SQL Express database. Everything in this code is dynamic, nothing is bound to the database. It's an old habit of mine that I don't like to automate things by tying up them to each other using bounding tools. Reason? Because this way I have more control over things; otherwise, if something snaps, the code will go one way, and the database another, tearing each other apart.

Using the code

There are two form files and one custom file in this program. The custom file contains two classes in it. They are not inheritances of each other, and have separate classes and duties. I do some work on my classes sometimes to make things more compact. Such as using multi-functional constructors :)

  • Form1 (Main form)
  • Form Settings
  • work.cs (Contains the ETWork class and DBConn classes. As you will see in the code, the ETWork class does two separate things depending on the parameters passed.)

The SQL Express database contains three tables:

  • Folder
  • Settings
  • UrlPath

Folder keeps the folder names for bookmarks. Settings keeps the browser options and other goodies. UrlPath keeps the bookmarks with their extra data (notes).

Let's start with something that I am dying to share. Indentation of my code! Yes, it's not the center piece of this article, although this is something I want to tell about first.

The following code samples are identical. I use the one that looks more compact. This way my line count gets much smaller and doesn't hurt my eyes when looking at curly-brackets.

try { Conn1.Open();
    MyCommand.ExecuteNonQuery();
    Conn1.Close(); }
catch (Exception exc) {
    throw exc; }
finally {
    Conn1.Close(); }

-----------------------------------

try
{
    Conn1.Open();
    MyCommand.ExecuteNonQuery();
    Conn1.Close();
}
catch (Exception exc)
{
    throw exc;
}
finally
{
    Conn1.Close();
}

I wouldn't ask everyone to code that way, it comes with practice and self-discipline. Even though VS indents the code for me, when I have time, I organza them (a good exercise for me to go through the code once again).

That's out of the way, I would like to share some other code with you now. You can always download and take a look at the full code yourself.

The following code is for the Search Engine that I use on my web browser. You can see how a "switch" is used, with multiple "cases" for one solution, and the ToLower property of the Text class. "ToLower" is same as "LCase" in VB, which makes every character in the text "lowercase".

switch (clsDB.SEARCH_ENGINE)
{
    case "Yahoo":
        CurrentSearchEngine = "search." + 
          clsDB.SEARCH_ENGINE.ToLower() + ".com//search?p=";
        break;
    case "Google":
    case "Search":
    case "Bing":
        CurrentSearchEngine = "www." + 
          clsDB.SEARCH_ENGINE.ToLower() + ".com//search?q=";
        break;
    case "Lycos":
        CurrentSearchEngine = "search." + 
          clsDB.SEARCH_ENGINE.ToLower() + ".com/?tab=web&query=";
        break;
}

C# won't let us use numbers as starting characters for our variables. So instead, I use underscores, which actually looks better ;)

private void ClearAlarmCheckBoxes()
{
    _5min.Checked = false;
    _15min.Checked = false;
    _30min.Checked = false;
    _1hr.Checked = false;
    _1nHalfHr.Checked = false;
    _2hr.Checked = false;
}

Here is a sample of formatting numbers. I used it to format the results of the conversion utility "lblResult.Text = String.Format("{0:0,0.0}".

The conversion utility I created converts three systems. Kilo to Lb, C to F, and Km to Mile (and vice-versa).

switch (XSelection)
{
    case 1:
        ResY = ConversionNumber * 1609.344;
        break;
    case 2:
        ResY = ConversionNumber * 0.621;
        break;
    case 3:
        ResY = (5.00 / 9.00) * (ConversionNumber - 32);
        break;
    case 4:
        ResY = (9.00 / 5.00) * ConversionNumber + 32;
        break;
    case 5:
        ResY = ConversionNumber * 0.4535;
        break;
    case 6:
        ResY = ConversionNumber * 2.2046;
        break;
}
_ConvertedNumber = ResY; // Set the result

You can see "_ConvertedNumber" also has an underscore. Because this code is located in a class, and that is a field. I name all my fields (I try to) starting with underscores to identify them better. Case 1 and 2 is for length, 3 and 4 is for temperature, and the last two are for weight.

There are lots of comments like this one: "clsDB = new DBConn(); // Create an instance of 'DBConn' class", which I wanted to emphasize on how important it is to understand the "concept" of "OOP". It's all about creating a usable copy (object) of the code you create.

Let's see some DB code.

There are four major things that I want from my DB code. To enter new data: "INSERT INTO table (...) VALUES(..)". Second, modify the data: "UPDATE table SET field = value, ...", then delete data: "DELETE FROM table..", and the last one, to request for data: "SELECT fields FROM table".

Although these are the main four things, there are other stuff that you probably will work on, such as "Joining the tables and/or databases in one string", "creating DBs and tables"... etc. They're not easy but, it gets easier when you practice. I didn't have to use "JOIN" in this code but I have used them many times in the past. Queries looks the same in most DB cases, with some minor adjustments from one to another.

Entering new data:

public void NewBookmark(int FolderID, string BookMarkName, string BookMarkUrl)
{
    // Create new bookmark
    CommaCheck(BookMarkName); // Cleanup commas
    Conn1 = new SqlConnection(connStr); // Create an instance of 'SqlConnection' class

    SqlCommand MyCommand = Conn1.CreateCommand(); // Create an instance of 'SqlCommand' class
    MyCommand.CommandText = "INSERT INTO UrlPath (FolderID, CustomName, FullUrlPath) VALUES ("
                         + FolderID + ", '" + BookMarkName + 
                         "', '" + BookMarkUrl + "')";
    try {
        Conn1.Open(); MyCommand.ExecuteNonQuery();
        Conn1.Close(); }
    catch (Exception exc) {
        throw exc; }
    finally {
        Conn1.Close(); }
}

Modifying data:

public void SaveSettings()
{
    // Save settings when click 'Save/Exit' button
    // on the Settings form
    Conn1 = new SqlConnection(connStr);
    // Create an instance of 'SqlConnection' class

    SqlCommand MyCommand = Conn1.CreateCommand();
    // Create an instance of 'SqlCommand' class

    MyCommand.CommandText = "UPDATE settings SET SearchEngine = '" +
        _SearchEngine + "', StartMax = " + BoolBitConversion(_StartMax) + 
        ", ShowToolTips = " + BoolBitConversion(_ShowToolTips) + 
        ", RememberRefresh = " + BoolBitConversion(_RememberRefresh) + 
        ", SaveHistory = " + BoolBitConversion(_SaveHistory);

    try {
        Conn1.Open(); MyCommand.ExecuteNonQuery();
        Conn1.Close(); }
    catch (Exception exc) {
        throw exc; }
    finally {
        Conn1.Close(); }
}

Deleting data:

public void DeleteSelectedBookmark(string BookMarkID)
{
    // Delete bookmark
    int ConvertID;
    ConvertID = Convert.ToInt32(BookMarkID);
    Conn1 = new SqlConnection(connStr);
    // Create an instance of 'SqlConnection' class

    // Create an instance of 'SqlCommand' class
    SqlCommand MyCommand = Conn1.CreateCommand();
    MyCommand.CommandText = 
            "DELETE FROM UrlPath WHERE ID = " + ConvertID;
    try {
        Conn1.Open(); MyCommand.ExecuteNonQuery();
        Conn1.Close(); }
    catch (Exception exc) {
        throw exc; }
    finally {
        Conn1.Close(); }
}

Requesting data:

public List<string> FillBookMarks(int SelectedFolderID)
{
    // Fill the bookmark list from selected boomark folder
    List<string> BookMarkList = new List<string>();
    // Create an instance of 'List<t>' array class

    Conn1 = new SqlConnection(connStr);

    SqlCommand MyCommand = Conn1.CreateCommand();
    char Splitchr = (char)8;

    try { Conn1.Open();
        MyCommand.CommandText = 
          "SELECT ID, CustomName, FullUrlPath " + 
          "FROM UrlPath WHERE FolderID = " + 
          SelectedFolderID; // set query
        SqlDataReader Rs1 = MyCommand.ExecuteReader();
        while (Rs1.Read()) {
            BookMarkList.Add(Convert.ToString(Rs1.GetInt32(0)) +
                                    Splitchr + Rs1.GetString(1).Trim() + 
                                    Splitchr + Rs1.GetString(2).Trim()); } }
    catch (Exception exc) {
        throw exc; }
    finally {
        Conn1.Close(); Conn1.Dispose(); Conn1 = null; 
        MyCommand.Dispose(); MyCommand = null;
    }

    return BookMarkList;
}

I researched and found this code. There is no way I would know about it if I didn't Google for it. These are the main things that I admire the most when I find solutions for. This code deletes the history file for Internet Explorer.

public void DeleteIEHistory()
{
    string[] theFiles = Directory.GetFiles(
       Environment.GetFolderPath(Environment.SpecialFolder.History),
       "*", SearchOption.AllDirectories);
    foreach (string DelThis in theFiles)
    {
        try { File.Delete(DelThis); }
        catch
        {
            // Do Nothing 
        }
    }
}

I have used two timer controls for this program. One to countdown the alarm, and another to refresh the web page. There are some other options to create my own classes and to use The "Timer" .NET class instead of using controls, but I got lazy. Here is one of them.

#region Alarm / Countdaown stuff // ***************************************

private void tmrCountDown_Tick(object sender, EventArgs e)
// Alarm timer count down
{
    // This is the code counts the time until is up and flashes the frame
    // after that until it is stopped by the 'button' or 'cancel menu item'.
    if (TickCount > 0) {
        TickCount -= 1; }
    else {
        btnStopAlarm.Visible = true;
        if (FlashingRed == true) {
            FlashingRed = false;
            pnlColor.BackColor = Color.White; }
        else {
            FlashingRed = true;
            pnlColor.BackColor = Color.Red; }
    }
}

private void btnStopAlarm_Click(object sender, EventArgs e)
{
    StopCancelAlarm(); // Stop 'flashing frame' and stop the timer
}

private void StartCountDown(int AddingTime)
{
    // Set some variables before start the timer
    ClearAlarmCheckBoxes();
    TickCount = AddingTime;
    btnStopAlarm.Visible = false;
    pnlColor.BackColor = Color.Green;
    tmrCountDown.Start();
}

........

private void StopCancelAlarm()
{
    // Stop the timer and set the
    // variables back to defaults
    ClearAlarmCheckBoxes();
    pnlColor.BackColor = Color.LightGray;
    btnStopAlarm.Visible = false;
    FlashingRed = true;
    tmrCountDown.Stop();
    tmrCountDown.Dispose();
}
#endregion

I also use my own commented separators to follow my code easier. "#region" helps me a lot if I need to hide some code during painful debugging. I know I did duplicate my tips from the previous article, but I felt it's important for you to know "#region" is available :).

Points of Interest

This code is for C# beginners. I do research a lot to learn a lot. As much as you can, please use any code I post here. I would also like to see your work. If you are interested in doing some enhancements, I would owe you a lot for teaching me how to fish better ;)

(By the way, my code has some stuff missing, such as error handlers. I will fix all the handlers later on. Although I am using exceptions, I am not taking care of them. There are some other stuff that I probably didn't mention here such as how to delete bookmarks, where to click for the blackouts... So, they might be good study material for you as well :)

********* Additional Features *********

I think I owe an apology to those who came here to see some code from the "WebBrowser" tool provided with .NET. I did use that tool in my code for the browser:

webbrowser.jpg

The WebBrowser tool is a very easy to use component that is pretty much self-explanatory. I will list a few lines of code here so you don't have to download the whole code if you don't want to.

The _DocumentCompleted method of the Web Browser only fires after downloading of the page is done. I added a few things, such as setting the "browse back" button, the "browse forward" button, the "loading" indicator etc. You also could see the Web1.CanGoBack, Web1.CanGoForward, and Web1.Url properties used here and in other places.

private void Web1_DocumentCompleted(object sender, 
             WebBrowserDocumentCompletedEventArgs e)
{
    // Set some variables here at the end
    // of DocumentComplete (End of webpage load)
    txtURL.Text = Web1.Url.ToString();
    TSBack.Enabled = Web1.CanGoBack;
    TSForward.Enabled = Web1.CanGoForward;
    TSLoading.ForeColor = Color.Green;
    TSLoading.Text = "Ready...";
}

The following code shows a method called when the browser starts navigating out of the current page. This method also sets the "busy" indicator.

private void Web1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
    // Show 'red text' while page busy and loading items
    TSLoading.ForeColor = Color.Red;
    TSLoading.Text = "Busy...";
}

Web1.Navigate(HomePageURL);: The web browser's URL is set with this code. You can use this line anywhere you need to change the page. In this sample, 'HomePageURL' is the variable which gets its value from the SQL server.

Web1.Refresh(): this just refreshes the current page on the web browser.

As you can see, not much going on with the Browser portion of the code. My goal is to learn and share other components that will be more useful for our programs, such as databases. The WebBrowser portion was the fun part of my application that gave me an excuse to create this application with SQL Express. In my previous article, I created an XML based database, but the application wasn't that attractive at all. I will make sure to name my articles properly next time.

Changes

New version uploaded on 4/25/2010. Many bugs fixed. There is also a NEW video clip showing WebPlus in action.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here