• RichTextBoxEx


      1 using System;
      2 using System.Collections.Specialized;
      3 using System.Drawing;
      4 using System.Drawing.Imaging;
      5 using System.IO;
      6 using System.Runtime.InteropServices;
      7 using System.Text;
      8 using System.Windows.Forms;
      9 namespace RichTextBoxEx.Controls
     10 {
     11     #region Public Enums
     12     //可能的RTF颜色枚举
     13     public enum RtfColor
     14     {
     15         Black, Maroon, Green, Olive, Navy, Purple, Teal, Gray, Silver,
     16         Red, Lime, Yellow, Blue, Fuchsia, Aqua, White
     17     }
     18     #endregion
     19     /// <summary>
     20     /// This class adds the following functionality to RichTextBox:
     21     /// 
     22     /// 1. Allows plain text to be inserted or appended programmatically to RTF
     23     ///  content.
     24     /// 2. Allows the font, text color, and highlight color of plain text to be
     25     ///  specified when inserting or appending text as RTF.
     26     /// 3. Allows images to be inserted programmatically, or with interaction from
     27     ///  the user.
     28     /// </summary>
     29     /// <remarks>
     30     /// Many solutions to the problem of programmatically inserting images
     31     /// into a RichTextBox use the clipboard or hard code the RTF for
     32     /// the image in the program.  This class is an attempt to make the process of
     33     /// inserting images at runtime more flexible without the overhead of maintaining
     34     /// the clipboard or the use of huge, cumbersome strings.
     35     /// 
     36     /// RTF Specification v1.6 was used and is referred to many times in this document.
     37     /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnrtfspec/html/rtfspec.asp
     38     /// 
     39     /// For information about the RichEdit (Unmanaged RichTextBox) ...
     40     /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/richedit/richeditcontrols/aboutricheditcontrols.asp
     41     /// </remarks>
     42     public class ExRichTextBox : System.Windows.Forms.RichTextBox
     43     {
     44         #region My Enums
     45         // Specifies the flags/options for the unmanaged call to the GDI+ method
     46         // Metafile.EmfToWmfBits().
     47         private enum EmfToWmfBitsFlags
     48         {
     49             // Use the default conversion
     50             EmfToWmfBitsFlagsDefault = 0x00000000,
     51             // Embedded the source of the EMF metafiel within the resulting WMF
     52             // metafile
     53             EmfToWmfBitsFlagsEmbedEmf = 0x00000001,
     54             // Place a 22-byte header in the resulting WMF file.  The header is
     55             // required for the metafile to be considered placeable.
     56             EmfToWmfBitsFlagsIncludePlaceable = 0x00000002,
     57             // Don't simulate clipping by using the XOR operator.
     58             EmfToWmfBitsFlagsNoXORClip = 0x00000004
     59         };
     60         #endregion
     61         #region My Structs
     62         // Definitions for colors in an RTF document
     63         private struct RtfColorDef
     64         {
     65             public const string Black = @"
    ed0green0lue0";
     66             public const string Maroon = @"
    ed128green0lue0";
     67             public const string Green = @"
    ed0green128lue0";
     68             public const string Olive = @"
    ed128green128lue0";
     69             public const string Navy = @"
    ed0green0lue128";
     70             public const string Purple = @"
    ed128green0lue128";
     71             public const string Teal = @"
    ed0green128lue128";
     72             public const string Gray = @"
    ed128green128lue128";
     73             public const string Silver = @"
    ed192green192lue192";
     74             public const string Red = @"
    ed255green0lue0";
     75             public const string Lime = @"
    ed0green255lue0";
     76             public const string Yellow = @"
    ed255green255lue0";
     77             public const string Blue = @"
    ed0green0lue255";
     78             public const string Fuchsia = @"
    ed255green0lue255";
     79             public const string Aqua = @"
    ed0green255lue255";
     80             public const string White = @"
    ed255green255lue255";
     81         }
     82         // Control words for RTF font families
     83         private struct RtfFontFamilyDef
     84         {
     85             public const string Unknown = @"fnil";
     86             public const string Roman = @"froman";
     87             public const string Swiss = @"fswiss";
     88             public const string Modern = @"fmodern";
     89             public const string Script = @"fscript";
     90             public const string Decor = @"fdecor";
     91             public const string Technical = @"ftech";
     92             public const string BiDirect = @"fbidi";
     93         }
     94         #endregion
     95         #region My Constants
     96         // Not used in this application.  Descriptions can be found with documentation
     97         // of Windows GDI function SetMapMode
     98         private const int MM_TEXT = 1;
     99         private const int MM_LOMETRIC = 2;
    100         private const int MM_HIMETRIC = 3;
    101         private const int MM_LOENGLISH = 4;
    102         private const int MM_HIENGLISH = 5;
    103         private const int MM_TWIPS = 6;
    104         // Ensures that the metafile maintains a 1:1 aspect ratio
    105         private const int MM_ISOTROPIC = 7;
    106         // Allows the x-coordinates and y-coordinates of the metafile to be adjusted
    107         // independently
    108         private const int MM_ANISOTROPIC = 8;
    109         // Represents an unknown font family
    110         private const string FF_UNKNOWN = "UNKNOWN";
    111         // The number of hundredths of millimeters (0.01 mm) in an inch
    112         // For more information, see GetImagePrefix() method.
    113         private const int HMM_PER_INCH = 2540;
    114         // The number of twips in an inch
    115         // For more information, see GetImagePrefix() method.
    116         private const int TWIPS_PER_INCH = 1440;
    117         #endregion
    118         #region My Privates
    119         // The default text color
    120         private RtfColor textColor;
    121         // The default text background color
    122         private RtfColor highlightColor;
    123         // Dictionary that maps color enums to RTF color codes
    124         private HybridDictionary rtfColor;
    125         // Dictionary that mapas Framework font families to RTF font families
    126         private HybridDictionary rtfFontFamily;
    127         // The horizontal resolution at which the control is being displayed
    128         private float xDpi;
    129         // The vertical resolution at which the control is being displayed
    130         private float yDpi;
    131         #endregion
    132         #region Elements required to create an RTF document
    133         /* RTF HEADER
    134    * ----------
    135    * 
    136    * 
    tf[N]  - For text to be considered to be RTF, it must be enclosed in this tag.
    137    *      rtf1 is used because the RichTextBox conforms to RTF Specification
    138    *      version 1.
    139    * ansi  - The character set.
    140    * ansicpg[N] - Specifies that unicode characters might be embedded. ansicpg1252
    141    *      is the default used by Windows.
    142    * deff[N]  - The default font. deff0 means the default font is the first font
    143    *      found.
    144    * deflang[N] - The default language. deflang1033 specifies US English.
    145    * */
    146         private const string RTF_HEADER = @"{
    tf1ansiansicpg1252deff0deflang1033";
    147         /* RTF DOCUMENT AREA
    148          * -----------------
    149          * 
    150          * viewkind[N] - The type of view or zoom level.  viewkind4 specifies normal view.
    151          * uc[N]  - The number of bytes corresponding to a Unicode character.
    152          * pard  - Resets to default paragraph properties
    153          * cf[N]  - Foreground color.  cf1 refers to the color at index 1 in
    154          *      the color table
    155          * f[N]  - Font number. f0 refers to the font at index 0 in the font
    156          *      table.
    157          * fs[N]  - Font size in half-points.
    158          * */
    159         private const string RTF_DOCUMENT_PRE = @"viewkind4uc1pardcf1f0fs20";
    160         private const string RTF_DOCUMENT_POST = @"cf0fs17}";
    161         private string RTF_IMAGE_POST = @"}";
    162         #endregion
    163         #region Accessors
    164         // TODO: This can be ommitted along with RemoveBadCharacters
    165         // Overrides the default implementation of RTF.  This is done because the control
    166         // was originally developed to run in an instant messenger that uses the
    167         // Jabber XML-based protocol.  The framework would throw an exception when the
    168         // XML contained the null character, so I filtered out.
    169         public new string Rtf
    170         {
    171             get { return RemoveBadChars(base.Rtf); }
    172             set { base.Rtf = value; }
    173         }
    174         // The color of the text
    175         public RtfColor TextColor
    176         {
    177             get { return textColor; }
    178             set { textColor = value; }
    179         }
    180         // The color of the highlight
    181         public RtfColor HiglightColor
    182         {
    183             get { return highlightColor; }
    184             set { highlightColor = value; }
    185         }
    186         #endregion
    187         #region Constructors
    188         /// <summary>
    189         /// Initializes the text colors, creates dictionaries for RTF colors and
    190         /// font families, and stores the horizontal and vertical resolution of
    191         /// the RichTextBox's graphics context.
    192         /// </summary>
    193         public ExRichTextBox()
    194             : base()
    195         {
    196             // Initialize default text and background colors
    197             textColor = RtfColor.Black;
    198             highlightColor = RtfColor.White;
    199             // Initialize the dictionary mapping color codes to definitions
    200             rtfColor = new HybridDictionary();
    201             rtfColor.Add(RtfColor.Aqua, RtfColorDef.Aqua);
    202             rtfColor.Add(RtfColor.Black, RtfColorDef.Black);
    203             rtfColor.Add(RtfColor.Blue, RtfColorDef.Blue);
    204             rtfColor.Add(RtfColor.Fuchsia, RtfColorDef.Fuchsia);
    205             rtfColor.Add(RtfColor.Gray, RtfColorDef.Gray);
    206             rtfColor.Add(RtfColor.Green, RtfColorDef.Green);
    207             rtfColor.Add(RtfColor.Lime, RtfColorDef.Lime);
    208             rtfColor.Add(RtfColor.Maroon, RtfColorDef.Maroon);
    209             rtfColor.Add(RtfColor.Navy, RtfColorDef.Navy);
    210             rtfColor.Add(RtfColor.Olive, RtfColorDef.Olive);
    211             rtfColor.Add(RtfColor.Purple, RtfColorDef.Purple);
    212             rtfColor.Add(RtfColor.Red, RtfColorDef.Red);
    213             rtfColor.Add(RtfColor.Silver, RtfColorDef.Silver);
    214             rtfColor.Add(RtfColor.Teal, RtfColorDef.Teal);
    215             rtfColor.Add(RtfColor.White, RtfColorDef.White);
    216             rtfColor.Add(RtfColor.Yellow, RtfColorDef.Yellow);
    217             // Initialize the dictionary mapping default Framework font families to
    218             // RTF font families
    219             rtfFontFamily = new HybridDictionary();
    220             rtfFontFamily.Add(FontFamily.GenericMonospace.Name, RtfFontFamilyDef.Modern);
    221             rtfFontFamily.Add(FontFamily.GenericSansSerif, RtfFontFamilyDef.Swiss);
    222             rtfFontFamily.Add(FontFamily.GenericSerif, RtfFontFamilyDef.Roman);
    223             rtfFontFamily.Add(FF_UNKNOWN, RtfFontFamilyDef.Unknown);
    224             // Get the horizontal and vertical resolutions at which the object is
    225             // being displayed
    226             using (Graphics _graphics = this.CreateGraphics())
    227             {
    228                 xDpi = _graphics.DpiX;
    229                 yDpi = _graphics.DpiY;
    230             }
    231         }
    232         /// <summary>
    233         /// Calls the default constructor then sets the text color.
    234         /// </summary>
    235         /// <param name="_textColor"></param>
    236         public ExRichTextBox(RtfColor _textColor)
    237             : this()
    238         {
    239             textColor = _textColor;
    240         }
    241         /// <summary>
    242         /// Calls the default constructor then sets te text and highlight colors.
    243         /// </summary>
    244         /// <param name="_textColor"></param>
    245         /// <param name="_highlightColor"></param>
    246         public ExRichTextBox(RtfColor _textColor, RtfColor _highlightColor)
    247             : this()
    248         {
    249             textColor = _textColor;
    250             highlightColor = _highlightColor;
    251         }
    252         #endregion
    253         #region Append RTF or Text to RichTextBox Contents
    254         /// <summary>
    255         /// Assumes the string passed as a paramter is valid RTF text and attempts
    256         /// to append it as RTF to the content of the control.
    257         /// </summary>
    258         /// <param name="_rtf"></param>
    259         public void AppendRtf(string _rtf)
    260         {
    261             // Move caret to the end of the text
    262             this.Select(this.TextLength, 0);
    263             // Since SelectedRtf is null, this will append the string to the
    264             // end of the existing RTF
    265             this.SelectedRtf = _rtf;
    266         }
    267         /// <summary>
    268         /// Assumes that the string passed as a parameter is valid RTF text and
    269         /// attempts to insert it as RTF into the content of the control.
    270         /// </summary>
    271         /// <remarks>
    272         /// NOTE: The text is inserted wherever the caret is at the time of the call,
    273         /// and if any text is selected, that text is replaced.
    274         /// </remarks>
    275         /// <param name="_rtf"></param>
    276         public void InsertRtf(string _rtf)
    277         {
    278             this.SelectedRtf = _rtf;
    279         }
    280         /// <summary>
    281         /// Appends the text using the current font, text, and highlight colors.
    282         /// </summary>
    283         /// <param name="_text"></param>
    284         public void AppendTextAsRtf(string _text)
    285         {
    286             AppendTextAsRtf(_text, this.Font);
    287         }
    288 
    289         /// <summary>
    290         /// Appends the text using the given font, and current text and highlight
    291         /// colors.
    292         /// </summary>
    293         /// <param name="_text"></param>
    294         /// <param name="_font"></param>
    295         public void AppendTextAsRtf(string _text, Font _font)
    296         {
    297             AppendTextAsRtf(_text, _font, textColor);
    298         }
    299         /// <summary>
    300         /// Appends the text using the given font and text color, and the current
    301         /// highlight color.
    302         /// </summary>
    303         /// <param name="_text"></param>
    304         /// <param name="_font"></param>
    305         /// <param name="_color"></param>
    306         public void AppendTextAsRtf(string _text, Font _font, RtfColor _textColor)
    307         {
    308             AppendTextAsRtf(_text, _font, _textColor, highlightColor);
    309         }
    310         /// <summary>
    311         /// Appends the text using the given font, text, and highlight colors.  Simply
    312         /// moves the caret to the end of the RichTextBox's text and makes a call to
    313         /// insert.
    314         /// </summary>
    315         /// <param name="_text"></param>
    316         /// <param name="_font"></param>
    317         /// <param name="_textColor"></param>
    318         /// <param name="_backColor"></param>
    319         public void AppendTextAsRtf(string _text, Font _font, RtfColor _textColor, RtfColor _backColor)
    320         {
    321             // Move carret to the end of the text
    322             this.Select(this.TextLength, 0);
    323             InsertTextAsRtf(_text, _font, _textColor, _backColor);
    324         }
    325         #endregion
    326         #region Insert Plain Text
    327         /// <summary>
    328         /// Inserts the text using the current font, text, and highlight colors.
    329         /// </summary>
    330         /// <param name="_text"></param>
    331         public void InsertTextAsRtf(string _text)
    332         {
    333             InsertTextAsRtf(_text, this.Font);
    334         }
    335 
    336         /// <summary>
    337         /// Inserts the text using the given font, and current text and highlight
    338         /// colors.
    339         /// </summary>
    340         /// <param name="_text"></param>
    341         /// <param name="_font"></param>
    342         public void InsertTextAsRtf(string _text, Font _font)
    343         {
    344             InsertTextAsRtf(_text, _font, textColor);
    345         }
    346         /// <summary>
    347         /// Inserts the text using the given font and text color, and the current
    348         /// highlight color.
    349         /// </summary>
    350         /// <param name="_text"></param>
    351         /// <param name="_font"></param>
    352         /// <param name="_color"></param>
    353         public void InsertTextAsRtf(string _text, Font _font, RtfColor _textColor)
    354         {
    355             InsertTextAsRtf(_text, _font, _textColor, highlightColor);
    356         }
    357         /// <summary>
    358         /// Inserts the text using the given font, text, and highlight colors.  The
    359         /// text is wrapped in RTF codes so that the specified formatting is kept.
    360         /// You can only assign valid RTF to the RichTextBox.Rtf property, else
    361         /// an exception is thrown.  The RTF string should follow this format ...
    362         /// 
    363         /// {
    tf1ansiansicpg1252deff0deflang1033{fonttbl{[FONTS]}{colortbl ;[COLORS]}}
    364         /// viewkind4uc1pardcf1f0fs20 [DOCUMENT AREA] }
    365         /// 
    366         /// </summary>
    367         /// <remarks>
    368         /// NOTE: The text is inserted wherever the caret is at the time of the call,
    369         /// and if any text is selected, that text is replaced.
    370         /// </remarks>
    371         /// <param name="_text"></param>
    372         /// <param name="_font"></param>
    373         /// <param name="_color"></param>
    374         /// <param name="_color"></param>
    375         public void InsertTextAsRtf(string _text, Font _font, RtfColor _textColor, RtfColor _backColor)
    376         {
    377             StringBuilder _rtf = new StringBuilder();
    378             // Append the RTF header
    379             _rtf.Append(RTF_HEADER);
    380             // Create the font table from the font passed in and append it to the
    381             // RTF string
    382             _rtf.Append(GetFontTable(_font));
    383             // Create the color table from the colors passed in and append it to the
    384             // RTF string
    385             _rtf.Append(GetColorTable(_textColor, _backColor));
    386             // Create the document area from the text to be added as RTF and append
    387             // it to the RTF string.
    388             _rtf.Append(GetDocumentArea(_text, _font));
    389             this.SelectedRtf = _rtf.ToString();
    390         }
    391         /// <summary>
    392         /// Creates the Document Area of the RTF being inserted. The document area
    393         /// (in this case) consists of the text being added as RTF and all the
    394         /// formatting specified in the Font object passed in. This should have the
    395         /// form ...
    396         /// 
    397         /// viewkind4uc1pardcf1f0fs20 [DOCUMENT AREA] }
    398         ///
    399         /// </summary>
    400         /// <param name="_text"></param>
    401         /// <param name="_font"></param>
    402         /// <returns>
    403         /// The document area as a string.
    404         /// </returns>
    405         private string GetDocumentArea(string _text, Font _font)
    406         {
    407             StringBuilder _doc = new StringBuilder();
    408             // Append the standard RTF document area control string
    409             _doc.Append(RTF_DOCUMENT_PRE);
    410             // Set the highlight color (the color behind the text) to the
    411             // third color in the color table.  See GetColorTable for more details.
    412             _doc.Append(@"highlight2");
    413             // If the font is bold, attach corresponding tag
    414             if (_font.Bold)
    415                 _doc.Append(@"");
    416             // If the font is italic, attach corresponding tag
    417             if (_font.Italic)
    418                 _doc.Append(@"i");
    419             // If the font is strikeout, attach corresponding tag
    420             if (_font.Strikeout)
    421                 _doc.Append(@"strike");
    422             // If the font is underlined, attach corresponding tag
    423             if (_font.Underline)
    424                 _doc.Append(@"ul");
    425             // Set the font to the first font in the font table.
    426             // See GetFontTable for more details.
    427             _doc.Append(@"f0");
    428             // Set the size of the font.  In RTF, font size is measured in
    429             // half-points, so the font size is twice the value obtained from
    430             // Font.SizeInPoints
    431             _doc.Append(@"fs");
    432             _doc.Append((int)Math.Round((2 * _font.SizeInPoints)));
    433             // Apppend a space before starting actual text (for clarity)
    434             _doc.Append(@" ");
    435             // Append actual text, however, replace newlines with RTF par.
    436             // Any other special text should be handled here (e.g.) tabs, etc.
    437             _doc.Append(_text.Replace("
    ", @"par "));
    438             // RTF isn't strict when it comes to closing control words, but what the
    439             // heck ...
    440             // Remove the highlight
    441             _doc.Append(@"highlight0");
    442             // If font is bold, close tag
    443             if (_font.Bold)
    444                 _doc.Append(@"0");
    445             // If font is italic, close tag
    446             if (_font.Italic)
    447                 _doc.Append(@"i0");
    448             // If font is strikeout, close tag
    449             if (_font.Strikeout)
    450                 _doc.Append(@"strike0");
    451             // If font is underlined, cloes tag
    452             if (_font.Underline)
    453                 _doc.Append(@"ulnone");
    454             // Revert back to default font and size
    455             _doc.Append(@"f0");
    456             _doc.Append(@"fs20");
    457             // Close the document area control string
    458             _doc.Append(RTF_DOCUMENT_POST);
    459             return _doc.ToString();
    460         }
    461         #endregion
    462         #region Insert Image
    463         /// <summary>
    464         /// Inserts an image into the RichTextBox.  The image is wrapped in a Windows
    465         /// Format Metafile, because although Microsoft discourages the use of a WMF,
    466         /// the RichTextBox (and even MS Word), wraps an image in a WMF before inserting
    467         /// the image into a document.  The WMF is attached in HEX format (a string of
    468         /// HEX numbers).
    469         /// 
    470         /// The RTF Specification v1.6 says that you should be able to insert bitmaps,
    471         /// .jpegs, .gifs, .pngs, and Enhanced Metafiles (.emf) directly into an RTF
    472         /// document without the WMF wrapper. This works fine with MS Word,
    473         /// however, when you don't wrap images in a WMF, WordPad and
    474         /// RichTextBoxes simply ignore them.  Both use the riched20.dll or msfted.dll.
    475         /// </summary>
    476         /// <remarks>
    477         /// NOTE: The image is inserted wherever the caret is at the time of the call,
    478         /// and if any text is selected, that text is replaced.
    479         /// </remarks>
    480         /// <param name="_image"></param>
    481         public void InsertImage(Image _image)
    482         {
    483             StringBuilder _rtf = new StringBuilder();
    484             // Append the RTF header
    485             _rtf.Append(RTF_HEADER);
    486             // Create the font table using the RichTextBox's current font and append
    487             // it to the RTF string
    488             _rtf.Append(GetFontTable(this.Font));
    489             // Create the image control string and append it to the RTF string
    490             _rtf.Append(GetImagePrefix(_image));
    491             // Create the Windows Metafile and append its bytes in HEX format
    492             _rtf.Append(GetRtfImage(_image));
    493             // Close the RTF image control string
    494             _rtf.Append(RTF_IMAGE_POST);
    495             this.SelectedRtf = _rtf.ToString();
    496         }
    497         /// <summary>
    498         /// Creates the RTF control string that describes the image being inserted.
    499         /// This description (in this case) specifies that the image is an
    500         /// MM_ANISOTROPIC metafile, meaning that both X and Y axes can be scaled
    501         /// independently.  The control string also gives the images current dimensions,
    502         /// and its target dimensions, so if you want to control the size of the
    503         /// image being inserted, this would be the place to do it. The prefix should
    504         /// have the form ...
    505         /// 
    506         /// {pictwmetafile8picw[A]pich[B]picwgoal[C]pichgoal[D]
    507         /// 
    508         /// where ...
    509         /// 
    510         /// A = current width of the metafile in hundredths of millimeters (0.01mm)
    511         ///  = Image Width in Inches * Number of (0.01mm) per inch
    512         ///  = (Image Width in Pixels / Graphics Context's Horizontal Resolution) * 2540
    513         ///  = (Image Width in Pixels / Graphics.DpiX) * 2540
    514         /// 
    515         /// B = current height of the metafile in hundredths of millimeters (0.01mm)
    516         ///  = Image Height in Inches * Number of (0.01mm) per inch
    517         ///  = (Image Height in Pixels / Graphics Context's Vertical Resolution) * 2540
    518         ///  = (Image Height in Pixels / Graphics.DpiX) * 2540
    519         /// 
    520         /// C = target width of the metafile in twips
    521         ///  = Image Width in Inches * Number of twips per inch
    522         ///  = (Image Width in Pixels / Graphics Context's Horizontal Resolution) * 1440
    523         ///  = (Image Width in Pixels / Graphics.DpiX) * 1440
    524         /// 
    525         /// D = target height of the metafile in twips
    526         ///  = Image Height in Inches * Number of twips per inch
    527         ///  = (Image Height in Pixels / Graphics Context's Horizontal Resolution) * 1440
    528         ///  = (Image Height in Pixels / Graphics.DpiX) * 1440
    529         /// 
    530         /// </summary>
    531         /// <remarks>
    532         /// The Graphics Context's resolution is simply the current resolution at which
    533         /// windows is being displayed.  Normally it's 96 dpi, but instead of assuming
    534         /// I just added the code.
    535         /// 
    536         /// According to Ken Howe at pbdr.com, "Twips are screen-independent units
    537         /// used to ensure that the placement and proportion of screen elements in
    538         /// your screen application are the same on all display systems."
    539         /// 
    540         /// Units Used
    541         /// ----------
    542         /// 1 Twip = 1/20 Point
    543         /// 1 Point = 1/72 Inch
    544         /// 1 Twip = 1/1440 Inch
    545         /// 
    546         /// 1 Inch = 2.54 cm
    547         /// 1 Inch = 25.4 mm
    548         /// 1 Inch = 2540 (0.01)mm
    549         /// </remarks>
    550         /// <param name="_image"></param>
    551         /// <returns></returns>
    552         private string GetImagePrefix(Image _image)
    553         {
    554             StringBuilder _rtf = new StringBuilder();
    555             // Calculate the current width of the image in (0.01)mm
    556             int picw = (int)Math.Round((_image.Width / xDpi) * HMM_PER_INCH);
    557             // Calculate the current height of the image in (0.01)mm
    558             int pich = (int)Math.Round((_image.Height / yDpi) * HMM_PER_INCH);
    559             // Calculate the target width of the image in twips
    560             int picwgoal = (int)Math.Round((_image.Width / xDpi) * TWIPS_PER_INCH);
    561             // Calculate the target height of the image in twips
    562             int pichgoal = (int)Math.Round((_image.Height / yDpi) * TWIPS_PER_INCH);
    563             // Append values to RTF string
    564             _rtf.Append(@"{pictwmetafile8");
    565             _rtf.Append(@"picw");
    566             _rtf.Append(picw);
    567             _rtf.Append(@"pich");
    568             _rtf.Append(pich);
    569             _rtf.Append(@"picwgoal");
    570             _rtf.Append(picwgoal);
    571             _rtf.Append(@"pichgoal");
    572             _rtf.Append(pichgoal);
    573             _rtf.Append(" ");
    574             return _rtf.ToString();
    575         }
    576         /// <summary>
    577         /// Use the EmfToWmfBits function in the GDI+ specification to convert a 
    578         /// Enhanced Metafile to a Windows Metafile
    579         /// </summary>
    580         /// <param name="_hEmf">
    581         /// A handle to the Enhanced Metafile to be converted
    582         /// </param>
    583         /// <param name="_bufferSize">
    584         /// The size of the buffer used to store the Windows Metafile bits returned
    585         /// </param>
    586         /// <param name="_buffer">
    587         /// An array of bytes used to hold the Windows Metafile bits returned
    588         /// </param>
    589         /// <param name="_mappingMode">
    590         /// The mapping mode of the image.  This control uses MM_ANISOTROPIC.
    591         /// </param>
    592         /// <param name="_flags">
    593         /// Flags used to specify the format of the Windows Metafile returned
    594         /// </param>
    595         [DllImportAttribute("gdiplus.dll")]
    596         private static extern uint GdipEmfToWmfBits(IntPtr _hEmf, uint _bufferSize,
    597             byte[] _buffer, int _mappingMode, EmfToWmfBitsFlags _flags);
    598 
    599         /// <summary>
    600         /// Wraps the image in an Enhanced Metafile by drawing the image onto the
    601         /// graphics context, then converts the Enhanced Metafile to a Windows
    602         /// Metafile, and finally appends the bits of the Windows Metafile in HEX
    603         /// to a string and returns the string.
    604         /// </summary>
    605         /// <param name="_image"></param>
    606         /// <returns>
    607         /// A string containing the bits of a Windows Metafile in HEX
    608         /// </returns>
    609         private string GetRtfImage(Image _image)
    610         {
    611             StringBuilder _rtf = null;
    612             // Used to store the enhanced metafile
    613             MemoryStream _stream = null;
    614             // Used to create the metafile and draw the image
    615             Graphics _graphics = null;
    616             // The enhanced metafile
    617             Metafile _metaFile = null;
    618             // Handle to the device context used to create the metafile
    619             IntPtr _hdc;
    620             try
    621             {
    622                 _rtf = new StringBuilder();
    623                 _stream = new MemoryStream();
    624                 // Get a graphics context from the RichTextBox
    625                 using (_graphics = this.CreateGraphics())
    626                 {
    627                     // Get the device context from the graphics context
    628                     _hdc = _graphics.GetHdc();
    629                     // Create a new Enhanced Metafile from the device context
    630                     _metaFile = new Metafile(_stream, _hdc);
    631                     // Release the device context
    632                     _graphics.ReleaseHdc(_hdc);
    633                 }
    634                 // Get a graphics context from the Enhanced Metafile
    635                 using (_graphics = Graphics.FromImage(_metaFile))
    636                 {
    637                     // Draw the image on the Enhanced Metafile
    638                     _graphics.DrawImage(_image, new Rectangle(0, 0, _image.Width, _image.Height));
    639                 }
    640                 // Get the handle of the Enhanced Metafile
    641                 IntPtr _hEmf = _metaFile.GetHenhmetafile();
    642                 // A call to EmfToWmfBits with a null buffer return the size of the
    643                 // buffer need to store the WMF bits.  Use this to get the buffer
    644                 // size.
    645                 uint _bufferSize = GdipEmfToWmfBits(_hEmf, 0, null, MM_ANISOTROPIC,
    646                     EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
    647                 // Create an array to hold the bits
    648                 byte[] _buffer = new byte[_bufferSize];
    649                 // A call to EmfToWmfBits with a valid buffer copies the bits into the
    650                 // buffer an returns the number of bits in the WMF.  
    651                 uint _convertedSize = GdipEmfToWmfBits(_hEmf, _bufferSize, _buffer, MM_ANISOTROPIC,
    652                     EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
    653                 // Append the bits to the RTF string
    654                 for (int i = 0; i < _buffer.Length; ++i)
    655                 {
    656                     _rtf.Append(String.Format("{0:X2}", _buffer[i]));
    657                 }
    658                 return _rtf.ToString();
    659             }
    660             finally
    661             {
    662                 if (_graphics != null)
    663                     _graphics.Dispose();
    664                 if (_metaFile != null)
    665                     _metaFile.Dispose();
    666                 if (_stream != null)
    667                     _stream.Close();
    668             }
    669         }
    670         #endregion
    671         #region RTF Helpers
    672         /// <summary>
    673         /// Creates a font table from a font object.  When an Insert or Append 
    674         /// operation is performed a font is either specified or the default font
    675         /// is used.  In any case, on any Insert or Append, only one font is used,
    676         /// thus the font table will always contain a single font.  The font table
    677         /// should have the form ...
    678         /// 
    679         /// {fonttbl{f0[FAMILY]fcharset0 [FONT_NAME];}
    680         /// </summary>
    681         /// <param name="_font"></param>
    682         /// <returns></returns>
    683         private string GetFontTable(Font _font)
    684         {
    685             StringBuilder _fontTable = new StringBuilder();
    686             // Append table control string
    687             _fontTable.Append(@"{fonttbl{f0");
    688             _fontTable.Append(@"");
    689             // If the font's family corresponds to an RTF family, append the
    690             // RTF family name, else, append the RTF for unknown font family.
    691             if (rtfFontFamily.Contains(_font.FontFamily.Name))
    692                 _fontTable.Append(rtfFontFamily[_font.FontFamily.Name]);
    693             else
    694                 _fontTable.Append(rtfFontFamily[FF_UNKNOWN]);
    695             // fcharset specifies the character set of a font in the font table.
    696             // 0 is for ANSI.
    697             _fontTable.Append(@"fcharset0 ");
    698             // Append the name of the font
    699             _fontTable.Append(_font.Name);
    700             // Close control string
    701             _fontTable.Append(@";}}");
    702             return _fontTable.ToString();
    703         }
    704         /// <summary>
    705         /// Creates a font table from the RtfColor structure.  When an Insert or Append
    706         /// operation is performed, _textColor and _backColor are either specified
    707         /// or the default is used.  In any case, on any Insert or Append, only three
    708         /// colors are used.  The default color of the RichTextBox (signified by a
    709         /// semicolon (;) without a definition), is always the first color (index 0) in
    710         /// the color table.  The second color is always the text color, and the third
    711         /// is always the highlight color (color behind the text).  The color table
    712         /// should have the form ...
    713         /// 
    714         /// {colortbl ;[TEXT_COLOR];[HIGHLIGHT_COLOR];}
    715         /// 
    716         /// </summary>
    717         /// <param name="_textColor"></param>
    718         /// <param name="_backColor"></param>
    719         /// <returns></returns>
    720         private string GetColorTable(RtfColor _textColor, RtfColor _backColor)
    721         {
    722             StringBuilder _colorTable = new StringBuilder();
    723             // Append color table control string and default font (;)
    724             _colorTable.Append(@"{colortbl ;");
    725             // Append the text color
    726             _colorTable.Append(rtfColor[_textColor]);
    727             _colorTable.Append(@";");
    728             // Append the highlight color
    729             _colorTable.Append(rtfColor[_backColor]);
    730             _colorTable.Append(@";}
    ");
    731             return _colorTable.ToString();
    732         }
    733         /// <summary>
    734         /// Called by overrided RichTextBox.Rtf accessor.
    735         /// Removes the null character from the RTF.  This is residue from developing
    736         /// the control for a specific instant messaging protocol and can be ommitted.
    737         /// </summary>
    738         /// <param name="_originalRtf"></param>
    739         /// <returns>RTF without null character</returns>
    740         private string RemoveBadChars(string _originalRtf)
    741         {
    742             return _originalRtf.Replace("", "");
    743         }
    744         #endregion
    745     }
    746 }
  • 相关阅读:
    SpringBoot整合Ehcache
    SpringCache整合Redis
    SpringBoot使用mongo搭建RESTful风格
    SpringBoot使用JPA搭建RESTful风格
    SpringBoot操作mongo的两种方法
    Nginx负载均衡
    【Java杂货铺】用Security做权限极简入门
    【Java杂货铺】JVM#虚拟机加载机制
    【Java杂货铺】JVM#Class类结构
    【Java杂货铺】JVM#Java高墙之GC与内存分配策略
  • 原文地址:https://www.cnblogs.com/endv/p/6161135.html
Copyright © 2020-2023  润新知