1

I'm creating a log reader that will be Color Blind Friendly that will parse a log file (text file) with the default color of blue. When a line contains "ERROR:" it should set the color to Orange. Sounds simple enough but the code I whipped up does not seem to detect that the line contains "ERROR:" in it. Here is my code:

        // Network Log
        string errorText1 = " ERROR: ";
        var i1 = 0;
        // From Bottom To Top
        var lines1 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\network.log").Reverse().Skip(1);

        foreach (string line1 in lines1)
        {
            // Catch ERROR: And Color Orange Else Blue
            if (line1.Contains(errorText1))
            {
                listBox1.ForeColor = Color.FromArgb(230, 159, 0);
                this.listBox1.Items.Add(line1);
            }
            else
            {
                listBox1.ForeColor = Color.FromArgb(0, 114, 178);
                this.listBox1.Items.Add(line1);
            }
            i1++;
            if (i1 >= logLength) break;
        }

Thanks for any help on this..

Example of a Log line with an Error:

I20160128:051414 ERROR: [network]: Error connecting to: weather-station.org:24556

Orel Eraki got me on the right path it looks like but I'm not sure why he used a Class or Namespace to handle the line to be printed. There would be nothing to put in the Class. So I tried the follow since this is part of the Form_Load Class:

        // Network Log
        string errorText1 = " ERROR: ";
        var i1 = 0;
        // From Bottom To Top
        var lines1 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\network.log").Reverse().Skip(1);

        foreach (string line1 in lines1)
        {
            var color = Color.FromArgb(0, 114, 178); // Blue
            if (line1.Contains(errorText1))
            {
                color = Color.FromArgb(230, 159, 0); // Orange
            }
            this.listBox1.ForeColor = color; // Apply Color
            this.listBox1.Items.Add(line1);

            i1++;
            if (i1 >= logLength) break;
        }

However this did not work either.. :(

Again thanks for brainstorming and for any help to resolve this issue.

UPDATE FULL CODE AS FOLLOWS:

Original:

using System;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace WWIV5TelnetServer
{
    public partial class LogForm : Form
    {
        public LogForm()
        {
            InitializeComponent();
        }

        private void LogForm_Load(object sender, EventArgs e)
        {
            // Default Number Of Lines Per Log
            int logLength  = Int32.Parse(logLines.Text);

            // Network Log
            string errorText1 = " ERROR: ";
            var i1 = 0;
            // From Bottom To Top
            var lines1 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\network.log").Reverse().Skip(1);

            foreach (string line1 in lines1)
            {
                // Catch ERROR: And Color Orange Else Blue
                if (line1.Contains(errorText1))
                {
                    listBox1.ForeColor = Color.FromArgb(230, 159, 0);
                    this.listBox1.Items.Add(line1);
                }
                else
                {
                    listBox1.ForeColor = Color.FromArgb(0, 114, 178);
                    this.listBox1.Items.Add(line1);
                }
                i1++;
                if (i1 >= logLength) break;
            }

            // Networkb Log
            string errorText2 = " ERROR: ";
            var i2 = 0;
            // From Bottom To Top
            var lines2 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\networkb.log").Reverse().Skip(1);

            foreach (string line2 in lines2)
            {
                this.listBox2.Items.Add(line2);
                i1++;
                if (i2 >= logLength) break;
            }

            foreach (string line2 in lines2)
            {
                // Catch ERROR: And Color Orange Else Blue
                if (line2.Contains(errorText2))
                {
                    listBox2.ForeColor = Color.FromArgb(230, 159, 0);
                    this.listBox2.Items.Add(line2);
                }
                else
                {
                    listBox2.ForeColor = Color.FromArgb(0, 114, 178);
                    this.listBox2.Items.Add(line2);
                }
                i2++;
                if (i2 >= logLength) break;
            }

            // Net.log
            string errorText3 = " ERROR: ";
            var i3 = 0;
            // From Bottom To Top
            var lines3 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\gfiles\NET.LOG");

            foreach (string line3 in lines3)
            {
                // Default Color Blue
                listBox3.ForeColor = Color.FromArgb(0, 114, 178);

                // Catch ERROR: And Color Orange Else Blue
                if (line3.Contains(errorText3))
                {
                    listBox3.ForeColor = Color.FromArgb(230, 159, 0);
                }
                this.listBox3.Items.Add(line3);
                i3++;
                if (i3 >= logLength) break;
            }

            // Change Log
            var lines4 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\changelog.txt");

            foreach (string line4 in lines4)
            {
                // Default Color Black
                listBox4.ForeColor = Color.Black;

                this.listBox4.Items.Add(line4);
            }

            // What's New
            var lines5 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\whatsnew.txt");

            foreach (string line5 in lines5)
            {
                // Default Color Black
                listBox5.ForeColor = Color.Black;

                this.listBox5.Items.Add(line5);
            }
        }

        private void exitButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Refresh();
        }
    }
}

Orel's Concept which is no doubt my fault for not showing the entire .cs:

using System;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace WWIV5TelnetServer
{
    public partial class LogForm : Form
    {
        public LogForm()
        {
            InitializeComponent();
        }

        private Brush GetMessageBrush(string message)
        {
            var brush = Brushes.Green; // Default
            if (message.Contains("ERROR:"))
            {
                brush = Brushes.Red;
            }
            return brush;
        }

        private void listBox2_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index > -1)
            {
                string item = listBox2.Items[e.Index].ToString();
                if (item != null)
                {
                    var brush = GetMessageBrush(item);
                    e.Graphics.DrawString(item, e.Font, brush, e.Bounds.X, e.Bounds.Y, StringFormat.GenericDefault);
                }
                e.DrawFocusRectangle();
            }
        }

        private void LogForm_Load(object sender, EventArgs e)
        {
            // Default Number Of Lines Per Log
            int logLength  = Int32.Parse(logLines.Text);

            // Network Log
            string errorText1 = " ERROR: ";
            var i1 = 0;
            // From Bottom To Top
            var lines1 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\network.log").Reverse().Skip(1);

            foreach (string line1 in lines1)
            {
                // Catch ERROR: And Color Orange Else Blue
                if (line1.Contains(errorText1))
                {
                    listBox1.ForeColor = Color.FromArgb(230, 159, 0);
                    this.listBox1.Items.Add(line1);
                }
                else
                {
                    listBox1.ForeColor = Color.FromArgb(0, 114, 178);
                    this.listBox1.Items.Add(line1);
                }
                i1++;
                if (i1 >= logLength) break;
            }

            // Networkb Log
            //string errorText2 = " ERROR: ";
            var i2 = 0;
            // From Bottom To Top
            var lines2 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\networkb.log").Reverse().Skip(1);

            foreach (string line2 in lines2)
            {
                this.listBox2.Items.Add(line2);
                i1++;
                if (i2 >= logLength) break;
            }
            /*foreach (string line2 in lines2)
            {
                var color = Color.FromArgb(0, 114, 178);
                if (line2.Contains(errorText2))
                {
                    color = Color.FromArgb(230, 159, 0);
                }
                this.listBox2.ForeColor = color;
                this.listBox2.Items.Add(line2);

                i2++;
                if (i2 >= logLength) break;
            }
            foreach (string line2 in lines2)
            {
                // Catch ERROR: And Color Orange Else Blue
                if (line2.Contains(errorText2))
                {
                    listBox2.ForeColor = Color.FromArgb(230, 159, 0);
                    this.listBox2.Items.Add(line2);
                }
                else
                {
                    listBox2.ForeColor = Color.FromArgb(0, 114, 178);
                    this.listBox2.Items.Add(line2);
                }
                i2++;
                if (i2 >= logLength) break;
            }*/

            // Net.log
            string errorText3 = " ERROR: ";
            var i3 = 0;
            // From Bottom To Top
            var lines3 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\gfiles\NET.LOG");

            foreach (string line3 in lines3)
            {
                // Default Color Blue
                listBox3.ForeColor = Color.FromArgb(0, 114, 178);

                // Catch ERROR: And Color Orange Else Blue
                if (line3.Contains(errorText3))
                {
                    listBox3.ForeColor = Color.FromArgb(230, 159, 0);
                }
                this.listBox3.Items.Add(line3);
                i3++;
                if (i3 >= logLength) break;
            }

            // Change Log
            var lines4 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\changelog.txt");

            foreach (string line4 in lines4)
            {
                // Default Color Black
                listBox4.ForeColor = Color.Black;

                this.listBox4.Items.Add(line4);
            }

            // What's New
            var lines5 = File.ReadAllLines(Properties.Settings.Default.homeDirectory + @"\whatsnew.txt");

            foreach (string line5 in lines5)
            {
                // Default Color Black
                listBox5.ForeColor = Color.Black;

                this.listBox5.Items.Add(line5);
            }
        }

        private void exitButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Refresh();
        }
    }
}

NOTES: As you can see in the Original I tried a separate case to handle the color coding. Lets just stick to one log so that I can then implement that across all logs that require the color coding. (ie. listBox1)

Hope this helps clears up the mess. It's a shame that the Draw Object isn't easier to implement.

UPDATE: Just trying to use Orel's code in a new project just to test it because it was doing the same trying to implement it into mine, does not color anything. It's all black text.

using System;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

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

        private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index > -1)
            {
                string item = listBox1.Items[e.Index].ToString();
                if (item != null)
                {
                    var brush = GetMessageBrush(item);
                    e.Graphics.DrawString(item, e.Font, brush, e.Bounds.X, e.Bounds.Y, StringFormat.GenericDefault);
                }
                e.DrawFocusRectangle();
            }
        }

        private Brush GetMessageBrush(string message)
        {
            var brush = Brushes.Green; // Default
            if (message.Contains("ERROR:"))
            {
                brush = Brushes.Red;
            }
            return brush;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //string errorText1 = " ERROR: ";
            int logLength = 1000;
            var i1 = 0;
            // From Bottom To Top
            var lines1 = File.ReadAllLines(@"networkb.log").Reverse().Skip(1);

            foreach (string line in lines1)
            {
                this.listBox1.Items.Add(line);
                i1++;
                if (i1 >= logLength) break;
            }
        }
    }
}
  • 1
    Can you provide a sample error line from the file? – Aaron Jan 29 '16 at 19:04
  • It you put a breakpoint in your code is it not going in to the `if` block or is it going in to that block but the item that is added does not have the correct color when everything is done? If it is not going in to the block please grab the value of `line1` and post it as [a edit to your question](http://stackoverflow.com/posts/35092115/edit) Also please update your question's tags with `Winforms` or `WPF`. – Scott Chamberlain Jan 29 '16 at 19:05
  • Possibly because of the spaces in `" ERROR: ";` ? – andeart Jan 29 '16 at 19:06
  • Yes it's a winform and I updated as you requested.. – Gregory Munson Jan 29 '16 at 19:22
  • Still not Solved Completely.. – Gregory Munson Jan 29 '16 at 20:49
  • @andeart I tried that without " ERROR: " and didn't work long before coming here for help.. Thank though... – Gregory Munson Jan 29 '16 at 23:20

1 Answers1

4

The Default draw method doesn't do this for you, you will need to make few adjustment to make it work.

Steps:

  1. Mark your ListBox DrawMode property as OwnerDrawFixed.
  2. Add to the ListBox new DrawItem event and double click it (It will generate the proper event method.
  3. Replace the current event generated code, with the following

DrawItem event handler

private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    if (e.Index > -1)
    {
        string item = listBox1.Items[e.Index].ToString();
        if (item != null)
        {
            var brush = GetMessageBrush(item);
            e.Graphics.DrawString(item, e.Font, brush, e.Bounds.X, e.Bounds.Y, StringFormat.GenericDefault);
        }
        e.DrawFocusRectangle();
    }
}

Also add the following method and custom it as you wish:

private Brush GetMessageBrush(string message)
{
    var brush = Brushes.Green; // Default
    if (message.Contains("ERROR"))
    {
        brush = Brushes.Red;
    }
    return brush;
}

Now your new adding code doesn't need to handle items drawing

foreach (string line in lines1)
{
    this.listBox1.Items.Add(line);
    i1++;
    if (i1 >= logLength) break;
}
Orel Eraki
  • 11,940
  • 3
  • 28
  • 36
  • Note `this.listBox1.Items[i].ForeColor` will only work for WPF, it will not work for Winforms because the `Items` collection on the winforms version is not a strongly typed collection. – Scott Chamberlain Jan 29 '16 at 19:11
  • Also note that you didn't need to add `i`. `i1` was already used as a counter, you could have just said `this.listBox1.Items[i1].ForeColor = color;` – Lews Therin Jan 29 '16 at 19:14
  • @ScottChamberlain, Yup, he didn't mentioned, should i add a Winform version ? – Orel Eraki Jan 29 '16 at 19:18
  • 1
    @Sylverac, Yeah, noticed it afterwards, fixed. – Orel Eraki Jan 29 '16 at 19:22
  • You really should not be using `i1` either, the code only works if `i1` matches `listBox1.Items.Count` at the start of the loop. The correct thing to do is use the `int` that `Add` returns (`i1 = this.listBox1.Items.Add(line1)` ) then get rid of the `i1++` – Scott Chamberlain Jan 29 '16 at 19:50
  • The i1 is for LogLength Termination. Set by the user for the Max Number of Lines to read. – Gregory Munson Jan 29 '16 at 20:01
  • Well this almost solves the problem however again my code is not using a MyListBoxItem Class or Namespace.. – Gregory Munson Jan 29 '16 at 20:31
  • Woah.. Sorry Orel didn't see your new addition.. Allow me to catch up.. Again thanks.. Funny I could have sworn I refreshed this page.. – Gregory Munson Jan 29 '16 at 21:40
  • @GregoryMunson, It helped you ? – Orel Eraki Jan 29 '16 at 21:49
  • I don't think this is going to work unless I post my entire .cs so let me do that.. Give a a few to update my Question with my code Before and my code After using your idea.. It will most likely make more sense to you.. I'm more of a Encryption Coder but a recent user is color blind and I wanted to make the logs easier for them to report problem and to help other users pinpoint errors more easily. I'm one of the WWIV Developers and just recently finished off adding SSH. So let me update my Question with the Entire .cs. – Gregory Munson Jan 29 '16 at 22:15
  • Okay after going bonkers getting back to this. I decided to just make a WinForm with just your code and it doesn't work. All the lines are black and it's not coloring anything. – Gregory Munson Feb 02 '16 at 22:30