0

I am trying to make a color changing mehapps metroui progress bar based on the percentage of the file that is downloaded. In lua I do like so:

ARGB(255, 255 * percent, 255 - (255 * percent), 0)

Now in trying to do this in C#:

void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    double bytesIn = double.Parse(e.BytesReceived.ToString());
    double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
    double percentage = bytesIn / totalBytes * 100;
    label2.Content = "Downloaded " + (e.BytesReceived / 1000) + "kb" + " of " + (e.TotalBytesToReceive / 1000) + "kb" + " (" + Math.Round(percentage) + "%)";
    progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
    Color myColor = Color.FromArgb(255, 255 * (Math.Round(percentage)), 255 - (255 * (Math.Round(percentage))), 0);
    string hex = myColor.R.ToString("X2") + myColor.G.ToString("X2") + myColor.B.ToString("X2");
    Console.WriteLine(hex);
}

The label2 works great but the mycolor line errors out with:

Cannot convert from double to byte.

I even tried using progressBar1.Value and get the same error. What am I doing wrong? Is there an easier way to just make my progress bar go from red to green based on percentage downloaded?

Sam
  • 7,252
  • 16
  • 46
  • 65
loveroflua
  • 35
  • 5

3 Answers3

4

This whole thing can be much simpler.

void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    label2.Content = string.Format("Downloaded {0}kb of {1}kb ({2}%)", e.BytesReceived / 1000, e.TotalBytesToReceive / 1000, e.ProgressPercentage);
    progressBar1.Value = e.ProgressPercentage;
    int c = e.ProgressPercentage * 255 / 100;
    // unused, but this would be how you'd get it
    // Color myColor = Color.FromArgb(255, (byte)(255 - c), (byte)c, 0);
    string hex = string.Format("FF{0:X2}{1:X2}00", 255 - c, c);
    Console.WriteLine(hex);
}

What I've done here:

  • use e.ProgressPercentage in most places.
  • avoid doubles entirely by scaling the colour as an integer (avoiding Round all over the place). Note the order of the multiplication and the division.
  • used string.Format
  • cast to byte, avoid Convert

By the way, this interpolates between red and green linearly, meaning it goes through murky dark yellow in the middle, instead of actual yellow. In order to go through yellow, you could use something like

int s = e.ProgressPercentage * 255 / 50;
int r = Math.Min(255, 510 - s);
int g = Math.Min(255, s);

Then proceed in the obvious way.

edit: swapped red/green as resquested.

harold
  • 61,398
  • 6
  • 86
  • 164
  • This is totally simpler and easy to understand. – J3soon Dec 28 '15 at 13:40
  • 1
    Og course, with C# 6 (which everyone should be using, as it's so much better than previous versions ;), the 1`string.Format` line can be changed to `string hex = $"FF{c:X2}{255-c:X2}00";` – David Arno Dec 28 '15 at 13:44
  • Ok i tried for an hour to figure out how to do this on my own but I cant and im sure its simple, what you posted works great except it goes from green to red and I need it to go from red to green, how can I invert it? – loveroflua Dec 28 '15 at 15:14
  • @loveroflua didn't your original code do that as well? I tried to make it the same. Anyway just swap the red and green then, no big deal. I'll edit it in though. – harold Dec 28 '15 at 16:39
0

Change the problematic line to

Color myColor = Color.FromArgb(255, Convert.ToByte(255 * Math.Round(percentage/100)), 255 - Convert.ToByte(255 * (Math.Round(percentage/100))), 0);

You have to divide percentage by 100 in order to get value from 0 to 1 and then cast the result to byte, since method Color.FromArg() expects byte parameters.

Marko Juvančič
  • 5,792
  • 1
  • 25
  • 41
0

Change this line

Color myColor = Color.FromArgb(255, 255 * (Math.Round(percentage)), 255 - (255 * (Math.Round(percentage))), 0);

To

Color myColor = Color.FromArgb(255, 255 * (Math.Round(percentage / 100)), 255 - (255 * (Math.Round(percentage / 100))), 0);
J3soon
  • 3,013
  • 2
  • 29
  • 49