using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using ImageOleLib;
using DynamicGifLib;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Diagnostics; namespace EmotionPanel
{ public class ChatRichTextBox : RichTextBox
{ RichEditOle ole;
private IRichEditOle _richEditOle;
private Dictionary<int, REOBJECT> _oleObjectList;
private int _index; #region Interop-Defines
[StructLayout(LayoutKind.Sequential)]
public struct CHARFORMAT2_STRUCT
{
public UInt32 cbSize;
public UInt32 dwMask;
public UInt32 dwEffects;
public Int32 yHeight;
public Int32 yOffset;
public Int32 crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = )]
public char[] szFaceName;
public UInt16 wWeight;
public UInt16 sSpacing;
public int crBackColor; // Color.ToArgb() -> int
public int lcid;
public int dwReserved;
public Int16 sStyle;
public Int16 wKerning;
public byte bUnderlineType;
public byte bAnimation;
public byte bRevAuthor;
public byte bReserved1;
} [DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); private const int WM_USER = 0x0400;
private const int EM_GETCHARFORMAT = WM_USER + ;
public const int EM_SETCHARFORMAT = WM_USER + ; public const int SCF_SELECTION = 0x0001;
private const int SCF_WORD = 0x0002;
private const int SCF_ALL = 0x0004; #region CHARFORMAT2 Flags
private const UInt32 CFE_BOLD = 0x0001;
private const UInt32 CFE_ITALIC = 0x0002;
private const UInt32 CFE_UNDERLINE = 0x0004;
private const UInt32 CFE_STRIKEOUT = 0x0008;
private const UInt32 CFE_PROTECTED = 0x0010;
public const UInt32 CFE_LINK = 0x0020;
private const UInt32 CFE_AUTOCOLOR = 0x40000000;
private const UInt32 CFE_SUBSCRIPT = 0x00010000; /* Superscript and subscript are */
private const UInt32 CFE_SUPERSCRIPT = 0x00020000; /* mutually exclusive */ private const int CFM_SMALLCAPS = 0x0040; /* (*) */
private const int CFM_ALLCAPS = 0x0080; /* Displayed by 3.0 */
private const int CFM_HIDDEN = 0x0100; /* Hidden by 3.0 */
private const int CFM_OUTLINE = 0x0200; /* (*) */
private const int CFM_SHADOW = 0x0400; /* (*) */
private const int CFM_EMBOSS = 0x0800; /* (*) */
private const int CFM_IMPRINT = 0x1000; /* (*) */
private const int CFM_DISABLED = 0x2000;
private const int CFM_REVISED = 0x4000; private const int CFM_BACKCOLOR = 0x04000000;
private const int CFM_LCID = 0x02000000;
private const int CFM_UNDERLINETYPE = 0x00800000; /* Many displayed by 3.0 */
private const int CFM_WEIGHT = 0x00400000;
private const int CFM_SPACING = 0x00200000; /* Displayed by 3.0 */
private const int CFM_KERNING = 0x00100000; /* (*) */
private const int CFM_STYLE = 0x00080000; /* (*) */
private const int CFM_ANIMATION = 0x00040000; /* (*) */
private const int CFM_REVAUTHOR = 0x00008000; private const UInt32 CFM_BOLD = 0x00000001;
private const UInt32 CFM_ITALIC = 0x00000002;
private const UInt32 CFM_UNDERLINE = 0x00000004;
private const UInt32 CFM_STRIKEOUT = 0x00000008;
private const UInt32 CFM_PROTECTED = 0x00000010;
public const UInt32 CFM_LINK = 0x00000020;
private const UInt32 CFM_SIZE = 0x80000000;
private const UInt32 CFM_COLOR = 0x40000000;
private const UInt32 CFM_FACE = 0x20000000;
private const UInt32 CFM_OFFSET = 0x10000000;
private const UInt32 CFM_CHARSET = 0x08000000;
private const UInt32 CFM_SUBSCRIPT = CFE_SUBSCRIPT | CFE_SUPERSCRIPT;
private const UInt32 CFM_SUPERSCRIPT = CFM_SUBSCRIPT; private const byte CFU_UNDERLINENONE = 0x00000000;
private const byte CFU_UNDERLINE = 0x00000001;
private const byte CFU_UNDERLINEWORD = 0x00000002; /* (*) displayed as ordinary underline */
private const byte CFU_UNDERLINEDOUBLE = 0x00000003; /* (*) displayed as ordinary underline */
private const byte CFU_UNDERLINEDOTTED = 0x00000004;
private const byte CFU_UNDERLINEDASH = 0x00000005;
private const byte CFU_UNDERLINEDASHDOT = 0x00000006;
private const byte CFU_UNDERLINEDASHDOTDOT = 0x00000007;
private const byte CFU_UNDERLINEWAVE = 0x00000008;
private const byte CFU_UNDERLINETHICK = 0x00000009;
private const byte CFU_UNDERLINEHAIRLINE = 0x0000000A; /* (*) displayed as ordinary underline */ #endregion #endregion public ChatRichTextBox()
: base()
{
base.BorderStyle = BorderStyle.FixedSingle;
this.DetectUrls = false;
} public Dictionary<int, REOBJECT> OleObjectList
{
get
{
if (_oleObjectList == null)
{
_oleObjectList = new Dictionary<int, REOBJECT>();
}
return _oleObjectList;
}
} internal RichEditOle RichEditOle
{
get
{
if (ole == null)
{
if (base.IsHandleCreated)
{
ole = new RichEditOle(this);
}
} return ole;
}
} public bool InsertImageUseImageOle(string path)
{
try
{
IGifAnimator gif = new GifAnimatorClass();
gif.LoadFromFile(path);
gif.TriggerFrameChange();
if (gif is IOleObject)
{
int index = _index ++;
REOBJECT reObj = RichEditOle.InsertOleObject(
(IOleObject)gif,
index);
RichEditOle.UpdateObjects(reObj.cp);
OleObjectList.Add(index, reObj);
return true;
}
return false;
}
catch (Exception)
{
return false;
}
} public bool InsertImageUseDynamic(string path)
{
try
{
IDynamicGif gif = new DynamicGifClass();
gif.LoadFromFile(path);
gif.Play();
if (gif is IOleObject)
{
int index = _index++;
REOBJECT reObj = RichEditOle.InsertOleObject(
(IOleObject)gif,
index);
RichEditOle.UpdateObjects(reObj.cp);
OleObjectList.Add(index, reObj);
return true;
}
return false;
}
catch (Exception)
{
return false;
}
} public bool InsertImageUseGifBox(Image path)
{
try
{
GifBox gif = new GifBox();
gif.BackColor = base.BackColor;
gif.Image = path;
RichEditOle.InsertControl(gif);
return true;
}
catch (Exception)
{
return false;
}
} public bool InsertImageUseGifBox(string path)
{
try
{
GifBox gif = new GifBox();
gif.BackColor = base.BackColor;
gif.Image = Image.FromFile(path);
RichEditOle.InsertControl(gif);
return true;
}
catch (Exception)
{
return false;
}
} [DefaultValue(false)]
public new bool DetectUrls
{
get { return base.DetectUrls; }
set { base.DetectUrls = value; }
} /// <summary>
/// Insert a given text as a link into the RichTextBox at the current insert position.
/// </summary>
/// <param name="text">Text to be inserted</param>
public void InsertLink(string text)
{
InsertLink(text, this.SelectionStart);
} /// <summary>
/// Insert a given text at a given position as a link.
/// </summary>
/// <param name="text">Text to be inserted</param>
/// <param name="position">Insert position</param>
public void InsertLink(string text, int position)
{
if (position < || position > this.Text.Length)
throw new ArgumentOutOfRangeException("position"); this.SelectionStart = position;
this.SelectedText = text;
this.Select(position, text.Length);
this.SetSelectionLink(true);
this.Select(position + text.Length, );
} /// <summary>
/// Insert a given text at at the current input position as a link.
/// The link text is followed by a hash (#) and the given hyperlink text, both of
/// them invisible.
/// When clicked on, the whole link text and hyperlink string are given in the
/// LinkClickedEventArgs.
/// </summary>
/// <param name="text">Text to be inserted</param>
/// <param name="hyperlink">Invisible hyperlink string to be inserted</param>
public void InsertLink(string text, string hyperlink)
{
InsertLink(text, hyperlink, this.SelectionStart);
} /// <summary>
/// Insert a given text at a given position as a link. The link text is followed by
/// a hash (#) and the given hyperlink text, both of them invisible.
/// When clicked on, the whole link text and hyperlink string are given in the
/// LinkClickedEventArgs.
/// </summary>
/// <param name="text">Text to be inserted</param>
/// <param name="hyperlink">Invisible hyperlink string to be inserted</param>
/// <param name="position">Insert position</param>
public void InsertLink(string text, string hyperlink, int position)
{
if (position < || position > this.Text.Length)
throw new ArgumentOutOfRangeException("position"); this.SelectionStart = position;
//this.SelectedRtf = @"{\rtf1\ansi "+text+@"\v #"+hyperlink+@"\v0}";// 只能显示英文
this.SelectedRtf = @"{\rtf1\ansi\cpg936 " + text + @"\v #" + hyperlink + @"\v0}"; // 可以显示中文
this.Select(position, text.Length + hyperlink.Length + );
this.SetSelectionLink(true);
this.Select(position + text.Length + hyperlink.Length + , );
} /// <summary>
/// Set the current selection's link style
/// </summary>
/// <param name="link">true: set link style, false: clear link style</param>
public void SetSelectionLink(bool link)
{
SetSelectionStyle(CFM_LINK, link ? CFE_LINK : );
}
/// <summary>
/// Get the link style for the current selection
/// </summary>
/// <returns>0: link style not set, 1: link style set, -1: mixed</returns>
public int GetSelectionLink()
{
return GetSelectionStyle(CFM_LINK, CFE_LINK);
} private void SetSelectionStyle(UInt32 mask, UInt32 effect)
{
CHARFORMAT2_STRUCT cf = new CHARFORMAT2_STRUCT();
cf.cbSize = (UInt32)Marshal.SizeOf(cf);
cf.dwMask = mask;
cf.dwEffects = effect; IntPtr wpar = new IntPtr(SCF_SELECTION);
IntPtr lpar = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
Marshal.StructureToPtr(cf, lpar, false); IntPtr res = SendMessage(Handle, EM_SETCHARFORMAT, wpar, lpar); Marshal.FreeCoTaskMem(lpar);
} private int GetSelectionStyle(UInt32 mask, UInt32 effect)
{
CHARFORMAT2_STRUCT cf = new CHARFORMAT2_STRUCT();
cf.cbSize = (UInt32)Marshal.SizeOf(cf);
cf.szFaceName = new char[]; IntPtr wpar = new IntPtr(SCF_SELECTION);
IntPtr lpar = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
Marshal.StructureToPtr(cf, lpar, false); IntPtr res = SendMessage(Handle, EM_GETCHARFORMAT, wpar, lpar); cf = (CHARFORMAT2_STRUCT)Marshal.PtrToStructure(lpar, typeof(CHARFORMAT2_STRUCT)); int state;
// dwMask holds the information which properties are consistent throughout the selection:
if ((cf.dwMask & mask) == mask)
{
if ((cf.dwEffects & effect) == effect)
state = ;
else
state = ;
}
else
{
state = -;
} Marshal.FreeCoTaskMem(lpar);
return state;
}
///////////////////////////////////////////
///////////////////////////////////////////// IRichEditOle richEditOle
{
get
{
if (this._richEditOle == null)
{
IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
IntPtr richEditOleIntPtr = IntPtr.Zero;
Marshal.WriteIntPtr(ptr, IntPtr.Zero);
try
{
int msgResult = (int)SendMessage(this.Handle, EmotionPanel.NativeMethods.EM_GETOLEINTERFACE, IntPtr.Zero, ptr);
if (msgResult != )
{
IntPtr intPtr = Marshal.ReadIntPtr(ptr);
try
{
if (intPtr != IntPtr.Zero)
{
Guid guid = new Guid("00020D00-0000-0000-c000-000000000046");
Marshal.QueryInterface(intPtr, ref guid, out richEditOleIntPtr); this._richEditOle = (IRichEditOle)Marshal.GetTypedObjectForIUnknown(richEditOleIntPtr, typeof(IRichEditOle));
}
}
finally
{
Marshal.Release(intPtr);
}
}
}
catch (Exception err)
{
Trace.WriteLine(err.ToString());
}
finally
{
Marshal.FreeCoTaskMem(ptr);
}
}
return this._richEditOle;
}
} public new bool ReadOnly { get; set; } protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x0100:
if (this.ReadOnly)
return;
break;
case 0X0102:
if (this.ReadOnly)
return;
break;
default:
break;
}
base.WndProc(ref m);
} List<MyGIF> gifList = new List<MyGIF>();
Panel gifPanel = new Panel();
public void ClearGif()
{
this.gifPanel.Controls.Clear();
this.gifList.Clear();
} public void InsertGIF(string Name, Image Data)
{ MyGIF gif = new MyGIF(Name, Data);
gif.Box.Invalidate();
this.gifPanel.Controls.Add(gif.Box);
this.gifList.Add(gif); //RichEditOle ole = new RichEditOle(this);
ole.InsertControl(gif); this.Invalidate(); } public string GetGIFInfo()
{
string imageInfo = "";
REOBJECT reObject = new REOBJECT();
for (int i = ; i < this.richEditOle.GetObjectCount(); i++)
{
this.richEditOle.GetObject(i, reObject, GETOBJECTOPTIONS.REO_GETOBJ_ALL_INTERFACES);
MyGIF gif = this.gifList.Find(p => p != null && p.Index == reObject.dwUser);
if (gif != null)
{
imageInfo += reObject.cp.ToString() + ":" + gif.Name + "|";
}
}
return imageInfo;
} private void SetSelectionStyle()
{
CHARFORMAT2_STRUCT cf = new CHARFORMAT2_STRUCT();
cf.cbSize = (UInt32)Marshal.SizeOf(cf);
cf.dwMask = CFM_LINK;
cf.dwEffects = CFE_LINK; IntPtr wpar = new IntPtr(SCF_SELECTION);
IntPtr lpar = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
Marshal.StructureToPtr(cf, lpar, false); IntPtr res = (IntPtr)SendMessage(Handle, EM_SETCHARFORMAT, wpar, lpar); Marshal.FreeCoTaskMem(lpar);
} public void SetFont(string Name, bool Bold, bool Italic, bool Underline, Color Color, float Size)
{
FontStyle style = FontStyle.Regular;
if (Bold) style |= FontStyle.Bold;
if (Italic) style |= FontStyle.Italic;
if (Underline) style |= FontStyle.Underline; this.Font = new Font(Name, Size, style);
this.ForeColor = Color;
} public string GetTextToSend()
{
string value = string.Empty;
value += "\\n" + this.Font.Name;
value += "\\b" + (this.Font.Bold ? "" : "");
value += "\\i" + (this.Font.Italic ? "" : "");
value += "\\u" + (this.Font.Underline ? "" : "");
value += "\\s" + this.Font.Size.ToString();
value += "\\c" + ColorTranslator.ToHtml(this.ForeColor);
value += "\\t" + this.Text;
value += "\\p" + this.GetGIFInfo(); return value;
}
}
}
05-07 15:13