using system;
using system.collections.specialized;
using system.drawing;
using system.drawing.imaging;
using system.io;
using system.runtime.interopservices;
using system.text;
using system.windows.forms;
namespace khendys.controls {
#region public enums
// enum for possible rtf colors
public enum rtfcolor {
black, maroon, green, olive, navy, purple, teal, gray, silver,
red, lime, yellow, blue, fuchsia, aqua, white
}
#endregion
public class exrichtextbox : system.windows.forms.richtextbox {
#region my enums
// specifies the flags/options for the unmanaged call to the gdi+ method
// metafile.emftowmfbits().
private enum emftowmfbitsflags {
// use the default conversion
emftowmfbitsflagsdefault = 0x00000000,
// embedded the source of the emf metafiel within the resulting wmf
// metafile
emftowmfbitsflagsembedemf = 0x00000001,
// place a 22-byte header in the resulting wmf file. the header is
// required for the metafile to be considered placeable.
emftowmfbitsflagsincludeplaceable = 0x00000002,
// dont simulate clipping by using the xor operator.
emftowmfbitsflagsnoxorclip = 0x00000004
};
#endregion
#region my structs
// definitions for colors in an rtf document
private struct rtfcolordef {
public const string black = @”\red0\green0\blue0″;
public const string maroon = @”\red128\green0\blue0″;
public const string green = @”\red0\green128\blue0″;
public const string olive = @”\red128\green128\blue0″;
public const string navy = @”\red0\green0\blue128″;
public const string purple = @”\red128\green0\blue128″;
public const string teal = @”\red0\green128\blue128″;
public const string gray = @”\red128\green128\blue128″;
public const string silver = @”\red192\green192\blue192″;
public const string red = @”\red255\green0\blue0″;
public const string lime = @”\red0\green255\blue0″;
public const string yellow = @”\red255\green255\blue0″;
public const string blue = @”\red0\green0\blue255″;
public const string fuchsia = @”\red255\green0\blue255″;
public const string aqua = @”\red0\green255\blue255″;
public const string white = @”\red255\green255\blue255″;
}
// control words for rtf font families
private struct rtffontfamilydef {
public const string unknown = @”\fnil”;
public const string roman = @”\froman”;
public const string swiss = @”\fswiss”;
public const string modern = @”\fmodern”;
public const string script = @”\fscript”;
public const string decor = @”\fdecor”;
public const string technical = @”\ftech”;
public const string bidirect = @”\fbidi”;
}
#endregion
#region my constants
// not used in this application. descriptions can be found with documentation
// of windows gdi function setmapmode
private const int mm_text = 1;
private const int mm_lometric = 2;
private const int mm_himetric = 3;
private const int mm_loenglish = 4;
private const int mm_hienglish = 5;
private const int mm_twips = 6;
// ensures that the metafile maintains a 1:1 aspect ratio
private const int mm_isotropic = 7;
// allows the x-coordinates and y-coordinates of the metafile to be adjusted
// independently
private const int mm_anisotropic = 8;
// represents an unknown font family
private const string ff_unknown = “unknown”;
// the number of hundredths of millimeters (0.01 mm) in an inch
// for more information, see getimageprefix() method.
private const int hmm_per_inch = 2540;
// the number of twips in an inch
// for more information, see getimageprefix() method.
private const int twips_per_inch = 1440;
#endregion
#region my privates
// the default text color
private rtfcolor textcolor;
// the default text background color
private rtfcolor highlightcolor;
// dictionary that maps color enums to rtf color codes
private hybriddictionary rtfcolor;
// dictionary that mapas framework font families to rtf font families
private hybriddictionary rtffontfamily;
// the horizontal resolution at which the control is being displayed
private float xdpi;
// the vertical resolution at which the control is being displayed
private float ydpi;
#endregion
#region elements required to create an rtf document
/* rtf header
* ———-
*
* \rtf[n] – for text to be considered to be rtf, it must be enclosed in this tag.
* rtf1 is used because the richtextbox conforms to rtf specification
* version 1.
* \ansi – the character set.
* \ansicpg[n] – specifies that unicode characters might be embedded. ansicpg1252
* is the default used by windows.
* \deff[n] – the default font. \deff0 means the default font is the first font
* found.
* \deflang[n] – the default language. \deflang1033 specifies us english.
* */
private const string rtf_header = @”{\rtf1\ansi\ansicpg1252\deff0\deflang1033″;
/* rtf document area
* —————–
*
* \viewkind[n] – the type of view or zoom level. \viewkind4 specifies normal view.
* \uc[n] – the number of bytes corresponding to a unicode character.
* \pard – resets to default paragraph properties
* \cf[n] – foreground color. \cf1 refers to the color at index 1 in
* the color table
* \f[n] – font number. \f0 refers to the font at index 0 in the font
* table.
* \fs[n] – font size in half-points.
* */
private const string rtf_document_pre = @”\viewkind4\uc1\pard\cf1\f0\fs20″;
private const string rtf_document_post = @”\cf0\fs17}”;
private string rtf_image_post = @”}”;
#endregion
#region accessors
// todo: this can be ommitted along with removebadcharacters
// overrides the default implementation of rtf. this is done because the control
// was originally developed to run in an instant messenger that uses the
// jabber xml-based protocol. the framework would throw an exception when the
// xml contained the null character, so i filtered out.
public new string rtf {
get {return removebadchars(base.rtf);}
set {base.rtf = value;}
}
// the color of the text
public rtfcolor textcolor {
get {return textcolor;}
set {textcolor = value;}
}
// the color of the highlight
public rtfcolor higlightcolor {
get {return highlightcolor;}
set {highlightcolor = value;}
}
#endregion
#region constructors
/// <summary>
/// initializes the text colors, creates dictionaries for rtf colors and
/// font families, and stores the horizontal and vertical resolution of
/// the richtextboxs graphics context.
/// </summary>
public exrichtextbox() : base() {
// initialize default text and background colors
textcolor = rtfcolor.black;
highlightcolor = rtfcolor.white;
// initialize the dictionary mapping color codes to definitions
rtfcolor = new hybriddictionary();
rtfcolor.add(rtfcolor.aqua, rtfcolordef.aqua);
rtfcolor.add(rtfcolor.black, rtfcolordef.black);
rtfcolor.add(rtfcolor.blue, rtfcolordef.blue);
rtfcolor.add(rtfcolor.fuchsia, rtfcolordef.fuchsia);
rtfcolor.add(rtfcolor.gray, rtfcolordef.gray);
rtfcolor.add(rtfcolor.green, rtfcolordef.green);
rtfcolor.add(rtfcolor.lime, rtfcolordef.lime);
rtfcolor.add(rtfcolor.maroon, rtfcolordef.maroon);
rtfcolor.add(rtfcolor.navy, rtfcolordef.navy);
rtfcolor.add(rtfcolor.olive, rtfcolordef.olive);
rtfcolor.add(rtfcolor.purple, rtfcolordef.purple);
rtfcolor.add(rtfcolor.red, rtfcolordef.red);
rtfcolor.add(rtfcolor.silver, rtfcolordef.silver);
rtfcolor.add(rtfcolor.teal, rtfcolordef.teal);
rtfcolor.add(rtfcolor.white, rtfcolordef.white);
rtfcolor.add(rtfcolor.yellow, rtfcolordef.yellow);
// initialize the dictionary mapping default framework font families to
// rtf font families
rtffontfamily = new hybriddictionary();
rtffontfamily.add(fontfamily.genericmonospace.name, rtffontfamilydef.modern);
rtffontfamily.add(fontfamily.genericsansserif, rtffontfamilydef.swiss);
rtffontfamily.add(fontfamily.genericserif, rtffontfamilydef.roman);
rtffontfamily.add(ff_unknown, rtffontfamilydef.unknown);
// get the horizontal and vertical resolutions at which the object is
// being displayed
using(graphics _graphics = this.creategraphics()) {
xdpi = _graphics.dpix;
ydpi = _graphics.dpiy;
}
}
/// <summary>
/// calls the default constructor then sets the text color.
/// </summary>
/// <param name=”_textcolor”></param>
public exrichtextbox(rtfcolor _textcolor) : this() {
textcolor = _textcolor;
}
/// <summary>
/// calls the default constructor then sets te text and highlight colors.
/// </summary>
/// <param name=”_textcolor”></param>
/// <param name=”_highlightcolor”></param>
public exrichtextbox(rtfcolor _textcolor, rtfcolor _highlightcolor) : this() {
textcolor = _textcolor;
highlightcolor = _highlightcolor;
}
#endregion
#region append rtf or text to richtextbox contents
/// <summary>
/// assumes the string passed as a paramter is valid rtf text and attempts
/// to append it as rtf to the content of the control.
/// </summary>
/// <param name=”_rtf”></param>
public void appendrtf(string _rtf) {
// move caret to the end of the text
this.select(this.textlength, 0);
// since selectedrtf is null, this will append the string to the
// end of the existing rtf
this.selectedrtf = _rtf;
}
/// <summary>
/// assumes that the string passed as a parameter is valid rtf text and
/// attempts to insert it as rtf into the content of the control.
/// </summary>
/// <remarks>
/// note: the text is inserted wherever the caret is at the time of the call,
/// and if any text is selected, that text is replaced.
/// </remarks>
/// <param name=”_rtf”></param>
public void insertrtf(string _rtf) {
this.selectedrtf = _rtf;
}
/// <summary>
/// appends the text using the current font, text, and highlight colors.
/// </summary>
/// <param name=”_text”></param>
public void appendtextasrtf(string _text) {
appendtextasrtf(_text, this.font);
}
/// <summary>
/// appends the text using the given font, and current text and highlight
/// colors.
/// </summary>
/// <param name=”_text”></param>
/// <param name=”_font”></param>
public void appendtextasrtf(string _text, font _font) {
appendtextasrtf(_text, _font, textcolor);
}
/// <summary>
/// appends the text using the given font and text color, and the current
/// highlight color.
/// </summary>
/// <param name=”_text”></param>
/// <param name=”_font”></param>
/// <param name=”_color”></param>
public void appendtextasrtf(string _text, font _font, rtfcolor _textcolor) {
appendtextasrtf(_text, _font, _textcolor, highlightcolor);
}
/// <summary>
/// appends the text using the given font, text, and highlight colors. simply
/// moves the caret to the end of the richtextboxs text and makes a call to
/// insert.
/// </summary>
/// <param name=”_text”></param>
/// <param name=”_font”></param>
/// <param name=”_textcolor”></param>
/// <param name=”_backcolor”></param>
public void appendtextasrtf(string _text, font _font, rtfcolor _textcolor, rtfcolor _backcolor) {
// move carret to the end of the text
this.select(this.textlength, 0);
inserttextasrtf(_text, _font, _textcolor, _backcolor);
}
#endregion
#region insert plain text
/// <summary>
/// inserts the text using the current font, text, and highlight colors.
/// </summary>
/// <param name=”_text”></param>
public void inserttextasrtf(string _text) {
inserttextasrtf(_text, this.font);
}
/// <summary>
/// inserts the text using the given font, and current text and highlight
/// colors.
/// </summary>
/// <param name=”_text”></param>
/// <param name=”_font”></param>
public void inserttextasrtf(string _text, font _font) {
inserttextasrtf(_text, _font, textcolor);
}
/// <summary>
/// inserts the text using the given font and text color, and the current
/// highlight color.
/// </summary>
/// <param name=”_text”></param>
/// <param name=”_font”></param>
/// <param name=”_color”></param>
public void inserttextasrtf(string _text, font _font, rtfcolor _textcolor) {
inserttextasrtf(_text, _font, _textcolor, highlightcolor);
}
/// <summary>
/// inserts the text using the given font, text, and highlight colors. the
/// text is wrapped in rtf codes so that the specified formatting is kept.
/// you can only assign valid rtf to the richtextbox.rtf property, else
/// an exception is thrown. the rtf string should follow this format …
///
/// {\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{[fonts]}{\colortbl ;[colors]}}
/// \viewkind4\uc1\pard\cf1\f0\fs20 [document area] }
///
/// </summary>
/// <remarks>
/// note: the text is inserted wherever the caret is at the time of the call,
/// and if any text is selected, that text is replaced.
/// </remarks>
/// <param name=”_text”></param>
/// <param name=”_font”></param>
/// <param name=”_color”></param>
/// <param name=”_color”></param>
public void inserttextasrtf(string _text, font _font, rtfcolor _textcolor, rtfcolor _backcolor) {
stringbuilder _rtf = new stringbuilder();
// append the rtf header
_rtf.append(rtf_header);
// create the font table from the font passed in and append it to the
// rtf string
_rtf.append(getfonttable(_font));
// create the color table from the colors passed in and append it to the
// rtf string
_rtf.append(getcolortable(_textcolor, _backcolor));
// create the document area from the text to be added as rtf and append
// it to the rtf string.
_rtf.append(getdocumentarea(_text, _font));
this.selectedrtf = _rtf.tostring();
}
/// <summary>
/// creates the document area of the rtf being inserted. the document area
/// (in this case) consists of the text being added as rtf and all the
/// formatting specified in the font object passed in. this should have the
/// form …
///
/// \viewkind4\uc1\pard\cf1\f0\fs20 [document area] }
///
/// </summary>
/// <param name=”_text”></param>
/// <param name=”_font”></param>
/// <returns>
/// the document area as a string.
/// </returns>
private string getdocumentarea(string _text, font _font) {
stringbuilder _doc = new stringbuilder();
// append the standard rtf document area control string
_doc.append(rtf_document_pre);
// set the highlight color (the color behind the text) to the
// third color in the color table. see getcolortable for more details.
_doc.append(@”\highlight2″);
// if the font is bold, attach corresponding tag
if (_font.bold)
_doc.append(@”\b”);
// if the font is italic, attach corresponding tag
if (_font.italic)
_doc.append(@”\i”);
// if the font is strikeout, attach corresponding tag
if (_font.strikeout)
_doc.append(@” trike”);
// if the font is underlined, attach corresponding tag
if (_font.underline)
_doc.append(@”\ul”);
// set the font to the first font in the font table.
// see getfonttable for more details.
_doc.append(@”\f0″);
// set the size of the font. in rtf, font size is measured in
// half-points, so the font size is twice the value obtained from
// font.sizeinpoints
_doc.append(@”\fs”);
_doc.append((int)math.round((2 * _font.sizeinpoints)));
// apppend a space before starting actual text (for clarity)
_doc.append(@” “);
// append actual text, however, replace newlines with rtf \par.
// any other special text should be handled here (e.g.) tabs, etc.
_doc.append(_text.replace(“\n”, @”\par “));
// rtf isnt strict when it comes to closing control words, but what the
// heck …
// remove the highlight
_doc.append(@”\highlight0″);
// if font is bold, close tag
if (_font.bold)
_doc.append(@”\b0″);
// if font is italic, close tag
if (_font.italic)
_doc.append(@”\i0″);
// if font is strikeout, close tag
if (_font.strikeout)
_doc.append(@” trike0″);
// if font is underlined, cloes tag
if (_font.underline)
_doc.append(@”\ulnone”);
// revert back to default font and size
_doc.append(@”\f0″);
_doc.append(@”\fs20″);
// close the document area control string
_doc.append(rtf_document_post);
return _doc.tostring();
}
#endregion
#region insert image
/// <summary>
/// inserts an image into the richtextbox. the image is wrapped in a windows
/// format metafile, because although microsoft discourages the use of a wmf,
/// the richtextbox (and even ms word), wraps an image in a wmf before inserting
/// the image into a document. the wmf is attached in hex format (a string of
/// hex numbers).
///
/// the rtf specification v1.6 says that you should be able to insert bitmaps,
/// .jpegs, .gifs, .pngs, and enhanced metafiles (.emf) directly into an rtf
/// document without the wmf wrapper. this works fine with ms word,
/// however, when you dont wrap images in a wmf, wordpad and
/// richtextboxes simply ignore them. both use the riched20.dll or msfted.dll.
/// </summary>
/// <remarks>
/// note: the image is inserted wherever the caret is at the time of the call,
/// and if any text is selected, that text is replaced.
/// </remarks>
/// <param name=”_image”></param>
public void insertimage(image _image) {
stringbuilder _rtf = new stringbuilder();
// append the rtf header
_rtf.append(rtf_header);
// create the font table using the richtextboxs current font and append
// it to the rtf string
_rtf.append(getfonttable(this.font));
// create the image control string and append it to the rtf string
_rtf.append(getimageprefix(_image));
// create the windows metafile and append its bytes in hex format
_rtf.append(getrtfimage(_image));
// close the rtf image control string
_rtf.append(rtf_image_post);
this.selectedrtf = _rtf.tostring();
}
/// <summary>
/// creates the rtf control string that describes the image being inserted.
/// this description (in this case) specifies that the image is an
/// mm_anisotropic metafile, meaning that both x and y axes can be scaled
/// independently. the control string also gives the images current dimensions,
/// and its target dimensions, so if you want to control the size of the
/// image being inserted, this would be the place to do it. the prefix should
/// have the form …
///
/// {\pict\wmetafile8\picw[a]\pich[b]\picwgoal[c]\pichgoal[d]
///
/// where …
///
/// a = current width of the metafile in hundredths of millimeters (0.01mm)
/// = image width in inches * number of (0.01mm) per inch
/// = (image width in pixels / graphics contexts horizontal resolution) * 2540
/// = (image width in pixels / graphics.dpix) * 2540
///
/// b = current height of the metafile in hundredths of millimeters (0.01mm)
/// = image height in inches * number of (0.01mm) per inch
/// = (image height in pixels / graphics contexts vertical resolution) * 2540
/// = (image height in pixels / graphics.dpix) * 2540
///
/// c = target width of the metafile in twips
/// = image width in inches * number of twips per inch
/// = (image width in pixels / graphics contexts horizontal resolution) * 1440
/// = (image width in pixels / graphics.dpix) * 1440
///
/// d = target height of the metafile in twips
/// = image height in inches * number of twips per inch
/// = (image height in pixels / graphics contexts horizontal resolution) * 1440
/// = (image height in pixels / graphics.dpix) * 1440
///
/// </summary>
/// <remarks>
/// the graphics contexts resolution is simply the current resolution at which
/// windows is being displayed. normally its 96 dpi, but instead of assuming
/// i just added the code.
///
/// according to ken howe at pbdr.com, “twips are screen-independent units
/// used to ensure that the placement and proportion of screen elements in
/// your screen application are the same on all display systems.”
///
/// units used
/// ———-
/// 1 twip = 1/20 point
/// 1 point = 1/72 inch
/// 1 twip = 1/1440 inch
///
/// 1 inch = 2.54 cm
/// 1 inch = 25.4 mm
/// 1 inch = 2540 (0.01)mm
/// </remarks>
/// <param name=”_image”></param>
/// <returns></returns>
private string getimageprefix(image _image) {
stringbuilder _rtf = new stringbuilder();
// calculate the current width of the image in (0.01)mm
int picw = (int)math.round((_image.width / xdpi) * hmm_per_inch);
// calculate the current height of the image in (0.01)mm
int pich = (int)math.round((_image.height / ydpi) * hmm_per_inch);
// calculate the target width of the image in twips
int picwgoal = (int)math.round((_image.width / xdpi) * twips_per_inch);
// calculate the target height of the image in twips
int pichgoal = (int)math.round((_image.height / ydpi) * twips_per_inch);
// append values to rtf string
_rtf.append(@”{\pict\wmetafile8″);
_rtf.append(@”\picw”);
_rtf.append(picw);
_rtf.append(@”\pich”);
_rtf.append(pich);
_rtf.append(@”\picwgoal”);
_rtf.append(picwgoal);
_rtf.append(@”\pichgoal”);
_rtf.append(pichgoal);
_rtf.append(” “);
return _rtf.tostring();
}
/// <summary>
/// use the emftowmfbits function in the gdi+ specification to convert a
/// enhanced metafile to a windows metafile
/// </summary>
/// <param name=”_hemf”>
/// a handle to the enhanced metafile to be converted
/// </param>
/// <param name=”_buffersize”>
/// the size of the buffer used to store the windows metafile bits returned
/// </param>
/// <param name=”_buffer”>
/// an array of bytes used to hold the windows metafile bits returned
/// </param>
/// <param name=”_mappingmode”>
/// the mapping mode of the image. this control uses mm_anisotropic.
/// </param>
/// <param name=”_flags”>
/// flags used to specify the format of the windows metafile returned
/// </param>
[dllimportattribute(“gdiplus.dll”)]
private static extern uint gdipemftowmfbits (intptr _hemf, uint _buffersize,
byte[] _buffer, int _mappingmode, emftowmfbitsflags _flags);
/// <summary>
/// wraps the image in an enhanced metafile by drawing the image onto the
/// graphics context, then converts the enhanced metafile to a windows
/// metafile, and finally appends the bits of the windows metafile in hex
/// to a string and returns the string.
/// </summary>
/// <param name=”_image”></param>
/// <returns>
/// a string containing the bits of a windows metafile in hex
/// </returns>
private string getrtfimage(image _image) {
stringbuilder _rtf = null;
// used to store the enhanced metafile
memorystream _stream = null;
// used to create the metafile and draw the image
graphics _graphics = null;
// the enhanced metafile
metafile _metafile = null;
// handle to the device context used to create the metafile
intptr _hdc;
try {
_rtf = new stringbuilder();
_stream = new memorystream();
// get a graphics context from the richtextbox
using(_graphics = this.creategraphics()) {
// get the device context from the graphics context
_hdc = _graphics.gethdc();
// create a new enhanced metafile from the device context
_metafile = new metafile(_stream, _hdc);
// release the device context
_graphics.releasehdc(_hdc);
}
// get a graphics context from the enhanced metafile
using(_graphics = graphics.fromimage(_metafile)) {
// draw the image on the enhanced metafile
_graphics.drawimage(_image, new rectangle(0, 0, _image.width, _image.height));
}
// get the handle of the enhanced metafile
intptr _hemf = _metafile.gethenhmetafile();
// a call to emftowmfbits with a null buffer return the size of the
// buffer need to store the wmf bits. use this to get the buffer
// size.
uint _buffersize = gdipemftowmfbits(_hemf, 0, null, mm_anisotropic,
emftowmfbitsflags.emftowmfbitsflagsdefault);
// create an array to hold the bits
byte[] _buffer = new byte[_buffersize];
// a call to emftowmfbits with a valid buffer copies the bits into the
// buffer an returns the number of bits in the wmf.
uint _convertedsize = gdipemftowmfbits(_hemf, _buffersize, _buffer, mm_anisotropic,
emftowmfbitsflags.emftowmfbitsflagsdefault);
// append the bits to the rtf string
for(int i = 0; i < _buffer.length; ++i) {
_rtf.append(string.format(“{0:x2}”, _buffer[i]));
}
return _rtf.tostring();
}
finally {
if(_graphics != null)
_graphics.dispose();
if(_metafile != null)
_metafile.dispose();
if(_stream != null)
_stream.close();
}
}
#endregion
#region rtf helpers
/// <summary>
/// creates a font table from a font object. when an insert or append
/// operation is performed a font is either specified or the default font
/// is used. in any case, on any insert or append, only one font is used,
/// thus the font table will always contain a single font. the font table
/// should have the form …
///
/// {\fonttbl{\f0\[family]\fcharset0 [font_name];}
/// </summary>
/// <param name=”_font”></param>
/// <returns></returns>
private string getfonttable(font _font) {
stringbuilder _fonttable = new stringbuilder();
// append table control string
_fonttable.append(@”{\fonttbl{\f0″);
_fonttable.append(@”\”);
// if the fonts family corresponds to an rtf family, append the
// rtf family name, else, append the rtf for unknown font family.
if (rtffontfamily.contains(_font.fontfamily.name))
_fonttable.append(rtffontfamily[_font.fontfamily.name]);
else
_fonttable.append(rtffontfamily[ff_unknown]);
// \fcharset specifies the character set of a font in the font table.
// 0 is for ansi.
_fonttable.append(@”\fcharset0 “);
// append the name of the font
_fonttable.append(_font.name);
// close control string
_fonttable.append(@”;}}”);
return _fonttable.tostring();
}
/// <summary>
/// creates a font table from the rtfcolor structure. when an insert or append
/// operation is performed, _textcolor and _backcolor are either specified
/// or the default is used. in any case, on any insert or append, only three
/// colors are used. the default color of the richtextbox (signified by a
/// semicolon (;) without a definition), is always the first color (index 0) in
/// the color table. the second color is always the text color, and the third
/// is always the highlight color (color behind the text). the color table
/// should have the form …
///
/// {\colortbl ;[text_color];[highlight_color];}
///
/// </summary>
/// <param name=”_textcolor”></param>
/// <param name=”_backcolor”></param>
/// <returns></returns>
private string getcolortable(rtfcolor _textcolor, rtfcolor _backcolor) {
stringbuilder _colortable = new stringbuilder();
// append color table control string and default font (;)
_colortable.append(@”{\colortbl ;”);
// append the text color
_colortable.append(rtfcolor[_textcolor]);
_colortable.append(@”;”);
// append the highlight color
_colortable.append(rtfcolor[_backcolor]);
_colortable.append(@”;}\n”);
return _colortable.tostring();
}
/// <summary>
/// called by overrided richtextbox.rtf accessor.
/// removes the null character from the rtf. this is residue from developing
/// the control for a specific instant messaging protocol and can be ommitted.
/// </summary>
/// <param name=”_originalrtf”></param>
/// <returns>rtf without null character</returns>
private string removebadchars(string _originalrtf) {
return _originalrtf.replace(“\0”, “”);
}
#endregion
}
}