0

This is example of what I'm trying to display with the label: It's not accurate yet, it should be line under line each start at the same location.

and the data should be in red the text should be in green.

information

First the red Download Progress: should not be displayed at all.

then the rest are line under line but it's all in red. the text Size: should be in green the 1.211 MB in red the text Downloaded: in green and 0.727 MB in red Images Left: green 4 red Speed: green 1.79 MB/s red

I tried to create a module class for that:

using System;
using System.Text;

public static class DownloadProgressFormatter
{
    public static string FormatDownloadProgress(double totalMBs, double downloadedMBs, int imagesLeft, double speed)
    {
        StringBuilder progressBuilder = new StringBuilder();

        Console.ForegroundColor = ConsoleColor.Green;
        progressBuilder.AppendLine("Download Progress:");
        Console.ForegroundColor = ConsoleColor.Red;
        progressBuilder.AppendLine($"   Size: {totalMBs} MB");
        progressBuilder.AppendLine($"   Downloaded: {downloadedMBs} MB");
        Console.ForegroundColor = ConsoleColor.Green;
        progressBuilder.AppendLine($"   Images Left: {imagesLeft}");
        Console.ForegroundColor = ConsoleColor.Red;
        progressBuilder.AppendLine($"   Speed: {speed} MB/s");

        Console.ResetColor();

        return progressBuilder.ToString();
    }
}

then using it in form1:

private async Task DownloadImages(List<string> links)
        {
            int totalLinks = links.Count;
            int downloadedCount = 0;

            for (int i = 0; i < links.Count; i++)
            {
                string link = links[i];
                using (var client = new WebClient())
                {
                    client.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36");

                    Stopwatch sw = Stopwatch.StartNew();
                    byte[] data = await client.DownloadDataTaskAsync(link);
                    sw.Stop();

                    string outputFolder = Properties.Settings.Default.SatelliteFolder;
                    string extension = ".png";
                    string filename = $"Satellite_{(i + 1).ToString("000")}{extension}";
                    string fullPath = Path.Combine(outputFolder, filename);

                    // Write the bytes to a file
                    using (FileStream stream = new FileStream(fullPath, FileMode.Create))
                    {
                        await stream.WriteAsync(data, 0, data.Length);
                    }

                    downloadedCount++;

                    // Calculate download progress information
                    int imagesLeft = totalLinks - downloadedCount;
                    double totalMBs = Math.Round((double)totalLinks * data.Length / 1024.0 / 1024.0, 3);
                    double downloadedMBs = Math.Round((double)downloadedCount * data.Length / 1024.0 / 1024.0, 3);
                    double speed = Math.Round((double)data.Length / 1024.0 / 1024.0 / sw.Elapsed.TotalSeconds, 3);

                    string progress = DownloadProgressFormatter.FormatDownloadProgress(totalMBs, downloadedMBs, imagesLeft, speed);
                    lblDownloadProgress.Text = progress;
                    lblDownloadProgress.Font = new Font(lblDownloadProgress.Font, FontStyle.Bold);

                    // Update progress bar
                    progressBar1.Value = (int)((double)downloadedCount / totalLinks * 100);

                    // Load the image from memory
                    Image image;
                    using (MemoryStream ms = new MemoryStream(data))
                    {
                        image = Image.FromStream(ms);
                    }

                    // Add the image to the downloadImages list
                    downloadedImages.Add(image);

                    // Update the picture box with the latest image
                    pictureBox1.Image = image;
                    pictureBox1.Refresh();

                    await Task.Delay(100);
                }
            }

            // Start the timer to display the downloaded images
            timer1.Enabled = true;
        }

the part:

// Calculate download progress information
                    int imagesLeft = totalLinks - downloadedCount;
                    double totalMBs = Math.Round((double)totalLinks * data.Length / 1024.0 / 1024.0, 3);
                    double downloadedMBs = Math.Round((double)downloadedCount * data.Length / 1024.0 / 1024.0, 3);
                    double speed = Math.Round((double)data.Length / 1024.0 / 1024.0 / sw.Elapsed.TotalSeconds, 3);

                    string progress = DownloadProgressFormatter.FormatDownloadProgress(totalMBs, downloadedMBs, imagesLeft, speed);
                    lblDownloadProgress.Text = progress;
                    lblDownloadProgress.Font = new Font(lblDownloadProgress.Font, FontStyle.Bold);

but it's all in red. the text for each property should be in green.

the label that displays the information is lblDownloadProgress

Benzi Avrumi
  • 937
  • 1
  • 8
  • 24
  • Surely, StringBuilder cannot process console colours as all it returns is a string – Peter Smith Aug 14 '23 at 11:58
  • A Label cannot have text with different colors, unless you paint that text on its surface. You may want to use a RichTextBox instead -- Why on earth do you have `Console.ForegroundColor` & Co. there? Did you copy this code from somewhere else? -- You should (really) dump WebClient and replace it with HttpClient (ASAP) – Jimi Aug 14 '23 at 12:03

1 Answers1

1

As was already mentioned in the comments, the Label control cannot have a text with different colors unless it is a custom implementation.

You might want to consider FlowLayoutPanel or TableLayoutPanel as an alternative. Below is an example of FlowLayoutPanel. Every line in this example consists of two controls of type Label. The line breaks are added programmatically. Find the comments below.

using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var flp = new FlowLayoutPanel
            {
                Width = 400,
                Height = 200,
                Location = new Point(10, 10)
            };
            Controls.Add(flp);

            // Put the labels to the dictionary for better processing.
            var labels = new Dictionary<string, string>
            {
                { "Size:", "1.211 MB" },
                { "Downloaded:", "0.727 MB" },
                { "Images left:", "4" },
                { "Speed:", "1.79 MB/s" },
            };

            // Go through each label
            foreach (var line in labels)
            {
                // Each line consists of two labels: Text + Value
                // Each label has its own color.
                flp.Controls.Add(new Label() { Text = line.Key, ForeColor = Color.Green });
                flp.Controls.Add(new Label() { Text = line.Value, ForeColor = Color.Red });

                // Break after each line
                flp.SetFlowBreak(flp.Controls[flp.Controls.Count - 1], true);
            }
        }
    }
}

It gives the following output:

enter image description here

Sergey
  • 581
  • 1
  • 5
  • 12
  • I created a UserControl and it's working fine and when dragging it to form1 designer it's working fine but still one problem. when dragging the usercontrol over a groupbox control i have in form1 the new usercontrol size change automatically. if i drag it then away from the groupbox area it back to it's original size. any idea why when the usercontrol is over the groupbox it's size changing ? it's getting much bigger. – Benzi Avrumi Aug 14 '23 at 23:59
  • @BenziAvrumi it is quite difficult to answer your question without seeing the code. I was not able to reproduce such a behavior in VS2022. I would only recommend to check the code of your user control, maybe you do something with the size dynamically. – Sergey Aug 15 '23 at 08:36
  • and how can I access the variables from the usercontrol and use them in form1 ? after i dragged the usercontrol to form1 designer how can I update each label text with the data in form1? for example the Size in the user control by defaule the value is 1.211 MB but if i want to update the 1.211 MB the size in runtime while downloading and update the label value ? here is a link for both the usercontrol code and the form1 code: https://pastebin.com/9Deft9TZ – Benzi Avrumi Aug 16 '23 at 00:15
  • here is a link for the form1 code and the usercontrol code I want that when I drag the usercontrol to form1 to be able to update the labels values in the usercontrol through the form1 inside the method DownloadImages at this part // Calculate download progress information pastebin.com/9Deft9TZ – Benzi Avrumi Aug 16 '23 at 00:17
  • I solved the first problem I had to set in the Usercontrol designer the property AutoScaleMode to None but now how to update the labels values and maybe also the text through the form1 ? – Benzi Avrumi Aug 16 '23 at 00:31
  • 1
    @BenziAvrumi This problem is usually solved by adding custom public properties to your user control. In your case you will have 4 public properties, including DownloadSize, Downloaded, ImagesLeft and Speed. For example, `public string DownloadSize { get { return labelDownloadSize.Text; } set { labelDownloadSize.Text = value} }`, etc. See [here](https://stackoverflow.com/questions/2081953/user-control-custom-properties) for example. – Sergey Aug 16 '23 at 10:38
  • 1
    @BenziAvrumi Alternatively, you could make all your labels in the user control publicly visibly. To do so, open your user control in the Designer, select any label, go to the Properties dialog, find the property 'Modifiers' and change from 'Private' to 'Public'. Then you will be able to access your labels from your main from. – Sergey Aug 16 '23 at 10:42