1

I'm displaying hex data in a Rich Text Box, that looks like this:

64 73 67 66 34 33 74 67 35 34 36 79 37 35 79 36
33 67 35 36 67 35 36 33 79 68 34 36 37 38 72 74

and I want it to be displayed with every 3 characters being a different colour. i.e. each bit (2 numbers and a space to be specific) being a different colour.

What I've tried to do is simply set the text colour to blue in designer mode, in order to halve the processing time. Then I'll just change every 2nd 3 characters to red.

However, this is what's happening:

http://i.imgur.com/ZzDtO.png

Here is the code:

for (int i = 0; i < richTextBox1.TextLength; i++)
    if (i % 4 == 1)
    {
        richTextBox1.SelectionStart = i;
        richTextBox1.SelectionLength = 2;
        richTextBox1.SelectionColor = Color.Red;
    }

It's apparent my math is wrong, I just can't think of anything that will work. I've tried i % 3 = 0, selectionLength = 3, and many others.

P.S. If this will be slow, can you suggest any other methods of doing it? here is the full code if you want to see it: http://pastebin.com/vHMfnZW1

Anteara
  • 729
  • 3
  • 14
  • 33
  • Its doing exactly what Id expect if you set it to do characters 2&3.. hence 2nd one is 4 and the space is 3 :) surely you wanted 4&5 out of 6? – BugFinder Sep 12 '12 at 07:58
  • yeah, as I said I couldn't figure out what math I would need to use to achieve the outcome I'm looking for >_< Would you have any idea about what math would be required to do this? I don't understand what you mean by 4&5 out of 6. This is essentially what I want it to look like: http://i.imgur.com/S82xF.png But here it is gray and blue instead of red and blue. – Anteara Sep 12 '12 at 08:10

4 Answers4

2

I'm not sure I got what you are trying to do (I'm not able to see the images), anyway I'd do it this way:

        for (int i = 3; i < richTextBox1.TextLength; i += 6)
        {
            richTextBox1.SelectionStart = i;
            richTextBox1.SelectionLength = 2;
            richTextBox1.SelectionColor = Color.Red;
        }

EDIT according to your comment.

This is you due to the fact that changing the selection is a slow operation. Things can get better operating on strings and taking advantage that you can set the Rtf property of a RichTextBox. You can inspect the Rtf property of your control after the slow loop to get an idea of what you have to build, it is a string composed by a part defining the fonts and colors used, the actual text, and a simple closing part.

In particular to use blue and red you define this "colour table" {\\colortbl ;\\red0\\green0\\blue255;\\red255\\green0\\blue0;} and then use the codes \\cf1 and \\cf2 for specifying blue and red, respectively.

This code should be much faster:

        StringBuilder sb = new StringBuilder();
        sb.Append("{\\rtf1\\ansi\\ansicpg1250\\deff0\\deflang1050{\\fonttbl{\\f0\\fnil\\fcharset238 Microsoft Sans Serif;}}\r\n{\\colortbl ;\\red0\\green0\\blue255;\\red255\\green0\\blue0;}\r\n\\viewkind4\\uc1\\pard\\f0\\fs17");
        string[] col = new string[] { "\\cf1 ", "\\cf2 " };
        int idxCol = 0;
        for (int i = 0; i < myText.Length; i++)
        {
            if (i % 3 == 0)
            {
                sb.Append(col[idxCol]);
                idxCol = (idxCol + 1) % 2;
            }
            sb.Append(myText[i]);
        }
        sb.Append("\\par\r\n}\r\n");

        richTextBox1.Rtf = sb.ToString();

Please note that I do not know RTF syntax deeply, just the colour part because it's been useful to me in the past. I consider the first and the last part as constant. As you can see the colours are defined as RGB and referenced by the constant string "\cf" followed by the index in the colour table (1 based).

You can find the full specification here and something much simpler but that I found useful here.

Francesco Baruchelli
  • 7,320
  • 2
  • 32
  • 40
  • This also works, thanks, all the methods that I've tried to use though are really show, which sucks. Since I'll need to parse 1mb + files. Any ideas of how I could do this fast? – Anteara Sep 12 '12 at 08:55
  • Wow Francesco, that's brilliant; it's blazing fast. Might I please ask you, if you have any msdn or learning references to what you did; I'd like to learn that as it will probably be helpful for me in other projects too. Specifically in regards to the "colour table", or what you're appending to the string builder. Thanks :D EDIT: Oh, damn. :/ It looks like it's actually not able to parse 1mb+ files either. Visual Studio states `ContextSwitchDeadlock was detected` which I assume is essentially a time out. It is much faster for small filesizes though, but it's not performing well for large :( – Anteara Sep 12 '12 at 14:16
  • Look to the edit for references. For the size I do not know, I never had to deal with the visualization of such an amount of data :-(. But did the slow approaches work? – Francesco Baruchelli Sep 12 '12 at 14:38
  • They all appear to work, however they're slow, and without adding another thread for them the program just can't operate. Even if I did add another thread it would still be over 60 seconds before the data displays. The annoying thing is that when I convert my byte array to a string, and then display my string in the RichTextBox, it's instant; regardless of how long the string is. – Anteara Sep 12 '12 at 14:51
  • Maybe this is something similar to [this](http://stackoverflow.com/questions/8106159/net-contextswitchdeadlock-was-detected) – Francesco Baruchelli Sep 12 '12 at 16:26
  • Well I could put it in a seperate thread, etc, but it's really only putting a bandaid on the problem. it will still take a long time to execute. – Anteara Sep 12 '12 at 21:45
0

Something like this?

for (int i = 0; i < richTextBox1.TextLength; i++)
    var oldStart = richTextBox1.SelectionStart;
    var oldLength = richTextBox1.SelectionLength;
    if (richTextBox1.Text[i-1] == ' ')
    {

        richTextBox1.Select(i);
        richTextBox1.SelectionColor = Color.Red;
    }
    // Restore selection
    richTextBox1.Select(oldStart, oldLength);
}
Andreas
  • 1,421
  • 3
  • 16
  • 32
  • it looks like what I want it to do, but because the first time it loops through it will crash because i-1 is outside the bounds of the array initially... i think. Also, `richTextBox`.Select(i) produces error: `Error 2 'System.Windows.Forms.RichTextBox' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'System.Windows.Forms.RichTextBox' could be found (are you missing a using directive or an assembly reference?` – Anteara Sep 12 '12 at 08:21
0

I was able to figure this out by doing this:

for (int i = 0; i < richTextBox1.TextLength; i++)
{
    if (richTextBox1.Text[i] == ' ')
    {
        if (colourIt == true)
        {
            richTextBox1.SelectionStart = i;
            richTextBox1.SelectionLength = 3;
            richTextBox1.SelectionColor = Color.Red;
            colourIt = false;
        }
        else colourIt = true;

    }
}

Thanks for the help :)

Anteara
  • 729
  • 3
  • 14
  • 33
  • If you wanted all visible characters to be red, why not just highlight the whole thing? After all, spaces have no colour. I thought you were trying to alternate colours of pairs of characters – BugFinder Sep 12 '12 at 08:30
  • That's what I am trying to do, and that's what this does. The first byte is red and the next is blue, etc. – Anteara Sep 12 '12 at 08:51
  • By checking for a space and colouring the next 3, you are always coloring the space, and the next 2 characters, so in effect all of it is red.. Not alternating.. – BugFinder Sep 12 '12 at 10:25
  • What Francesco said... the boolean colourIt essentially creates a switch which alternates the colours. If there is a space, then it colours the next 3 characters. but on the NEXT space, since colourIt is FALSE, ALL it does is set it to true. It doesn't do any colouring, it just changes the value of the boolean. I don't understand why you guys think this makes ALL of the text red... it successfully alternates.. :/ – Anteara Sep 12 '12 at 14:11
0

I'm not sure what you're trying to achieve. But maybe this will help:

    for (int i = 0; i < richTextBox1.TextLength; i++)
        if (i % 6 == 2)
        {
            richTextBox1.SelectionStart = i - 2;
            richTextBox1.SelectionLength = 3;
            richTextBox1.SelectionColor = Color.Red;
        }
Zen
  • 244
  • 1
  • 3
  • 15