using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace ryControls.Controls
{
    /// <summary>
    /// 增强富文本控件
    /// </summary>
    public partial class RichTextBox2 : RichTextBox
    {
        /// <summary>
        /// 开始更新
        /// </summary>
        public void BeginUpdate()
        {
            SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero);
        }
        /// <summary>
        /// 结束更新
        /// </summary>
        public void EndUpdate()
        {
            SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
            this.Invalidate();
        }
        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
        private const int WM_SETREDRAW = 0x0b;
        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, ref Rectangle lParam);//
        private const int EM_SETRECT = 0x00b3;
        /// <summary>
        /// RichTextBox
        /// </summary>
        public RichTextBox2():base()
        {
            //this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); this.UpdateStyles();
            InitializeComponent();
            this.DetectUrls = false;
            this.AutoWordSelection = false;
            this.Multiline = true;
            this.WordWrap = false;
            this.Font = new Font("Courier New",10, FontStyle.Regular);
            //this.contextMenuStripRichText1.Opening += ContextMenuStripRichText1_Opening;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            if (this.DesignMode) return;

            // The following operations should not recreate the handle
                // Workaround for .NET bug:
                // AutoWordSelection remembers the value of the property
                // correctly, but incorrectly sends a message as follows:
                //   SendMessage(EM_SETOPTIONS, value ? ECOOP_OR : ECOOP_XOR,
                //       ECO_AUTOWORDSELECTION);
                // So, when setting AutoWordSelection to false, the control
                // style is toggled instead of turned off (the internal value
                // is updated correctly)
                bool bAutoWord = this.AutoWordSelection; // Internal, no message
                if (!bAutoWord) // Only 'false' needs workaround
                {
                    // Ensure control style is on (currently we're in a
                    // random state, as it could be set to false multiple
                    // times; e.g. base.OnHandleCreated does the following:
                    // 'this.AutoWordSelection = this.AutoWordSelection;')
                    this.AutoWordSelection = true;

                    // Toggle control style to false
                    this.AutoWordSelection = false;
                    Rectangle rect2 = new Rectangle(this.ClientRectangle.Left + 7, this.ClientRectangle.Top + 5, this.ClientRectangle.Width - 14, this.ClientRectangle.Height - 10);
                    SendMessage(this.Handle, EM_SETRECT, IntPtr.Zero, ref rect2);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnHScroll(EventArgs e)
        {
            base.Invalidate();
            base.OnHScroll(e);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnVScroll(EventArgs e)
        {
            base.Invalidate();
            base.OnVScroll(e);
        }
        /// <summary>
        /// 在自带菜单弹出前激发
        /// </summary>
        [Description("在自带菜单弹出前激发")]
        public event CancelEventHandler OnMenuOpening;
        private void ContextMenuStripRichText1_Opening(object sender, CancelEventArgs e)
        {
            OnMenuOpening?.Invoke(sender,e);
        }
        /// <summary>
        /// 根据标签获得菜单项
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        public ToolStripItem GetMenuItem(string tag)
        {
            for (int i = 0; i < contextMenuStripRichText1.Items.Count; i++)
            {
                var item = contextMenuStripRichText1.Items[i];
                if (item.Tag == null) { continue; }
                if(tag== item.Tag.ToString())
                {
                    return item;
                }   
            }
            return null;
        }
        /// <summary>
        /// 只允许输入文本(只对设置之后的人工输入有效)
        /// </summary>
        [Description("只允许输入文本(只对设置之后的人工输入有效)")]
        public bool OnlyInputText { get; set; } = false;
        /// <summary>
        /// 按下按键
        /// </summary>
        /// <param name="e"></param>
        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (OnlyInputText && e.Control && e.KeyCode == Keys.V)
            {
                e.SuppressKeyPress = true;
                this.Paste(DataFormats.GetFormat(DataFormats.Text));
                return;
            }
            base.OnKeyDown(e);
        }
       /// <summary>
       /// 
       /// </summary>
       /// <param name="e"></param>
        protected override void OnLostFocus(EventArgs e)
        {
            base.Invalidate();
            base.OnLostFocus(e);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnEnter(EventArgs e)
        {
            if (base.Text.Length == 0)
            {
                base.Invalidate();
            }
            base.OnEnter(e);
        }
        //private bool _Selecting = false;
        //private int _StartPosition = 0;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
        {
            //if (_Selecting)
            //{
            //    int charPosition = base.GetCharIndexFromPosition(new System.Drawing.Point(e.X, e.Y));
            //    int length = 0;
            //    if (charPosition >= _StartPosition)
            //    {
            //        length = charPosition - _StartPosition + 1;
            //        this.Select(_StartPosition, length);
            //    }
            //    else
            //    {
            //        length = _StartPosition - charPosition;
            //        this.Select(charPosition, length);
            //    }
            //}

            base.OnMouseMove(e);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeave(EventArgs e)
        {
            if (base.Text.Length == 0)
            {
                base.Invalidate();
            }
            base.OnMouseLeave(e);
        }
        /// <summary>
        /// 鼠标按下
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            //this._Selecting = true;
            //_StartPosition = base.GetCharIndexFromPosition(new System.Drawing.Point(e.X, e.Y));
            if (e.Button==MouseButtons.Right && this.ContextMenuStrip==null)
            {
                contextMenuStripRichText1.Show(this, e.Location);
            }
            base.OnMouseDown(e);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
        {
            //this._Selecting = false;
            base.OnMouseUp(e);
        }
        private const UInt32 WM_USER = 0x0400;
        private const UInt32 EM_SETBKGNDCOLOR = (WM_USER + 67);
        private const UInt32 WM_KILLFOCUS = 0x0008;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == 0xf || m.Msg == 0x133)
            {
                if (this.BorderStyle == BorderStyle.None)
                {
                    System.Drawing.Pen pen = new Pen(SkinHelp.DefalutBorderColor, 1);
                    Graphics g = Graphics.FromHwnd(m.HWnd);
                    g.DrawRectangle(pen, 0, 0, this.Width - 1, this.Height - 1);
                    pen.Dispose();
                    //m.Result = IntPtr.Zero;
                }
                if(!base.Focused && this.Text.Length==0)
                {
                    Graphics g = Graphics.FromHwnd(m.HWnd);
                    Brush brush = new SolidBrush(Color.FromArgb(175, 185, 200)); 
                    g.DrawString(EmptyText,Font, brush, 3, 7);
                    brush.Dispose();
                }
                //返回结果
                m.Result = IntPtr.Zero;
            }
            if (m.Msg == EM_SETBKGNDCOLOR) //color disabled background
            {
                Invalidate();
            }

            if (m.Msg == WM_KILLFOCUS) //set border back to normal on lost focus
            {
                Invalidate();
            }
            
        }
        /// <summary>
        /// 当文本框为空时,显示的内容。
        /// </summary>
        [Description("当文本框为空时,显示的内容。")]
        public string EmptyText
        {
            get { return _EmptyText; }
            set
            {
                _EmptyText = value;
                base.Invalidate();
            }
        }
        private string _EmptyText = "";
        /// <summary>
        /// 添加菜单分隔线
        /// </summary>
        /// <returns></returns>
        public ToolStripSeparator AddSeparatorMenu()
        {
            return contextMenuStripRichText1.AddSeparatorMenu();
        }
        /// <summary>
        /// 添加菜单
        /// </summary>
        /// <param name="name"></param>
        /// <param name="tag"></param>
        /// <returns></returns>
        public ToolStripMenuItem AddMenu(string name, string tag)
        {
            return contextMenuStripRichText1.AddMenu(name, tag);
        }
    }
}
