Pages

Ads 468x60px

Thursday, August 16, 2012

ProgressBar not Updating Fix - C#

It has been sited by many StackOverflow questions that, usually when using a BackgroundWorker, your ProgressBar will not update correctly when using C#. I do not know why this happens, however some people suggest that it is because of the threaded interface in Windows Vista and Windows 7.The ProgressBar would get to about 75% full when it should have been at its maximum, and would revert back to 0% before it was fully drawn. Here is what that looked like:

And this is the example code I used:
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; (i <= 100); i++)
            {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(20);
                    backgroundWorker1.ReportProgress((i ));
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            if (progressBar1.Maximum == e.ProgressPercentage)
                progressBar1.Value = 0;
        }

However, Mark Lansdown from StackOverflow found a very useful solution, taken from this question.

What he suggested is to draw the value, then draw the value minus 1, because that would force a redraw on the ProgressBar. To to that, I just changed my ProgressChanged event to:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            if (e.ProgressPercentage != 0)
                progressBar1.Value = e.ProgressPercentage - 1;
            progressBar1.Value = e.ProgressPercentage;
            if (progressBar1.Maximum == e.ProgressPercentage)
                progressBar1.Value = 0;
        }

And the result is that the ProgressBar will now be smoothly redrawn to 100% before it is reverted.

And while this is most certainly strange behavior, I can verify that it works, and now the ProgressBar will fill all the way up.

I hope you enjoyed!

Center A Form to another form in C#

Recently, while I was using C#, I had an issue. I wanted to center a form in the middle of another form. After drawing a chart and doing some math, I have come up with this piece of code:

form2.SetDesktopLocation(form1.Location.X + ((form1.Width / 2) - form2.Width / 2), form1.Location.Y + ((form1.Height / 2) - form2.Height / 2));
What this code actually does, is it first gets the location of form1 X. It then adds that to form1 Width / 2, and subtracts that from form2's width / 2, and does the same for Y. It does that, because you get the X position, and that position needs to be in the center of form1's width. Then, you need to factor in half of form2's width per side, because form1's width was divided by 2. Don't worry if you do not understand. This code assumes the form you want to center is form2, and the form you want to center it around is form1. You have to create a variable for the current instance of form1 and form2. Here is an example of that:

Form1 form1 = (Form1)Application.OpenForms[0];
What this code does, is it gets a current array of the open forms. If form2 is your child form, and form 1 is your main form, form1 would be position [0] and form2 would be position [1].

Here is a picture of this:



I hope it helps!

Sunday, August 12, 2012

How to access Opera History in C#

Hi all! Today, I will be continuing my series on getting browser history in C#. I am going to focus on Opera today. Opera is different from Chrome and Firefox, in the fact that it does not use an SQLite Database to store browser history. Instead, it uses a text file. Each URL entry has four lines. The first line is the title, the second is the URL, the third is the time visited in Unix, or Epoch, time, and the last is the frequency. You can find this file in your appdata folder, by typing %appdata% into run, then browsing to Opera/Opera/global_history.dat and opening it with a text editor, such as NotePad++. Here is an example of my file:

The default frequency, for a site that has been visited one time, is -1. If it has been visited more than once, it will rise up into the millions. I am not sure how the frequency corresponds to the number of visits. If you know, please tell me.





To access this in C#, you will need to read the file line by line, and determine if the line is the title, url, etc. I have come up with this code that should help you:
 public IEnumerable GetHistory(bool display)
 {
  // Get Current Users App Data
  string documentsFolder = GetFolder();
  //If directory exists
  if (Directory.Exists(documentsFolder))
  {
   //This is the line number of the history file
   int lineNumber = 1;
   //This is the history file in the documents folder
   string historyFile = documentsFolder + "global_history.dat";
   //URL Variables
   string title = null;
   string url = null;
   int frequency = 0;
   DateTime visited = new DateTime();
   //These variables tell you if each line has been parsed
   //and each part has been assigned
   bool urlAssigned = false;
   bool titleAssigned = false;
   bool frequencyAssigned = false;
   bool visitedAssigned = false;
   //The url to assign to the URL table
   URL u;
   //Create a new StreamReader using the history file
   //to read the file line by line
   System.IO.StreamReader file =
 new System.IO.StreamReader(historyFile);
   //The line that is being read
   string line;
   //While the line that is being read is being read by
   //file.ReadLine, and is not null
   while ((line = file.ReadLine()) != null)
   {
    /*This is a table of what each line is
     * Line 1 = The Title of the URL
     * Line 2 = The URL of the URL
     * Line 3 = The Unix Time of which the URL was visited
     * Line 4 = The frequency of visits, which cannot convert 
     */
    //If the line number is the first, or if the line number minus 1
    //is a multiple of 4, for example, line number 5 - 1 is 4, which 
    //is a multiple of 4
    if (lineNumber == 1 || (lineNumber - 1) % 4 == 0)
    {
     Debug.WriteLine(line);
     title = line;
     titleAssigned = true;
    }
    //If line number is the second, or line number - 2 is a multiple
    //of 4, ex. 6 - 2 = 4, which is a multiple of 4
    if (lineNumber == 2 || (lineNumber - 2) % 4 == 0)
    {
     url = line;
     urlAssigned = true;
    }
    //If the line number is the third, or if line number - 3 is a
    //multiple of 4, ex. 7 - 3 = 4
    if (lineNumber == 3 || (lineNumber - 3) % 4 == 0)
    {
     //If the line is the correct length for Unix time
     if (line.Length == 10)
     {
      //then convert the number to a local datetime
      visited = FromUnixTime(Int64.Parse(line)).ToLocalTime();
     }
     else
      MessageBox.Show("An error occured while parsing the date \n" + line);
     visitedAssigned = true;
     frequencyAssigned = true;
    }
    //If all of the values have been assigned
    if (urlAssigned == true && titleAssigned == true 
&& frequencyAssigned == true && visitedAssigned == true)
    {
     //create a new URL with the values
     u = new URL(url, title, "Opera", visited, frequency);
     //And add the URL to the URLs array
     URLs.Add(u);
     //Reset the assigned values
     urlAssigned = false;
     titleAssigned = false;
     frequencyAssigned = false;
     visitedAssigned = false;

    }

    if (lineNumber == 4000 || file.EndOfStream == true)
    {
     MessageBox.Show("done " + URLs.Count.ToString());
    }
    
    lineNumber++;
   }

  }
  return URLs;
 }

 private static string GetFolder()
 {
  string folder = "\\Opera\\Opera\\";
  string documentsFolder = Environment.GetFolderPath
      (Environment.SpecialFolder.ApplicationData);
  documentsFolder += folder;
  return documentsFolder;
 }
 public DateTime FromUnixTime(long unixTime)
 {
  var epoch = new DateTime(1970, 1, 1, 0, 0, 0);
  return epoch.AddSeconds(unixTime);
 }
Note: To use this, you will need to include:
using System.Diagnostics;
using System.IO;

This script also reuses the URL class from my post on IE history. I have commented on most parts of this, so it should be easy to understand. This is the underlying method on how to get Opera's history with C#.

If you have any more questions or comments, please let me know!