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 Emftowmfbitsflagsinclud ePlaceable = 0x00000002, // Do not 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_isisotropic = 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 whi Ch 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 framew.. ork 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> 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 (RTFColorDef.silver); RTFColor.Add (RTFColorDeal); RTFColor.Add (RTFColor.Whit) e, 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 death set the text color. /// summary> /// param> public exrichtextbox (RTFCOLOR _TEXTCOLOR): this () {textcolor = _TextColor;} ///
/// Appends the text using the current font, text, and highlight colors. /// summary> /// param> public void AppendTextAsRtf (string _text) {AppendTextAsRtf (_text , this.font);} ///
} #Endregion #Region Insert Plain Text ///
/// NOTE: The text is inserted where of the call _Text "> param> /// param> /// param> /// 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 (_text, _font)); this.selectedRTF = _rtf.toString ();} / //
// 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 tagiff (_font.bold) _doc.Append (@ "/ b"); // if the font is italic, attach corresponding tagiff (_font) .Italic) _doc.append (@ "/ i"); // if the font is strike f (_font.strikeout) _doc.append (@ "/ strike"); // 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.sizei) Npoints)))); // apppend a space before starting actual text (for clarity) _doc.Append (@ "); // append activity text, however, replace newlines with rtf / par. // Any Other Special Text Should Be Handled Here (EG) Tabs, etc._doc.append (_text.replace ("/ n", @ "/ par")); // rtf isn't strict when comes To Closing Control Words, But what the HECK ... // Remove the highlight _doc.append (@ "/ highlight0"); // if font is bold, close tagiff _doc.Append (@ "/ b0"); // if font Is italic, close tagiff _doc.append (@ "/ i0");
// if font is strikeout, close tag if (_font.strikeout) _doc.Append (@ "/ strike0"); // if font is underlined, cloes tagiff (_font.underline) _doc.append (@ "/ ulnone" ); // repert back to default font and size _doc.append (@ "/ f0"); _doc.Append (@ "/ fs20"); // close the document isa control string _doc.Append (RTF_Document_post); return_doc .ToString ();} #endregion #region Insert Image ///
// 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 ();} ///
(Image width in pixels / graphics.dpix) * 1440 /// // D = target height of the metafile in twips /// = image height in inches * Number of twips per in ,// = (Image Height in Pixels) / Graphics context's horizontal resolution * 1440 /// = (image height in pixels / graphics.dpix) * 1440 /// /// ////
(int) Math.Round ((_ image.height / ydpi) * twips_per_inch); // append value to RTF string _rtf.append (@ "{/ pic / wmetafile8); _rtf.append (@" / picw "); _rtf.append (picw); _rtf.append (@ "/ pich"); _rtf.append (@ "/ picwgoal"); _rtf.append (picwgoal); _rtf.Append (@ "/ Pichgoal "); _rtf.append (pichgoal); _rtf.append (" "); return _rtf.tostring ();} ///
/// 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> ///
// 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 ///
_fontTable.Append (@ "/");. // If the font's 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 ();} ///