ChatRichTextBox : RichTextBox

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Text;
  4 using System.Windows.Forms;
  5 using System.Drawing;
  6 using ImageOleLib;
  7 using DynamicGifLib;
  8 using System.ComponentModel;
  9 using System.Runtime.InteropServices;
 10 using System.Diagnostics;
 11 
 12 namespace EmotionPanel
 13 { 
 14 
 15     public class ChatRichTextBox : RichTextBox
 16     {
 17 
 18         RichEditOle ole;
 19         private IRichEditOle _richEditOle;
 20         private Dictionary<int, REOBJECT> _oleObjectList;
 21         private int _index;
 22 
 23         #region Interop-Defines
 24         [StructLayout(LayoutKind.Sequential)]
 25         public struct CHARFORMAT2_STRUCT
 26         {
 27             public UInt32 cbSize;
 28             public UInt32 dwMask;
 29             public UInt32 dwEffects;
 30             public Int32 yHeight;
 31             public Int32 yOffset;
 32             public Int32 crTextColor;
 33             public byte bCharSet;
 34             public byte bPitchAndFamily;
 35             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
 36             public char[] szFaceName;
 37             public UInt16 wWeight;
 38             public UInt16 sSpacing;
 39             public int crBackColor; // Color.ToArgb() -> int
 40             public int lcid;
 41             public int dwReserved;
 42             public Int16 sStyle;
 43             public Int16 wKerning;
 44             public byte bUnderlineType;
 45             public byte bAnimation;
 46             public byte bRevAuthor;
 47             public byte bReserved1;
 48         }
 49 
 50         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 51         public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
 52 
 53         private const int WM_USER = 0x0400;
 54         private const int EM_GETCHARFORMAT = WM_USER + 58;
 55         public const int EM_SETCHARFORMAT = WM_USER + 68;
 56 
 57         public const int SCF_SELECTION = 0x0001;
 58         private const int SCF_WORD = 0x0002;
 59         private const int SCF_ALL = 0x0004;
 60 
 61         #region CHARFORMAT2 Flags
 62         private const UInt32 CFE_BOLD = 0x0001;
 63         private const UInt32 CFE_ITALIC = 0x0002;
 64         private const UInt32 CFE_UNDERLINE = 0x0004;
 65         private const UInt32 CFE_STRIKEOUT = 0x0008;
 66         private const UInt32 CFE_PROTECTED = 0x0010;
 67         public const UInt32 CFE_LINK = 0x0020;
 68         private const UInt32 CFE_AUTOCOLOR = 0x40000000;
 69         private const UInt32 CFE_SUBSCRIPT = 0x00010000;        /* Superscript and subscript are */
 70         private const UInt32 CFE_SUPERSCRIPT = 0x00020000;        /*  mutually exclusive             */
 71 
 72         private const int CFM_SMALLCAPS = 0x0040;            /* (*)    */
 73         private const int CFM_ALLCAPS = 0x0080;            /* Displayed by 3.0    */
 74         private const int CFM_HIDDEN = 0x0100;            /* Hidden by 3.0 */
 75         private const int CFM_OUTLINE = 0x0200;            /* (*)    */
 76         private const int CFM_SHADOW = 0x0400;            /* (*)    */
 77         private const int CFM_EMBOSS = 0x0800;            /* (*)    */
 78         private const int CFM_IMPRINT = 0x1000;            /* (*)    */
 79         private const int CFM_DISABLED = 0x2000;
 80         private const int CFM_REVISED = 0x4000;
 81 
 82         private const int CFM_BACKCOLOR = 0x04000000;
 83         private const int CFM_LCID = 0x02000000;
 84         private const int CFM_UNDERLINETYPE = 0x00800000;        /* Many displayed by 3.0 */
 85         private const int CFM_WEIGHT = 0x00400000;
 86         private const int CFM_SPACING = 0x00200000;        /* Displayed by 3.0    */
 87         private const int CFM_KERNING = 0x00100000;        /* (*)    */
 88         private const int CFM_STYLE = 0x00080000;        /* (*)    */
 89         private const int CFM_ANIMATION = 0x00040000;        /* (*)    */
 90         private const int CFM_REVAUTHOR = 0x00008000;
 91 
 92 
 93         private const UInt32 CFM_BOLD = 0x00000001;
 94         private const UInt32 CFM_ITALIC = 0x00000002;
 95         private const UInt32 CFM_UNDERLINE = 0x00000004;
 96         private const UInt32 CFM_STRIKEOUT = 0x00000008;
 97         private const UInt32 CFM_PROTECTED = 0x00000010;
 98         public const UInt32 CFM_LINK = 0x00000020;
 99         private const UInt32 CFM_SIZE = 0x80000000;
100         private const UInt32 CFM_COLOR = 0x40000000;
101         private const UInt32 CFM_FACE = 0x20000000;
102         private const UInt32 CFM_OFFSET = 0x10000000;
103         private const UInt32 CFM_CHARSET = 0x08000000;
104         private const UInt32 CFM_SUBSCRIPT = CFE_SUBSCRIPT | CFE_SUPERSCRIPT;
105         private const UInt32 CFM_SUPERSCRIPT = CFM_SUBSCRIPT;
106 
107         private const byte CFU_UNDERLINENONE = 0x00000000;
108         private const byte CFU_UNDERLINE = 0x00000001;
109         private const byte CFU_UNDERLINEWORD = 0x00000002; /* (*) displayed as ordinary underline    */
110         private const byte CFU_UNDERLINEDOUBLE = 0x00000003; /* (*) displayed as ordinary underline    */
111         private const byte CFU_UNDERLINEDOTTED = 0x00000004;
112         private const byte CFU_UNDERLINEDASH = 0x00000005;
113         private const byte CFU_UNDERLINEDASHDOT = 0x00000006;
114         private const byte CFU_UNDERLINEDASHDOTDOT = 0x00000007;
115         private const byte CFU_UNDERLINEWAVE = 0x00000008;
116         private const byte CFU_UNDERLINETHICK = 0x00000009;
117         private const byte CFU_UNDERLINEHAIRLINE = 0x0000000A; /* (*) displayed as ordinary underline    */
118 
119         #endregion
120 
121         #endregion
122      
123 
124         public ChatRichTextBox()
125             : base()
126         {
127             base.BorderStyle = BorderStyle.FixedSingle;
128             this.DetectUrls = false;
129         }
130 
131         public Dictionary<int, REOBJECT> OleObjectList
132         {
133             get
134             {
135                 if (_oleObjectList == null)
136                 {
137                     _oleObjectList = new Dictionary<int, REOBJECT>(10);
138                 }
139                 return _oleObjectList;
140             }
141         }
142 
143         internal RichEditOle RichEditOle
144         {
145             get
146             {
147                 if (ole == null)
148                 {
149                     if (base.IsHandleCreated)
150                     {
151                         ole = new RichEditOle(this);
152                     }
153                 }
154 
155                 return ole;
156             }
157         }
158 
159         public bool InsertImageUseImageOle(string path)
160         {
161             try
162             {
163                 IGifAnimator gif = new GifAnimatorClass();
164                 gif.LoadFromFile(path);
165                 gif.TriggerFrameChange();
166                 if (gif is IOleObject)
167                 {
168                     int index = _index ++;
169                     REOBJECT reObj = RichEditOle.InsertOleObject(
170                         (IOleObject)gif,
171                         index);
172                     RichEditOle.UpdateObjects(reObj.cp);
173                     OleObjectList.Add(index, reObj);
174                     return true;
175                 }
176                 return false;
177             }
178             catch (Exception)
179             {
180                 return false;
181             }
182         }
183 
184         public bool InsertImageUseDynamic(string path)
185         {
186             try
187             {
188                 IDynamicGif gif = new DynamicGifClass();
189                 gif.LoadFromFile(path);
190                 gif.Play();
191                 if (gif is IOleObject)
192                 {
193                     int index = _index++;
194                     REOBJECT reObj = RichEditOle.InsertOleObject(
195                         (IOleObject)gif,
196                         index);
197                     RichEditOle.UpdateObjects(reObj.cp);
198                     OleObjectList.Add(index, reObj);
199                     return true;
200                 }
201                 return false;
202             }
203             catch (Exception)
204             {
205                 return false;
206             }
207         }
208 
209         public bool InsertImageUseGifBox(Image path)
210         {
211             try
212             {
213                 GifBox gif = new GifBox();
214                 gif.BackColor = base.BackColor;
215                 gif.Image = path;
216                 RichEditOle.InsertControl(gif);
217                 return true;
218             }
219             catch (Exception)
220             {
221                 return false;
222             }
223         }
224 
225         public bool InsertImageUseGifBox(string path)
226         {
227             try
228             {
229                 GifBox gif = new GifBox();
230                 gif.BackColor = base.BackColor;
231                 gif.Image = Image.FromFile(path);
232                 RichEditOle.InsertControl(gif);
233                 return true;
234             }
235             catch (Exception)
236             {
237                 return false;
238             }
239         }
240 
241         [DefaultValue(false)]
242         public new bool DetectUrls
243         {
244             get { return base.DetectUrls; }
245             set { base.DetectUrls = value; }
246         }
247 
248         /// <summary>
249         /// Insert a given text as a link into the RichTextBox at the current insert position.
250         /// </summary>
251         /// <param name="text">Text to be inserted</param>
252         public void InsertLink(string text)
253         {
254             InsertLink(text, this.SelectionStart);
255         }
256 
257         /// <summary>
258         /// Insert a given text at a given position as a link. 
259         /// </summary>
260         /// <param name="text">Text to be inserted</param>
261         /// <param name="position">Insert position</param>
262         public void InsertLink(string text, int position)
263         {
264             if (position < 0 || position > this.Text.Length)
265                 throw new ArgumentOutOfRangeException("position");
266 
267             this.SelectionStart = position;
268             this.SelectedText = text;
269             this.Select(position, text.Length);
270             this.SetSelectionLink(true);
271             this.Select(position + text.Length, 0);
272         }
273 
274         /// <summary>
275         /// Insert a given text at at the current input position as a link.
276         /// The link text is followed by a hash (#) and the given hyperlink text, both of
277         /// them invisible.
278         /// When clicked on, the whole link text and hyperlink string are given in the
279         /// LinkClickedEventArgs.
280         /// </summary>
281         /// <param name="text">Text to be inserted</param>
282         /// <param name="hyperlink">Invisible hyperlink string to be inserted</param>
283         public void InsertLink(string text, string hyperlink)
284         {
285             InsertLink(text, hyperlink, this.SelectionStart);
286         }
287 
288         /// <summary>
289         /// Insert a given text at a given position as a link. The link text is followed by
290         /// a hash (#) and the given hyperlink text, both of them invisible.
291         /// When clicked on, the whole link text and hyperlink string are given in the
292         /// LinkClickedEventArgs.
293         /// </summary>
294         /// <param name="text">Text to be inserted</param>
295         /// <param name="hyperlink">Invisible hyperlink string to be inserted</param>
296         /// <param name="position">Insert position</param>
297         public void InsertLink(string text, string hyperlink, int position)
298         {
299             if (position < 0 || position > this.Text.Length)
300                 throw new ArgumentOutOfRangeException("position");
301 
302             this.SelectionStart = position;
303             //this.SelectedRtf = @"{
tf1ansi "+text+@"v #"+hyperlink+@"v0}";// 只能显示英文
304             this.SelectedRtf = @"{
tf1ansicpg936 " + text + @"v #" + hyperlink + @"v0}";  // 可以显示中文
305             this.Select(position, text.Length + hyperlink.Length + 1);
306             this.SetSelectionLink(true);
307             this.Select(position + text.Length + hyperlink.Length + 1, 0);
308         }
309 
310         /// <summary>
311         /// Set the current selection's link style
312         /// </summary>
313         /// <param name="link">true: set link style, false: clear link style</param>
314         public void SetSelectionLink(bool link)
315         {
316             SetSelectionStyle(CFM_LINK, link ? CFE_LINK : 0);
317         }
318         /// <summary>
319         /// Get the link style for the current selection
320         /// </summary>
321         /// <returns>0: link style not set, 1: link style set, -1: mixed</returns>
322         public int GetSelectionLink()
323         {
324             return GetSelectionStyle(CFM_LINK, CFE_LINK);
325         }
326 
327 
328         private void SetSelectionStyle(UInt32 mask, UInt32 effect)
329         {
330             CHARFORMAT2_STRUCT cf = new CHARFORMAT2_STRUCT();
331             cf.cbSize = (UInt32)Marshal.SizeOf(cf);
332             cf.dwMask = mask;
333             cf.dwEffects = effect;
334 
335             IntPtr wpar = new IntPtr(SCF_SELECTION);
336             IntPtr lpar = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
337             Marshal.StructureToPtr(cf, lpar, false);
338 
339             IntPtr res = SendMessage(Handle, EM_SETCHARFORMAT, wpar, lpar);
340 
341             Marshal.FreeCoTaskMem(lpar);
342         }
343 
344         private int GetSelectionStyle(UInt32 mask, UInt32 effect)
345         {
346             CHARFORMAT2_STRUCT cf = new CHARFORMAT2_STRUCT();
347             cf.cbSize = (UInt32)Marshal.SizeOf(cf);
348             cf.szFaceName = new char[32];
349 
350             IntPtr wpar = new IntPtr(SCF_SELECTION);
351             IntPtr lpar = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
352             Marshal.StructureToPtr(cf, lpar, false);
353 
354             IntPtr res = SendMessage(Handle, EM_GETCHARFORMAT, wpar, lpar);
355 
356             cf = (CHARFORMAT2_STRUCT)Marshal.PtrToStructure(lpar, typeof(CHARFORMAT2_STRUCT));
357 
358             int state;
359             // dwMask holds the information which properties are consistent throughout the selection:
360             if ((cf.dwMask & mask) == mask)
361             {
362                 if ((cf.dwEffects & effect) == effect)
363                     state = 1;
364                 else
365                     state = 0;
366             }
367             else
368             {
369                 state = -1;
370             }
371 
372             Marshal.FreeCoTaskMem(lpar);
373             return state;
374         }
375         ///////////////////////////////////////////
376         /////////////////////////////////////////////
377 
378         IRichEditOle richEditOle
379         {
380             get
381             {
382                 if (this._richEditOle == null)
383                 {
384                     IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
385                     IntPtr richEditOleIntPtr = IntPtr.Zero;
386                     Marshal.WriteIntPtr(ptr, IntPtr.Zero);
387                     try
388                     {
389                         int msgResult = (int)SendMessage(this.Handle, EmotionPanel.NativeMethods.EM_GETOLEINTERFACE, IntPtr.Zero, ptr);
390                         if (msgResult != 0)
391                         {
392                             IntPtr intPtr = Marshal.ReadIntPtr(ptr);
393                             try
394                             {
395                                 if (intPtr != IntPtr.Zero)
396                                 {
397                                     Guid guid = new Guid("00020D00-0000-0000-c000-000000000046");
398                                     Marshal.QueryInterface(intPtr, ref guid, out richEditOleIntPtr);
399 
400                                     this._richEditOle = (IRichEditOle)Marshal.GetTypedObjectForIUnknown(richEditOleIntPtr, typeof(IRichEditOle));
401                                 }
402                             }
403                             finally
404                             {
405                                 Marshal.Release(intPtr);
406                             }
407                         }
408                     }
409                     catch (Exception err)
410                     {
411                         Trace.WriteLine(err.ToString());
412                     }
413                     finally
414                     {
415                         Marshal.FreeCoTaskMem(ptr);
416                     }
417                 }
418                 return this._richEditOle;
419             }
420         }
421 
422         public new bool ReadOnly { get; set; }
423 
424         protected override void WndProc(ref Message m)
425         {
426             switch (m.Msg)
427             {
428                 case 0x0100:
429                     if (this.ReadOnly)
430                         return;
431                     break;
432                 case 0X0102:
433                     if (this.ReadOnly)
434                         return;
435                     break;
436                 default:
437                     break;
438             }
439             base.WndProc(ref m);
440         }
441 
442         List<MyGIF> gifList = new List<MyGIF>();
443         Panel gifPanel = new Panel();
444         public void ClearGif()
445         {
446             this.gifPanel.Controls.Clear();
447             this.gifList.Clear();
448         }
449 
450         public void InsertGIF(string Name, Image Data)
451         {
452 
453             MyGIF gif = new MyGIF(Name, Data);
454             gif.Box.Invalidate();
455             this.gifPanel.Controls.Add(gif.Box);
456             this.gifList.Add(gif);
457 
458             //RichEditOle ole = new RichEditOle(this);
459             ole.InsertControl(gif);
460 
461 
462             this.Invalidate();
463 
464 
465         }
466 
467         public string GetGIFInfo()
468         {
469             string imageInfo = "";
470             REOBJECT reObject = new REOBJECT();
471             for (int i = 0; i < this.richEditOle.GetObjectCount(); i++)
472             {
473                 this.richEditOle.GetObject(i, reObject, GETOBJECTOPTIONS.REO_GETOBJ_ALL_INTERFACES);
474                 MyGIF gif = this.gifList.Find(p => p != null && p.Index == reObject.dwUser);
475                 if (gif != null)
476                 {
477                     imageInfo += reObject.cp.ToString() + ":" + gif.Name + "|";
478                 }
479             }
480             return imageInfo;
481         }
482 
483         private void SetSelectionStyle()
484         {
485             CHARFORMAT2_STRUCT cf = new CHARFORMAT2_STRUCT();
486             cf.cbSize = (UInt32)Marshal.SizeOf(cf);
487             cf.dwMask = CFM_LINK;
488             cf.dwEffects = CFE_LINK;
489 
490             IntPtr wpar = new IntPtr(SCF_SELECTION);
491             IntPtr lpar = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
492             Marshal.StructureToPtr(cf, lpar, false);
493 
494             IntPtr res = (IntPtr)SendMessage(Handle, EM_SETCHARFORMAT, wpar, lpar);
495 
496             Marshal.FreeCoTaskMem(lpar);
497         }
498 
499         public void SetFont(string Name, bool Bold, bool Italic, bool Underline, Color Color, float Size)
500         {
501             FontStyle style = FontStyle.Regular;
502             if (Bold) style |= FontStyle.Bold;
503             if (Italic) style |= FontStyle.Italic;
504             if (Underline) style |= FontStyle.Underline;
505 
506             this.Font = new Font(Name, Size, style);
507             this.ForeColor = Color;
508         }
509 
510         public string GetTextToSend()
511         {
512             string value = string.Empty;
513             value += "\n" + this.Font.Name;
514             value += "\b" + (this.Font.Bold ? "1" : "0");
515             value += "\i" + (this.Font.Italic ? "1" : "0");
516             value += "\u" + (this.Font.Underline ? "1" : "0");
517             value += "\s" + this.Font.Size.ToString();
518             value += "\c" + ColorTranslator.ToHtml(this.ForeColor);
519             value += "\t" + this.Text;
520             value += "\p" + this.GetGIFInfo();
521 
522             return value;
523         }
524     }
525 }
原文地址:https://www.cnblogs.com/endv/p/6158177.html