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 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 "case
s" 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;
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)
{
CommaCheck(BookMarkName); Conn1 = new SqlConnection(connStr);
SqlCommand MyCommand = Conn1.CreateCommand(); 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()
{
Conn1 = new SqlConnection(connStr);
SqlCommand MyCommand = Conn1.CreateCommand();
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)
{
int ConvertID;
ConvertID = Convert.ToInt32(BookMarkID);
Conn1 = new SqlConnection(connStr);
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)
{
List<string> BookMarkList = new List<string>();
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; 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
{
}
}
}
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)
{
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(); }
private void StartCountDown(int AddingTime)
{
ClearAlarmCheckBoxes();
TickCount = AddingTime;
btnStopAlarm.Visible = false;
pnlColor.BackColor = Color.Green;
tmrCountDown.Start();
}
........
private void StopCancelAlarm()
{
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:
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)
{
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)
{
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.