Richedit / Custom Control help for final university project

L

Lee

Hi all, I'm trying to programatically change the background color of
lines of text and running into a few difficulties, anyone got any
suggestions?

my relevant code is as follows:

public void colorLines() {
//_Paint = false; //don't want to update while we are doing
this
//loop thru lines like addText() does
//call checkColors(lineNo)
//print line
// _Paint = true; //now we update.
int curChar = 0;
for (int curLine=0; curLine < this.Lines.Length; curLine++)
{
if (this.Lines[curLine].Length > 0)
{
this.Select(curChar, this.Lines[curLine].Length);
this.SelectionBackColor =
checkColorByLine(curLine);
curChar += this.Lines[curLine].Length + 1;
this.SelectionBackColor = Color.Empty;
}
}
}

and

public Color checkColorByLine(int lineNo)
{
//search hash table for line no
//what color should that line no be?
//return LineColor
//System.Console.WriteLine("Checking Line: " + lineNo);
//System.Console.WriteLine("ColorTable Size: " +
colorTable.Count);
foreach (DictionaryEntry de in colorTable)
{
ArrayList tempArray = (ArrayList)de.Value;
for (int x = 0; x < tempArray.Count; x++)
{
if (tempArray[x].Equals(lineNo))
{
return (Color)de.Key;
}
}
}
return Color.Empty;
}

This is all done from within an extended rich text box control

What tends to happen is that more than one line of text gets colored...
I'm fairly sure I've got some broken logic or something, but I've been
staring at this code too long to work out what it is!

Cheers :)

Lee
 
M

Marc Gravell

You are updating SelectionBackColor - but IIRC this is simply the color that
appears (for that control) when you select a block of text with the mouse;
you need to edit the RTF content itself - methinks you need to read up on
RTF codes

Marc
 
M

Marc Gravell

Please ignore this; I may have the wrong end of the RichTextBox stick...

To attempt to salvage some pride (if possible), I will see if I can find the
actual problem...

Marc
 
L

Lee

Well, as is it kind of works, it just has a habbit of selecting the
wrong thing.

(Essentially the code selects a block of text and gives it a back color
as if it were done with the mouse, except this isn't painted so it's
hidden from the user)

RTF codes are no use as it's a little tricker to handle them
dynamically (I'd have to parse each line of text, as in the contents
instead of just the line numbers) and as this is all due in on the
28th, I don't have the time to do that! :blush:

Thanks :)
 
L

Lee

If you manage to find the problem you not only salvage pride but also
gain a mention in my about box and my eternal gratitude ;)

Lee
 
M

Marc Gravell

Well, what exactly are you seeing? I've taken your code, and hacked it using
a round-robin colouring, and all is fine. Unfortunately, your code (alone)
doesn't illustrate the problem, as a: colorTable isn't defined / populated
(hence why I am using a round-robin), and b: you haven't included any sample
text that raises the problem.

I can, however, get some odd results with different line-endings; you code
assumes 1 character only, but you could get a cr-lf pair - and hence you end
up a character out. In terms of "more than 1 line of text gets coloured",
well it is hard to see what you mean without something that actually
illustrates this in progress.

Marc
 
M

Marc Gravell

Also - curChar is only incremented if the line is non-empty - so you will
get one character out-of-sync for every blank line in the text; perhaps this
is the real issue?

Marc
 
L

Lee

I could send you the whole project, but it's a lot.

The basic principle is as follows (sorry if this is too rough)

You type something into a text box
This is sent to a server on a character by character basis
Information is passed to the client telling it the current line we are
working on
this line is locked out from any other edits (i.e. only the person who
has started on this line may add or remove text on it)
This line is colored
The text is added to the second text box on our client
Process repeats.

Below is the entire class file for the control I've been writing (some
of it is a bit of a mess I'm afraid)


---------------------------------------------------------


using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace AffinityGui{

public partial class affinityEditBox : RichTextBox
{
///errors that are likely to show up
///if someone trys to insert a line this may go tits up, I
don't know in what way yet though
///amendum: think inserting a line is fixed.
private int cursorPos;
private Hashtable colorTable = new Hashtable();
private ArrayList lockedLines = new ArrayList();
public static bool _Paint = true;
const short WM_PAINT = 0x00f;
const char BACKSPACE = (char)8;

public affinityEditBox()
{
InitializeComponent();
//this.SetStyle(ControlStyles.DoubleBuffer, true);
}
//check if a line is locked based on line no
public Boolean LineLocked(int lineNo)
{
if (lockedLines.Equals(null))
{
return false;
}
else
{
if(lockedLines.Contains(lineNo)) {
return true;
} else {
return false;
}
}
}
public Color checkColorByLine(int lineNo)
{
//search hash table for line no
//what color should that line no be?
//return LineColor
//System.Console.WriteLine("Checking Line: " + lineNo);
//System.Console.WriteLine("ColorTable Size: " +
colorTable.Count);
foreach (DictionaryEntry de in colorTable)
{
ArrayList tempArray = (ArrayList)de.Value;
for (int x = 0; x < tempArray.Count; x++)
{
if (tempArray[x].Equals(lineNo))
{
Console.WriteLine("LineNo: " + lineNo);
Console.WriteLine("Returning: " + de.Key);
return (Color)de.Key;
}
}
}
return Color.Empty;
}
public void colorLines() {
//_Paint = false; //don't want to update while we are doing
this
//loop thru lines like addText() does
//call checkColors(lineNo)
//print line
// _Paint = true; //now we update.
int curChar = 0;
for (int curLine=0; curLine < this.Lines.Length; curLine++)
{
if (this.Lines[curLine].Length > 0)
{
this.Select(curChar, this.Lines[curLine].Length);
this.SelectionBackColor =
checkColorByLine(curLine);
curChar += this.Lines[curLine].Length + 1;
this.SelectionBackColor = Color.Empty;
}
}
}

public void lockLines(int lineNo)
{
lockedLines.Add(lineNo);
}
public void unLockLines(int lineNo)
{
lockedLines.Remove(lineNo);
}

public void addColorBlock(ArrayList lines, Color color)
{
System.Console.WriteLine("Color: " + color.ToString());
//method to add a set of lines to a color
if (!colorTable.ContainsKey(color))
{
colorTable.Add(color, lines);
//System.Console.WriteLine("****colorTableSize: " +
colorTable.Count);
}
else
{
//do something else
colorTable.Remove(color);
colorTable.Add(color, lines);
}
/**
_Paint = false;
colorLines(); //make sure _Paint is still false while we do
this!
_Paint = true;
**/
}

public ArrayList getColorLinesByKey(Color key)
{
//get the lines that a color owns by it's key (user)
foreach (DictionaryEntry de in colorTable)
{
if (de.Key.Equals(key))
{
return (ArrayList)de.Value;
}
}
return null;
}
public void delText(int startPos, int len)
{
_Paint = false; //don't paint
/*
if (len > 1)
{
startPos -= len;
//startPos--;
}*/
string temp = this.Text.Remove(startPos, len);
this.Text = temp;
_Paint = true;
}

//method for insterting text at arbituary points
public void addText(int lineNo, int stringPos, string text)
//text should really be a chr seeing as we are only dealing with chr by
chr
{
/* lineNo is for selecting the line of text we want to edit
* stringPos is for selecting the position of the string we
want to edit from
* this pretty much a find and replace
*/
cursorPos = this.SelectionStart;
ArrayList tempArl = new ArrayList(this.Lines);
if (lineNo == tempArl.Count)
{
//System.Console.WriteLine("LineNo and text edit are
exactly the same size");
string tempStr = " ";
for (int curPos = 0; curPos < stringPos; curPos++)
{
tempStr += " ";
}
//}
//tempArl.Add(tempStr);
//tempArl.Add(tempStr);

}
else if (lineNo > tempArl.Count)
{
//System.Console.WriteLine("lineNo is bigger than text
edit space");
string tempStr = " ";
int diff = lineNo - tempArl.Count;
//diff += 2;
for (int current = 0; current < diff; current++)
{
//if (current == diff)
//{
for (int curPos = 0; curPos < stringPos;
curPos++)
{
tempStr += " ";
}
//}
tempArl.Add(tempStr);
}
//tempArl.Add(tempStr);

}
// Create a string array and store the contents of the
Lines property.
string[] tempArray = new string[tempArl.Count];
//System.Console.WriteLine("lineNo: " + lineNo);
//System.Console.WriteLine("tempArl: " + tempArl.Count);
tempArray = (string[])tempArl.ToArray(typeof(string));


tempArray[lineNo] = tempArray[lineNo].Insert(stringPos,
text); //ohhh a one liner for inserting strings, score!



//loop through array and whack it into the rich text box
(rtbMain)
_Paint = false;
//this.Clear(); <=--- if we put this line of code in we get
flicker...
String tempText = "";
for (int counter = 0; counter < tempArray.Length;
counter++)
{
tempText += tempArray[counter] + "\n"; //done to
minimize the number of updates on the text box
}
this.Text = tempText;
colorLines(); //make sure _Paint is still false while we do
this!
_Paint = true;
this.SelectionStart = cursorPos + text.Length;
this.SelectionLength = 0;
}
public int CurrentColumn
{
get { return CursorPosition.Column(this, SelectionStart); }
}

protected override void WndProc(ref
System.Windows.Forms.Message m)
{

// sometimes we want to eat the paint message so we don't
have to see all the
// flicker from when we select the text to change the
color.
if (m.Msg == WM_PAINT)
{

if (_Paint)
{

base.WndProc(ref m);
}
else
{

m.Result = IntPtr.Zero;
}
}

else
{

base.WndProc(ref m);
}

}
}
internal class CursorPosition
{
[System.Runtime.InteropServices.DllImport("user32")]
public static extern int GetCaretPos(ref Point lpPoint);

private static int GetCorrection(RichTextBox e, int index)
{
Point pt1 = Point.Empty;
GetCaretPos(ref pt1);
Point pt2 = e.GetPositionFromCharIndex(index);

if (pt1 != pt2)
return 1;
else
return 0;
}

public static int Line(RichTextBox e, int index)
{
int correction = GetCorrection(e, index);
return e.GetLineFromCharIndex(index) - correction + 1;
}

public static int Column(RichTextBox e, int index1)
{
int correction = GetCorrection(e, index1);
Point p = e.GetPositionFromCharIndex(index1 - correction);

if (p.X == 1)
return 1;

p.X = 0;
int index2 = e.GetCharIndexFromPosition(p);

int col = index1 - index2 + 1;

return col;
}
}
}
 
M

Marc Gravell

Sorry, but there's way too much there that is unrelated, and nothing
(visibly) here that actually reproduces what you are seeing (i.e. the values
of .Text and colorTable). I think what you need to do here is to boil this
down to the simplest thing that introduces your problem... in fact, your
/previous/ code would suffice, if you just added (somewhere) a definition
for colorTable (along with some suitable contents), and a value for .Text
that shows the problem.This would allow the many readers here to attempt to
reproduce and resolve it with you.

In reality, the simple fact of doing the above usually helps the original
developer find the problem themselves, which is also a bonus. Sorry if this
doesn't sound helpful, but it is the best approach here...

Jon Skeet has a very good article on this:
http://www.pobox.com/~skeet/csharp/complete.html

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top